]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 9 May 2007 20:38:45 +0000 (13:38 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 9 May 2007 20:38:45 +0000 (13:38 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
  [IA64] wire up pselect, ppoll
  [IA64] Add TIF_RESTORE_SIGMASK
  [IA64] unwind did not work for processes born with CLONE_STOPPED
  [IA64] Optional method to purge the TLB on SN systems
  [IA64] SPIN_LOCK_UNLOCKED macro cleanup in arch/ia64
  [IA64-SN2][KJ] mmtimer.c-kzalloc
  [IA64] fix stack alignment for ia32 signal handlers
  [IA64] - Altix: hotplug after intr redirect can crash system
  [IA64] save and restore cpus_allowed in cpu_idle_wait
  [IA64] Removal of percpu TR cleanup in kexec code
  [IA64] Fix some section mismatch errors

2217 files changed:
CREDITS
Documentation/ABI/removed/devfs
Documentation/CodingStyle
Documentation/DocBook/Makefile
Documentation/DocBook/kernel-api.tmpl
Documentation/DocBook/librs.tmpl
Documentation/MSI-HOWTO.txt
Documentation/SubmitChecklist
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
Documentation/accounting/getdelays.c
Documentation/arm/Interrupts
Documentation/arm/Samsung-S3C24XX/H1940.txt
Documentation/auxdisplay/cfag12864b
Documentation/binfmt_misc.txt
Documentation/block/ioprio.txt
Documentation/cciss.txt
Documentation/cpu-freq/cpufreq-stats.txt
Documentation/cpu-hotplug.txt
Documentation/crypto/api-intro.txt
Documentation/device-mapper/delay.txt [new file with mode: 0644]
Documentation/driver-model/platform.txt
Documentation/dvb/README.dvb-usb
Documentation/dvb/contributors.txt
Documentation/fb/arkfb.txt [new file with mode: 0644]
Documentation/fb/aty128fb.txt
Documentation/fb/deferred_io.txt [new file with mode: 0644]
Documentation/fb/framebuffer.txt
Documentation/fb/imacfb.txt
Documentation/fb/s3fb.txt
Documentation/fb/sstfb.txt
Documentation/fb/vt8623fb.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/Locking
Documentation/filesystems/hpfs.txt
Documentation/filesystems/jfs.txt
Documentation/filesystems/ntfs.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/relay.txt
Documentation/filesystems/vfat.txt
Documentation/filesystems/vfs.txt
Documentation/filesystems/xip.txt
Documentation/fujitsu/frv/gdbstub.txt
Documentation/hwmon/adm1026
Documentation/hwmon/coretemp [new file with mode: 0644]
Documentation/hwmon/gl518sm
Documentation/hwmon/lm83
Documentation/hwmon/max6650 [new file with mode: 0644]
Documentation/hwmon/sis5595
Documentation/hwmon/smsc47m1
Documentation/hwmon/smsc47m192
Documentation/hwmon/sysfs-interface
Documentation/hwmon/via686a
Documentation/hwmon/w83792d
Documentation/i2c/busses/i2c-i810
Documentation/i2c/busses/i2c-sis96x
Documentation/i2c/busses/i2c-via
Documentation/i2c/busses/i2c-viapro
Documentation/i2c/i2c-protocol
Documentation/i2o/README
Documentation/i386/boot.txt
Documentation/input/atarikbd.txt
Documentation/input/xpad.txt
Documentation/ioctl-number.txt
Documentation/isdn/CREDITS
Documentation/isdn/README
Documentation/isdn/README.icn
Documentation/java.txt
Documentation/kernel-docs.txt
Documentation/kernel-parameters.txt
Documentation/kprobes.txt
Documentation/laptop-mode.txt
Documentation/m68k/README.buddha
Documentation/magic-number.txt
Documentation/md.txt
Documentation/netlabel/introduction.txt
Documentation/networking/6pack.txt
Documentation/networking/NAPI_HOWTO.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/slicecom.hun
Documentation/networking/slicecom.txt
Documentation/networking/tms380tr.txt
Documentation/networking/udplite.txt
Documentation/networking/wan-router.txt
Documentation/oops-tracing.txt
Documentation/pci.txt
Documentation/pcieaer-howto.txt
Documentation/pnp.txt
Documentation/power/basic-pm-debugging.txt [new file with mode: 0644]
Documentation/power/drivers-testing.txt [new file with mode: 0644]
Documentation/power/swsusp.txt
Documentation/power/userland-swsusp.txt
Documentation/powerpc/booting-without-of.txt
Documentation/rtc.txt
Documentation/s390/Debugging390.txt
Documentation/scsi/aacraid.txt
Documentation/scsi/aha152x.txt
Documentation/scsi/aic7xxx.txt
Documentation/scsi/aic7xxx_old.txt
Documentation/scsi/ncr53c8xx.txt
Documentation/scsi/st.txt
Documentation/scsi/sym53c8xx_2.txt
Documentation/scsi/tmscsim.txt
Documentation/sonypi.txt
Documentation/sound/oss/mwave
Documentation/spi/spi-summary
Documentation/spi/spidev [new file with mode: 0644]
Documentation/sysctl/kernel.txt
Documentation/tty.txt
Documentation/usb/CREDITS
Documentation/usb/usb-serial.txt
Documentation/video4linux/README.pvrusb2
Documentation/video4linux/Zoran
Documentation/video4linux/meye.txt
Documentation/video4linux/ov511.txt
Documentation/vm/slabinfo.c
MAINTAINERS
arch/alpha/Kconfig.debug
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/srmcons.c
arch/alpha/mm/fault.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/init_task.c
arch/arm/kernel/module.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-aaec2000/core.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-clps711x/time.c
arch/arm/mach-clps7500/core.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/isa-timer.c
arch/arm/mach-h720x/cpu-h7201.c
arch/arm/mach-h720x/cpu-h7202.c
arch/arm/mach-imx/time.c
arch/arm/mach-integrator/core.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-lh7a40x/time.c
arch/arm/mach-netx/time.c
arch/arm/mach-ns9xxx/time.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/board-fsample.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-perseus2.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/io.c
arch/arm/mach-omap1/mailbox.c [new file with mode: 0644]
arch/arm/mach-omap1/time.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mailbox.c [new file with mode: 0644]
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-pnx4008/time.c
arch/arm/mach-pxa/time.c
arch/arm/mach-realview/core.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/time.c
arch/arm/mach-shark/core.c
arch/arm/mach-versatile/core.c
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/abort-ev7.S [new file with mode: 0644]
arch/arm/mm/cache-v7.S [new file with mode: 0644]
arch/arm/mm/context.c
arch/arm/mm/fault.c
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-v7.S [new file with mode: 0644]
arch/arm/plat-iop/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/debug-leds.c [new file with mode: 0644]
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mailbox.c [new file with mode: 0644]
arch/arm/plat-omap/mailbox.h [new file with mode: 0644]
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/timer32k.c
arch/arm/plat-omap/usb.c
arch/arm/plat-s3c24xx/sleep.S
arch/arm/plat-s3c24xx/time.c
arch/arm26/kernel/armksyms.c
arch/arm26/kernel/ptrace.c
arch/arm26/kernel/signal.c
arch/arm26/mm/memc.c
arch/avr32/Makefile
arch/avr32/kernel/kprobes.c
arch/avr32/kernel/process.c
arch/avr32/kernel/ptrace.c
arch/avr32/kernel/syscall_table.S
arch/avr32/kernel/traps.c
arch/avr32/kernel/vmlinux.lds.c
arch/avr32/mach-at32ap/clock.c
arch/avr32/mm/dma-coherent.c
arch/avr32/mm/fault.c
arch/blackfin/kernel/asm-offsets.c
arch/blackfin/kernel/ptrace.c
arch/cris/arch-v10/kernel/ptrace.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/pci/dma.c
arch/cris/arch-v32/kernel/ptrace.c
arch/cris/kernel/crisksyms.c
arch/cris/kernel/ptrace.c
arch/frv/Kconfig
arch/frv/kernel/entry.S
arch/frv/kernel/irq.c
arch/frv/kernel/process.c
arch/frv/kernel/ptrace.c
arch/frv/kernel/semaphore.c
arch/frv/kernel/setup.c
arch/frv/kernel/signal.c
arch/frv/kernel/sys_frv.c
arch/frv/mm/elf-fdpic.c
arch/frv/mm/pgalloc.c
arch/h8300/Kconfig.debug
arch/h8300/kernel/asm-offsets.c
arch/h8300/kernel/ptrace.c
arch/h8300/kernel/sys_h8300.c
arch/i386/Kconfig
arch/i386/Kconfig.cpu
arch/i386/kernel/Makefile
arch/i386/kernel/apic.c
arch/i386/kernel/apm.c
arch/i386/kernel/cpu/intel_cacheinfo.c
arch/i386/kernel/cpu/mcheck/therm_throt.c
arch/i386/kernel/cpu/transmeta.c
arch/i386/kernel/cpuid.c
arch/i386/kernel/crash.c
arch/i386/kernel/efi.c
arch/i386/kernel/i8259.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/ioport.c
arch/i386/kernel/kprobes.c
arch/i386/kernel/ldt.c
arch/i386/kernel/legacy_serial.c [new file with mode: 0644]
arch/i386/kernel/microcode.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/msr.c
arch/i386/kernel/nmi.c
arch/i386/kernel/pci-dma.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/signal.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/sys_i386.c
arch/i386/kernel/syscall_table.S
arch/i386/kernel/traps.c
arch/i386/kernel/vm86.c
arch/i386/lib/msr-on-cpu.c
arch/i386/mach-default/setup.c
arch/i386/mach-generic/probe.c
arch/i386/mach-visws/setup.c
arch/i386/mach-visws/visws_apic.c
arch/i386/mach-voyager/setup.c
arch/i386/mach-voyager/voyager_basic.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mach-voyager/voyager_thread.c
arch/i386/mm/fault.c
arch/i386/mm/hugetlbpage.c
arch/i386/mm/init.c
arch/i386/oprofile/nmi_int.c
arch/i386/oprofile/nmi_timer_int.c
arch/i386/pci/init.c
arch/ia64/Kconfig
arch/ia64/hp/sim/boot/fw-emu.c
arch/ia64/ia32/ia32_ldt.c
arch/ia64/ia32/ia32_signal.c
arch/ia64/ia32/ia32_support.c
arch/ia64/kernel/crash.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/err_inject.c
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/process.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/signal.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/sys_ia64.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/ia64/kernel/traps.c
arch/ia64/kernel/unaligned.c
arch/ia64/mm/discontig.c
arch/ia64/mm/fault.c
arch/ia64/mm/hugetlbpage.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/xpc_main.c
arch/m32r/kernel/m32r_ksyms.c
arch/m32r/kernel/signal.c
arch/m32r/kernel/smpboot.c
arch/m32r/kernel/sys_m32r.c
arch/m32r/mm/fault-nommu.c
arch/m32r/mm/fault.c
arch/m68k/kernel/ptrace.c
arch/m68k/mvme16x/rtc.c
arch/m68knommu/Kconfig.debug
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/ptrace.c
arch/m68knommu/kernel/sys_m68k.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/configs/rbhma4500_defconfig
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/early_printk.c
arch/mips/kernel/irixelf.c
arch/mips/kernel/irixioctl.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smtc.c
arch/mips/kernel/stacktrace.c
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/math-emu/dsemul.c
arch/mips/mm/fault.c
arch/mips/pci/fixup-sb1250.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sni/irq.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
arch/mips/tx4938/toshiba_rbtx4938/setup.c
arch/parisc/hpux/fs.c
arch/parisc/hpux/ioctl.c
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/signal32.c
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/traps.c
arch/parisc/kernel/unwind.c
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/44x.c [new file with mode: 0644]
arch/powerpc/boot/44x.h [new file with mode: 0644]
arch/powerpc/boot/Makefile
arch/powerpc/boot/cuboot-ebony.c [new file with mode: 0644]
arch/powerpc/boot/dcr.h [new file with mode: 0644]
arch/powerpc/boot/dts/ebony.dts [new file with mode: 0644]
arch/powerpc/boot/dts/holly.dts [new file with mode: 0644]
arch/powerpc/boot/dts/lite5200.dts
arch/powerpc/boot/dts/lite5200b.dts
arch/powerpc/boot/dts/mpc832x_mds.dts
arch/powerpc/boot/dts/mpc832x_rdb.dts
arch/powerpc/boot/dts/mpc836x_mds.dts
arch/powerpc/boot/dts/mpc8568mds.dts
arch/powerpc/boot/ebony.c [new file with mode: 0644]
arch/powerpc/boot/holly.c [new file with mode: 0644]
arch/powerpc/boot/mktree.c
arch/powerpc/boot/treeboot-ebony.c [new file with mode: 0644]
arch/powerpc/boot/wrapper
arch/powerpc/configs/ebony_defconfig [new file with mode: 0644]
arch/powerpc/configs/holly_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc832x_mds_defconfig
arch/powerpc/configs/mpc832x_rdb_defconfig
arch/powerpc/configs/mpc836x_mds_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/head_44x.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/idle_power4.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/lparmap.c
arch/powerpc/kernel/msi.c [new file with mode: 0644]
arch/powerpc/kernel/of_device.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/swsusp.c [new file with mode: 0644]
arch/powerpc/kernel/swsusp_64.c [new file with mode: 0644]
arch/powerpc/kernel/swsusp_asm64.S [new file with mode: 0644]
arch/powerpc/kernel/syscalls.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/udbg_16550.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vio.c
arch/powerpc/lib/dma-noncoherent.c
arch/powerpc/mm/44x_mmu.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_64.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/mm/slb.c
arch/powerpc/mm/slb_low.S
arch/powerpc/mm/slice.c [new file with mode: 0644]
arch/powerpc/mm/stab.c
arch/powerpc/mm/tlb_32.c
arch/powerpc/mm/tlb_64.c
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/platforms/44x/44x.h [new file with mode: 0644]
arch/powerpc/platforms/44x/Kconfig [new file with mode: 0644]
arch/powerpc/platforms/44x/Makefile [new file with mode: 0644]
arch/powerpc/platforms/44x/ebony.c [new file with mode: 0644]
arch/powerpc/platforms/44x/misc_44x.S [new file with mode: 0644]
arch/powerpc/platforms/52xx/Kconfig
arch/powerpc/platforms/52xx/Makefile
arch/powerpc/platforms/52xx/efika.c
arch/powerpc/platforms/52xx/lite5200.c
arch/powerpc/platforms/52xx/mpc52xx_pm.c [new file with mode: 0644]
arch/powerpc/platforms/52xx/mpc52xx_sleep.S [new file with mode: 0644]
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc832x_rdb.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/85xx/mpc8544_ds.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/mpc86xx_smp.c
arch/powerpc/platforms/8xx/mpc86xads_setup.c
arch/powerpc/platforms/8xx/mpc885ads_setup.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/cell/Kconfig
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/cell/io-workarounds.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spufs/Makefile
arch/powerpc/platforms/cell/spufs/backing_ops.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/hw_ops.c
arch/powerpc/platforms/cell/spufs/lscsa_alloc.c [new file with mode: 0644]
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/switch.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/embedded6xx/Kconfig
arch/powerpc/platforms/embedded6xx/Makefile
arch/powerpc/platforms/embedded6xx/holly.c [new file with mode: 0644]
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/iseries/Kconfig
arch/powerpc/platforms/iseries/smp.c
arch/powerpc/platforms/iseries/viopath.c
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/pasemi/cpufreq.c
arch/powerpc/platforms/pasemi/pci.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/powermac/nvram.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/htab.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/ps3/smp.c
arch/powerpc/platforms/ps3/spu.c
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/msi.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic.h [new file with mode: 0644]
arch/powerpc/sysdev/mpic_msi.c [new file with mode: 0644]
arch/powerpc/sysdev/mpic_u3msi.c [new file with mode: 0644]
arch/powerpc/sysdev/rom.c [deleted file]
arch/powerpc/sysdev/tsi108_dev.c
arch/powerpc/sysdev/tsi108_pci.c
arch/powerpc/sysdev/uic.c
arch/powerpc/xmon/xmon.c
arch/ppc/kernel/asm-offsets.c
arch/ppc/kernel/ppc_htab.c
arch/ppc/kernel/smp.c
arch/ppc/platforms/mpc866ads_setup.c
arch/ppc/syslib/ipic.c
arch/ppc/syslib/ppc4xx_sgdma.c
arch/ppc/syslib/virtex_devices.h
arch/s390/appldata/appldata_base.c
arch/s390/crypto/Kconfig
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/dis.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/process.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/sys_s390.c
arch/s390/kernel/time.c
arch/s390/kernel/traps.c
arch/s390/mm/fault.c
arch/sh/Kconfig
arch/sh/boards/landisk/setup.c
arch/sh/boards/se/7751/setup.c
arch/sh/drivers/Makefile
arch/sh/drivers/dma/Kconfig
arch/sh/drivers/dma/Makefile
arch/sh/drivers/dma/dmabrg.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-st40.c
arch/sh/kernel/cpu/sh2a/Makefile
arch/sh/kernel/cpu/sh2a/opcode_helper.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/probe.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/ex.S [deleted file]
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4a/clock-sh73180.c
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7770.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/early_printk.c
arch/sh/kernel/process.c
arch/sh/kernel/ptrace.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls.S
arch/sh/kernel/time.c
arch/sh/kernel/timers/timer-cmt.c
arch/sh/kernel/timers/timer-mtu2.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps.c
arch/sh/kernel/vsyscall/vsyscall.c
arch/sh/lib/delay.c
arch/sh/mm/Kconfig
arch/sh/mm/fault-nommu.c
arch/sh/mm/fault.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh/mm/pmb.c
arch/sh64/kernel/early_printk.c
arch/sh64/kernel/irq.c
arch/sh64/kernel/pci_sh5.c
arch/sh64/kernel/sh_ksyms.c
arch/sh64/kernel/signal.c
arch/sh64/kernel/sys_sh64.c
arch/sh64/kernel/traps.c
arch/sh64/kernel/unwind.c
arch/sh64/mm/fault.c
arch/sh64/mm/hugetlbpage.c
arch/sh64/mm/tlbmiss.c
arch/sparc/kernel/asm-offsets.c
arch/sparc/kernel/head.S
arch/sparc/kernel/irq.c
arch/sparc/kernel/process.c
arch/sparc/kernel/setup.c
arch/sparc/kernel/signal.c
arch/sparc/kernel/smp.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/sunos_ioctl.c
arch/sparc/kernel/sys_solaris.c
arch/sparc/kernel/systbls.S
arch/sparc/kernel/traps.c
arch/sparc/lib/bitext.c
arch/sparc/mm/fault.c
arch/sparc/mm/srmmu.c
arch/sparc64/kernel/ebus.c
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_common.c
arch/sparc64/kernel/pci_fire.c
arch/sparc64/kernel/pci_impl.h
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/stacktrace.c
arch/sparc64/kernel/sunos_ioctl32.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/unaligned.c
arch/sparc64/mm/fault.c
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/solaris/ipc.c
arch/sparc64/solaris/misc.c
arch/sparc64/solaris/signal.c
arch/sparc64/solaris/socket.c
arch/sparc64/solaris/socksys.c
arch/um/Kconfig
arch/um/Kconfig.scsi [deleted file]
arch/um/drivers/net_kern.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/pcap_user.c
arch/um/include/sysdep-i386/archsetjmp.h
arch/um/include/sysdep-x86_64/archsetjmp.h
arch/um/kernel/skas/process.c
arch/um/kernel/time.c
arch/um/os-Linux/process.c
arch/um/os-Linux/skas/mem.c
arch/um/os-Linux/skas/process.c
arch/v850/kernel/asm-offsets.c
arch/v850/kernel/entry.S
arch/v850/kernel/process.c
arch/v850/kernel/ptrace.c
arch/v850/kernel/signal.c
arch/v850/kernel/syscalls.c
arch/x86_64/ia32/ia32_signal.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/crash.c
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/ioport.c
arch/x86_64/kernel/irq.c
arch/x86_64/kernel/kprobes.c
arch/x86_64/kernel/ldt.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mce_amd.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/reboot.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/stacktrace.c
arch/x86_64/kernel/sys_x86_64.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vsyscall.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/xtensa/kernel/asm-offsets.c
arch/xtensa/kernel/pci-dma.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
arch/xtensa/kernel/signal.c
block/as-iosched.c
block/genhd.c
block/ll_rw_blk.c
crypto/Kconfig
crypto/cryptomgr.c
drivers/acpi/glue.c
drivers/acpi/osl.c
drivers/acpi/scan.c
drivers/acpi/sleep/main.c
drivers/acpi/sleep/proc.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_amd.c
drivers/ata/pata_artop.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_it8213.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_marvell.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_nv.c
drivers/ata/sata_sil24.c
drivers/ata/sata_svw.c
drivers/ata/sata_via.c
drivers/base/devres.c
drivers/base/platform.c
drivers/base/topology.c
drivers/block/acsi_slm.c
drivers/block/cciss.c
drivers/block/cciss_scsi.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/rd.c
drivers/block/umem.c
drivers/char/Kconfig
drivers/char/agp/uninorth-agp.c
drivers/char/amiserial.c
drivers/char/briq_panel.c
drivers/char/consolemap.c
drivers/char/cs5535_gpio.c
drivers/char/cyclades.c
drivers/char/digi.h [deleted file]
drivers/char/drm/ati_pcigart.c
drivers/char/drm/drmP.h
drivers/char/drm/drm_dma.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_os_linux.h
drivers/char/drm/drm_pciids.h
drivers/char/drm/drm_vm.c
drivers/char/drm/r128_cce.c
drivers/char/drm/r128_drv.h
drivers/char/drm/r300_reg.h
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_state.c
drivers/char/drm/via_dma.c
drivers/char/drm/via_drv.h
drivers/char/ds1620.c
drivers/char/dsp56k.c
drivers/char/dtlk.c
drivers/char/ec3104_keyb.c
drivers/char/epca.c
drivers/char/genrtc.c
drivers/char/hangcheck-timer.c
drivers/char/hvc_console.c
drivers/char/hvc_iseries.c
drivers/char/hvc_vio.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/Makefile
drivers/char/hw_random/intel-rng.c
drivers/char/hw_random/pasemi-rng.c [new file with mode: 0644]
drivers/char/i8k.c
drivers/char/ip27-rtc.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/isicom.c
drivers/char/keyboard.c
drivers/char/lp.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/mxser_new.c
drivers/char/n_r3964.c
drivers/char/pcmcia/Kconfig
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/ppdev.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/rocket_int.h
drivers/char/rtc.c
drivers/char/selection.c
drivers/char/serial167.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/sysrq.c
drivers/char/tipar.c
drivers/char/tpm/Kconfig
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_atmel.h
drivers/char/tpm/tpm_infineon.c
drivers/char/tty_io.c
drivers/char/vc_screen.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/char/watchdog/omap_wdt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/crypto/Kconfig
drivers/edac/i82875p_edac.c
drivers/eisa/virtual_root.c
drivers/hid/hid-core.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/ad7418.c [new file with mode: 0644]
drivers/hwmon/ams/ams-core.c
drivers/hwmon/ams/ams-i2c.c
drivers/hwmon/ams/ams-pmu.c
drivers/hwmon/applesmc.c [new file with mode: 0644]
drivers/hwmon/coretemp.c [new file with mode: 0644]
drivers/hwmon/f71805f.c
drivers/hwmon/hdaps.c
drivers/hwmon/hwmon-vid.c
drivers/hwmon/lm75.c
drivers/hwmon/lm78.c
drivers/hwmon/lm87.c
drivers/hwmon/max6650.c [new file with mode: 0644]
drivers/hwmon/pc87427.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/smsc47m192.c
drivers/hwmon/vt1211.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/tps65010.c
drivers/i2c/i2c-dev.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/siimage.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/nodemgr.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/video1394.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/evdev.c
drivers/input/ff-core.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/joystick/Kconfig
drivers/input/joystick/Makefile
drivers/input/joystick/analog.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/turbografx.c
drivers/input/joystick/xpad.c [moved from drivers/usb/input/xpad.c with 99% similarity]
drivers/input/keyboard/Kconfig
drivers/input/keyboard/aaed2000_kbd.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ati_remote.c [moved from drivers/usb/input/ati_remote.c with 100% similarity]
drivers/input/misc/ati_remote2.c [moved from drivers/usb/input/ati_remote2.c with 99% similarity]
drivers/input/misc/keyspan_remote.c [moved from drivers/usb/input/keyspan_remote.c with 100% similarity]
drivers/input/misc/map_to_7segment.h [moved from drivers/usb/input/map_to_7segment.h with 100% similarity]
drivers/input/misc/powermate.c [moved from drivers/usb/input/powermate.c with 98% similarity]
drivers/input/misc/uinput.c
drivers/input/misc/yealink.c [moved from drivers/usb/input/yealink.c with 98% similarity]
drivers/input/misc/yealink.h [moved from drivers/usb/input/yealink.h with 100% similarity]
drivers/input/mouse/Kconfig
drivers/input/mouse/Makefile
drivers/input/mouse/appletouch.c [moved from drivers/usb/input/appletouch.c with 100% similarity]
drivers/input/mouse/synaptics.c
drivers/input/mousedev.c
drivers/input/serio/i8042.c
drivers/input/tablet/Kconfig [new file with mode: 0644]
drivers/input/tablet/Makefile [new file with mode: 0644]
drivers/input/tablet/acecad.c [moved from drivers/usb/input/acecad.c with 99% similarity]
drivers/input/tablet/aiptek.c [moved from drivers/usb/input/aiptek.c with 100% similarity]
drivers/input/tablet/gtco.c [moved from drivers/usb/input/gtco.c with 100% similarity]
drivers/input/tablet/kbtab.c [moved from drivers/usb/input/kbtab.c with 99% similarity]
drivers/input/tablet/wacom.h [moved from drivers/usb/input/wacom.h with 99% similarity]
drivers/input/tablet/wacom_sys.c [moved from drivers/usb/input/wacom_sys.c with 99% similarity]
drivers/input/tablet/wacom_wac.c [moved from drivers/usb/input/wacom_wac.c with 99% similarity]
drivers/input/tablet/wacom_wac.h [moved from drivers/usb/input/wacom_wac.h with 93% similarity]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/usbtouchscreen.c [moved from drivers/usb/input/usbtouchscreen.c with 99% similarity]
drivers/input/tsdev.c
drivers/isdn/capi/Kconfig
drivers/isdn/capi/capi.c
drivers/isdn/capi/capiutil.c
drivers/isdn/divert/divert_procfs.c
drivers/isdn/gigaset/usb-gigaset.c
drivers/isdn/hardware/eicon/capimain.c
drivers/isdn/hardware/eicon/dbgioctl.h [deleted file]
drivers/isdn/hardware/eicon/divamnt.c
drivers/isdn/hardware/eicon/divasi.c
drivers/isdn/hardware/eicon/divasmain.c
drivers/isdn/hardware/eicon/divasync.h
drivers/isdn/hardware/eicon/main_if.h [deleted file]
drivers/isdn/hardware/eicon/platform.h
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/hysdn/boardergo.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/isdn/isdnloop/isdnloop.c
drivers/kvm/kvm_main.c
drivers/leds/leds-h1940.c
drivers/macintosh/Kconfig
drivers/macintosh/apm_emu.c
drivers/macintosh/mac_hid.c
drivers/macintosh/macio_sysfs.c
drivers/macintosh/smu.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/therm_pm72.c
drivers/macintosh/via-pmu-led.c
drivers/macintosh/via-pmu.c
drivers/macintosh/windfarm_core.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/macintosh/windfarm_smu_controls.c
drivers/macintosh/windfarm_smu_sat.c
drivers/mca/mca-bus.c
drivers/mca/mca-driver.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/bitmap.c
drivers/md/dm-bio-list.h
drivers/md/dm-crypt.c
drivers/md/dm-delay.c [new file with mode: 0644]
drivers/md/dm-exception-store.c
drivers/md/dm-hw-handler.h
drivers/md/dm-io.c
drivers/md/dm-io.h
drivers/md/dm-log.c
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/kcopyd.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/frontends/dib7000m.c
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/radio/dsbr100.c
drivers/media/video/cpia.h
drivers/media/video/cpia_pp.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/dabusb.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/ov511.h
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pwc/philips.txt
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/se401.h
drivers/media/video/tvaudio.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
drivers/media/video/zoran_driver.c
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/mptbase.c
drivers/message/i2o/i2o_lan.h [deleted file]
drivers/mfd/ucb1x00-ts.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/blink.c [new file with mode: 0644]
drivers/misc/phantom.c [new file with mode: 0644]
drivers/misc/tifm_7xx1.c
drivers/mmc/Kconfig
drivers/mmc/card/Kconfig
drivers/mmc/core/Kconfig
drivers/mmc/core/core.c
drivers/mmc/host/Kconfig
drivers/mmc/host/tifm_sd.c
drivers/mtd/chips/Kconfig
drivers/mtd/chips/Makefile
drivers/mtd/chips/amd_flash.c [deleted file]
drivers/mtd/chips/jedec.c [deleted file]
drivers/mtd/chips/sharp.c [deleted file]
drivers/mtd/devices/block2mtd.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/arctic-mtd.c [deleted file]
drivers/mtd/maps/beech-mtd.c [deleted file]
drivers/mtd/maps/nettel.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/at91_nand.c
drivers/mtd/nand/cafe_ecc.c [deleted file]
drivers/mtd/nand/cafe_nand.c [moved from drivers/mtd/nand/cafe.c with 88% similarity]
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/plat_nand.c [new file with mode: 0644]
drivers/mtd/onenand/onenand_base.c
drivers/net/3c509.c
drivers/net/3c59x.c
drivers/net/Kconfig
drivers/net/arm/at91_ether.c
drivers/net/arm/at91_ether.h
drivers/net/atl1/atl1_ethtool.c
drivers/net/atl1/atl1_hw.c
drivers/net/atl1/atl1_main.c
drivers/net/atl1/atl1_param.c
drivers/net/atp.c
drivers/net/bmac.c
drivers/net/bonding/bond_main.c
drivers/net/dm9000.c
drivers/net/e1000/e1000_main.c
drivers/net/eepro.c
drivers/net/eepro100.c
drivers/net/ehea/ehea_main.c
drivers/net/epic100.c
drivers/net/hamradio/Kconfig
drivers/net/irda/donauboe.h
drivers/net/irda/sir_dev.c
drivers/net/irda/sir_dongle.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/vlsi_ir.c
drivers/net/ixgb/ixgb_ee.c
drivers/net/mace.c
drivers/net/meth.h
drivers/net/myri10ge/myri10ge.c
drivers/net/myri10ge/myri10ge_mcp.h
drivers/net/natsemi.c
drivers/net/ne.c
drivers/net/ne2k-pci.c
drivers/net/ns83820.c
drivers/net/pasemi_mac.c
drivers/net/pasemi_mac.h
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/phy/phy.c
drivers/net/ppp_generic.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/smc91x.h
drivers/net/spider_net.c
drivers/net/sundance.c
drivers/net/sungem.c
drivers/net/sungem_phy.c
drivers/net/tc35815.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tsi108_eth.c
drivers/net/tsi108_eth.h
drivers/net/tulip/interrupt.c
drivers/net/tulip/winbond-840.c
drivers/net/tulip/xircom_cb.c
drivers/net/typhoon.c
drivers/net/ucc_geth.c
drivers/net/ucc_geth_mii.c
drivers/net/wan/cosa.c
drivers/net/wireless/Kconfig
drivers/net/wireless/airo.c
drivers/net/wireless/airport.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wavelan_cs.p.h
drivers/net/yellowfin.c
drivers/parisc/lba_pci.c
drivers/parport/parport_cs.c
drivers/parport/parport_mfc3.c
drivers/parport/parport_pc.c
drivers/parport/parport_serial.c
drivers/parport/parport_sunbpp.c
drivers/parport/share.c
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/ibmphp_hpc.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/proc.c
drivers/pcmcia/pxa2xx_mainstone.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pnp/core.c
drivers/pnp/pnpacpi/core.c
drivers/pnp/pnpbios/core.c
drivers/pnp/quirks.c
drivers/ps3/vuart.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/hctosys.c
drivers/rtc/interface.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-core.h [new file with mode: 0644]
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-lib.c
drivers/rtc/rtc-max6900.c [new file with mode: 0644]
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-proc.c
drivers/rtc/rtc-rs5c313.c [new file with mode: 0644]
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-vr41xx.c
drivers/s390/char/sclp_rw.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_eddp.c
drivers/s390/net/qeth_eddp.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_mpc.c
drivers/s390/net/qeth_mpc.h
drivers/s390/net/qeth_sys.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/sbus/char/bpp.c
drivers/sbus/char/rtc.c
drivers/sbus/char/vfc_dev.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/dpcsup.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic94xx/Makefile
drivers/scsi/ch.c
drivers/scsi/dc395x.c
drivers/scsi/dpt_i2o.c
drivers/scsi/esp_scsi.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_disc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/mac53c94.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid.h
drivers/scsi/megaraid/megaraid_mm.c
drivers/scsi/mesh.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla4xxx/ql4_dbg.c
drivers/scsi/qla4xxx/ql4_glbl.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sg.c
drivers/scsi/sni_53c710.c
drivers/scsi/tmscsim.c
drivers/scsi/tmscsim.h
drivers/serial/8250.c
drivers/serial/Kconfig
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/icom.c
drivers/serial/jsm/jsm_neo.c
drivers/serial/jsm/jsm_tty.c
drivers/serial/mpc52xx_uart.c
drivers/serial/of_serial.c
drivers/serial/pmac_zilog.c
drivers/serial/s3c2410.c
drivers/serial/serial_txx9.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/atmel_spi.c
drivers/spi/au1550_spi.c [new file with mode: 0644]
drivers/spi/spi.c
drivers/spi/spi_butterfly.c
drivers/spi/spidev.c [new file with mode: 0644]
drivers/telephony/ixj.c
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/atm/usbatm.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/usblp.c
drivers/usb/core/hub.c
drivers/usb/core/inode.c
drivers/usb/core/usb.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-ppc-of.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/image/mdc800.c
drivers/usb/image/microtek.c
drivers/usb/input/Kconfig [deleted file]
drivers/usb/input/Makefile [deleted file]
drivers/usb/misc/auerswald.c
drivers/usb/misc/idmouse.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/rio500.c
drivers/usb/misc/sisusbvga/sisusb_con.c
drivers/usb/mon/mon_main.c
drivers/usb/net/usbnet.h
drivers/usb/serial/Kconfig
drivers/usb/serial/aircable.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/usb.h
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/arcfb.c
drivers/video/arkfb.c [new file with mode: 0644]
drivers/video/aty/ati_ids.h
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/mach64_ct.c
drivers/video/aty/mach64_cursor.c
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_monitor.c
drivers/video/aty/radeon_pm.c
drivers/video/aty/radeonfb.h
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/cr_bllcd.c [new file with mode: 0644]
drivers/video/cfbcopyarea.c
drivers/video/cfbfillrect.c
drivers/video/cirrusfb.c
drivers/video/console/fbcon.c
drivers/video/console/fonts.c
drivers/video/console/mdacon.c
drivers/video/console/promcon.c
drivers/video/console/softcursor.c
drivers/video/console/sticon.c
drivers/video/console/sticore.c
drivers/video/console/vgacon.c
drivers/video/display/Kconfig [new file with mode: 0644]
drivers/video/display/Makefile [new file with mode: 0644]
drivers/video/display/display-sysfs.c [new file with mode: 0644]
drivers/video/epson1355fb.c
drivers/video/fb_defio.c [new file with mode: 0644]
drivers/video/fb_draw.h [new file with mode: 0644]
drivers/video/fb_sys_fops.c [new file with mode: 0644]
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/fbsysfs.c
drivers/video/hecubafb.c [new file with mode: 0644]
drivers/video/i810/i810.h
drivers/video/i810/i810_main.c
drivers/video/intelfb/intelfbhw.c
drivers/video/logo/Kconfig
drivers/video/matrox/matroxfb_Ti3026.c
drivers/video/matrox/matroxfb_accel.c
drivers/video/matrox/matroxfb_base.c
drivers/video/matrox/matroxfb_misc.c
drivers/video/modedb.c
drivers/video/neofb.c
drivers/video/nvidia/nv_accel.c
drivers/video/nvidia/nv_hw.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nv_local.h
drivers/video/nvidia/nv_of.c
drivers/video/nvidia/nv_setup.c
drivers/video/nvidia/nv_type.h
drivers/video/nvidia/nvidia.c
drivers/video/offb.c
drivers/video/pm2fb.c
drivers/video/ps3fb.c
drivers/video/pvr2fb.c
drivers/video/pxafb.c
drivers/video/riva/fbdev.c
drivers/video/riva/nv4ref.h [deleted file]
drivers/video/riva/nv_driver.c
drivers/video/riva/riva_hw.c
drivers/video/riva/rivafb-i2c.c
drivers/video/riva/rivafb.h
drivers/video/s3fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/savage/savagefb.h
drivers/video/savage/savagefb_driver.c
drivers/video/sis/osdef.h
drivers/video/sis/sis.h
drivers/video/sis/sis_main.c
drivers/video/skeletonfb.c
drivers/video/sm501fb.c
drivers/video/sunxvr2500.c
drivers/video/svgalib.c
drivers/video/syscopyarea.c [new file with mode: 0644]
drivers/video/sysfillrect.c [new file with mode: 0644]
drivers/video/sysimgblt.c [new file with mode: 0644]
drivers/video/tgafb.c
drivers/video/vermilion/Makefile [new file with mode: 0644]
drivers/video/vermilion/cr_pll.c [new file with mode: 0644]
drivers/video/vermilion/vermilion.c [new file with mode: 0644]
drivers/video/vermilion/vermilion.h [new file with mode: 0644]
drivers/video/vfb.c
drivers/video/vga16fb.c
drivers/video/vgastate.c
drivers/video/vt8623fb.c [new file with mode: 0644]
drivers/video/xilinxfb.c [new file with mode: 0644]
drivers/w1/masters/Kconfig
drivers/w1/masters/Makefile
drivers/w1/masters/ds1wm.c [new file with mode: 0644]
drivers/w1/w1.c
drivers/w1/w1_int.c
fs/9p/vfs_addr.c
fs/9p/vfs_dentry.c
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/Kconfig
fs/affs/file.c
fs/afs/Makefile
fs/afs/afs_fs.h
fs/afs/callback.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/main.c
fs/afs/misc.c
fs/afs/mntpt.c
fs/afs/rxrpc.c
fs/afs/security.c
fs/afs/server.c
fs/afs/super.c
fs/afs/vnode.c
fs/afs/write.c [new file with mode: 0644]
fs/aio.c
fs/attr.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/bad_inode.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_em86.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/block_dev.c
fs/buffer.c
fs/cifs/file.c
fs/cifs/readdir.c
fs/compat.c
fs/compat_ioctl.c
fs/configfs/file.c
fs/dcache.c
fs/devpts/inode.c
fs/direct-io.c
fs/dquot.c
fs/ecryptfs/file.c
fs/eventpoll.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext2/dir.c
fs/ext2/ext2.h
fs/ext2/fsync.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/xattr_security.c
fs/ext2/xattr_trusted.c
fs/ext3/dir.c
fs/ext3/inode.c
fs/ext3/ioctl.c
fs/ext3/namei.c
fs/ext3/resize.c
fs/ext3/xattr_security.c
fs/ext3/xattr_trusted.c
fs/ext3/xattr_user.c
fs/ext4/dir.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/xattr_security.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/fat/dir.c
fs/fat/inode.c
fs/fifo.c
fs/file_table.c
fs/filesystems.c
fs/freevxfs/vxfs_bmap.c
fs/freevxfs/vxfs_inode.c
fs/fuse/inode.c
fs/gfs2/glops.c
fs/gfs2/locking/nolock/main.c
fs/gfs2/ops_dentry.c
fs/gfs2/ops_file.c
fs/hfs/btree.c
fs/hfsplus/btree.c
fs/hostfs/hostfs.h
fs/hostfs/hostfs_kern.c
fs/hostfs/hostfs_user.c
fs/inode.c
fs/inotify.c
fs/internal.h
fs/ioctl.c
fs/jbd/checkpoint.c
fs/jbd/commit.c
fs/jbd/journal.c
fs/jbd/recovery.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/revoke.c
fs/jbd2/transaction.c
fs/jffs2/histo_mips.h [deleted file]
fs/jffs2/readinode.c
fs/jffs2/wbuf.c
fs/jfs/inode.c
fs/jfs/ioctl.c
fs/jfs/jfs_dmap.c
fs/jfs/jfs_imap.c
fs/jfs/jfs_inode.c
fs/jfs/jfs_inode.h
fs/jfs/jfs_lock.h
fs/jfs/jfs_logmgr.c
fs/jfs/jfs_txnmgr.c
fs/libfs.c
fs/lockd/clntproc.c
fs/mpage.c
fs/namei.c
fs/namespace.c
fs/ncpfs/file.c
fs/nfs/client.c
fs/nfs/direct.c
fs/nfs/getroot.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4renewd.c
fs/nfs/proc.c
fs/nfs/symlink.c
fs/nfs/write.c
fs/nfsd/Makefile
fs/nfsd/export.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/nfsxdr.c
fs/ntfs/dir.c
fs/ntfs/file.c
fs/ntfs/inode.c
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/inode.c
fs/ocfs2/slot_map.c
fs/ocfs2/vote.c
fs/open.c
fs/partitions/Kconfig
fs/partitions/Makefile
fs/partitions/check.c
fs/partitions/sysv68.c [new file with mode: 0644]
fs/partitions/sysv68.h [new file with mode: 0644]
fs/pipe.c
fs/pnode.c
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/proc_misc.c
fs/proc/proc_sysctl.c
fs/proc/proc_tty.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/quota.c
fs/ramfs/file-nommu.c
fs/ramfs/inode.c
fs/read_write.c
fs/readdir.c
fs/reiserfs/dir.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/journal.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/resize.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/select.c
fs/smbfs/request.c
fs/smbfs/smbiod.c
fs/smbfs/sock.c
fs/smbfs/symlink.c
fs/splice.c
fs/stat.c
fs/super.c
fs/sync.c
fs/sysfs/file.c
fs/sysv/namei.c
fs/udf/balloc.c
fs/udf/dir.c
fs/udf/directory.c
fs/udf/fsync.c
fs/udf/inode.c
fs/udf/misc.c
fs/udf/namei.c
fs/udf/partition.c
fs/udf/super.c
fs/udf/symlink.c
fs/udf/truncate.c
fs/udf/udf_sb.h
fs/udf/udfdecl.h
fs/ufs/dir.c
fs/utimes.c
fs/xattr.c
fs/xfs/linux-2.6/mrlock.h
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_fs_subr.c
fs/xfs/linux-2.6/xfs_fs_subr.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/support/debug.c
fs/xfs/support/debug.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2_block.c
fs/xfs/xfs_dir2_data.c
fs/xfs/xfs_dir2_data.h
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_error.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_iocore.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iomap.h
fs/xfs/xfs_itable.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_qmops.c
fs/xfs/xfs_quota.h
fs/xfs/xfs_rename.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rw.c
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_utils.c
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_bus.h
include/asm-alpha/atomic.h
include/asm-alpha/kdebug.h [new file with mode: 0644]
include/asm-alpha/local.h
include/asm-alpha/pgtable.h
include/asm-alpha/smp.h
include/asm-alpha/system.h
include/asm-alpha/thread_info.h
include/asm-arm/arch-at91/at91rm9200.h
include/asm-arm/arch-at91/at91sam9260.h
include/asm-arm/arch-at91/at91sam9261.h
include/asm-arm/arch-at91/at91sam9263.h
include/asm-arm/arch-at91/board.h
include/asm-arm/arch-at91/cpu.h
include/asm-arm/arch-imx/imx-regs.h
include/asm-arm/arch-integrator/platform.h
include/asm-arm/arch-iop32x/glantank.h
include/asm-arm/arch-iop32x/n2100.h
include/asm-arm/arch-omap/aic23.h
include/asm-arm/arch-omap/board-apollon.h
include/asm-arm/arch-omap/board-h4.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/dma.h
include/asm-arm/arch-omap/dsp.h [deleted file]
include/asm-arm/arch-omap/dsp_common.h
include/asm-arm/arch-omap/gpio-switch.h [new file with mode: 0644]
include/asm-arm/arch-omap/gpio.h
include/asm-arm/arch-omap/gpmc.h
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/hwa742.h [new file with mode: 0644]
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/lcd_lph8923.h [deleted file]
include/asm-arm/arch-omap/lcd_mipid.h [new file with mode: 0644]
include/asm-arm/arch-omap/led.h [new file with mode: 0644]
include/asm-arm/arch-omap/mailbox.h [new file with mode: 0644]
include/asm-arm/arch-omap/mcspi.h
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-omap/menelaus.h
include/asm-arm/arch-omap/omap16xx.h
include/asm-arm/arch-omap/omap24xx.h
include/asm-arm/arch-omap/omapfb.h
include/asm-arm/arch-omap/sram.h
include/asm-arm/arch-omap/usb.h
include/asm-arm/arch-s3c2410/regs-power.h
include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
include/asm-arm/arch-s3c2410/regs-watchdog.h
include/asm-arm/arch-s3c2410/udc.h
include/asm-arm/atomic.h
include/asm-arm/cacheflush.h
include/asm-arm/dma-mapping.h
include/asm-arm/glue.h
include/asm-arm/kdebug.h [new file with mode: 0644]
include/asm-arm/kexec.h
include/asm-arm/mmu_context.h
include/asm-arm/pgtable-nommu.h
include/asm-arm/pgtable.h
include/asm-arm/proc-fns.h
include/asm-arm/system.h
include/asm-arm26/atomic.h
include/asm-arm26/io.h
include/asm-arm26/kdebug.h [new file with mode: 0644]
include/asm-arm26/memory.h
include/asm-arm26/pgtable.h
include/asm-arm26/setup.h
include/asm-arm26/system.h
include/asm-avr32/arch-at32ap/cpu.h [new file with mode: 0644]
include/asm-avr32/kdebug.h
include/asm-avr32/pgtable.h
include/asm-avr32/setup.h
include/asm-avr32/unistd.h
include/asm-blackfin/processor.h
include/asm-blackfin/system.h
include/asm-cris/kdebug.h [new file with mode: 0644]
include/asm-frv/atomic.h
include/asm-frv/kdebug.h [new file with mode: 0644]
include/asm-frv/pgtable.h
include/asm-frv/semaphore.h
include/asm-frv/system.h
include/asm-frv/tlb.h
include/asm-frv/unistd.h
include/asm-generic/atomic.h
include/asm-generic/bitops/atomic.h
include/asm-generic/kdebug.h [new file with mode: 0644]
include/asm-generic/local.h
include/asm-h8300/kdebug.h [new file with mode: 0644]
include/asm-h8300/pgtable.h
include/asm-h8300/system.h
include/asm-i386/atomic.h
include/asm-i386/bitops.h
include/asm-i386/boot.h
include/asm-i386/cmpxchg.h [new file with mode: 0644]
include/asm-i386/elf.h
include/asm-i386/ioctls.h
include/asm-i386/kdebug.h
include/asm-i386/kexec.h
include/asm-i386/local.h
include/asm-i386/mmzone.h
include/asm-i386/msr.h
include/asm-i386/paravirt.h
include/asm-i386/pgtable.h
include/asm-i386/serial.h
include/asm-i386/smp.h
include/asm-i386/sync_bitops.h
include/asm-i386/system.h
include/asm-i386/termbits.h
include/asm-i386/termios.h
include/asm-i386/thread_info.h
include/asm-i386/unistd.h
include/asm-ia64/atomic.h
include/asm-ia64/kdebug.h
include/asm-ia64/kexec.h
include/asm-ia64/local.h
include/asm-ia64/pgtable.h
include/asm-ia64/smp.h
include/asm-ia64/thread_info.h
include/asm-m32r/atomic.h
include/asm-m32r/kdebug.h [new file with mode: 0644]
include/asm-m32r/pgtable.h
include/asm-m32r/smp.h
include/asm-m32r/system.h
include/asm-m68k/atarihw.h
include/asm-m68k/atariints.h
include/asm-m68k/atomic.h
include/asm-m68k/kdebug.h [new file with mode: 0644]
include/asm-m68k/pgtable.h
include/asm-m68k/scatterlist.h
include/asm-m68k/system.h
include/asm-m68k/thread_info.h
include/asm-m68knommu/atomic.h
include/asm-m68knommu/kdebug.h [new file with mode: 0644]
include/asm-m68knommu/pgtable.h
include/asm-m68knommu/system.h
include/asm-mips/atomic.h
include/asm-mips/bootinfo.h
include/asm-mips/kdebug.h [new file with mode: 0644]
include/asm-mips/kexec.h
include/asm-mips/local.h
include/asm-mips/mach-au1x00/au1550_spi.h [new file with mode: 0644]
include/asm-mips/pgtable.h
include/asm-mips/system.h
include/asm-parisc/atomic.h
include/asm-parisc/compat.h
include/asm-parisc/kdebug.h [new file with mode: 0644]
include/asm-parisc/local.h
include/asm-parisc/pgtable.h
include/asm-powerpc/atomic.h
include/asm-powerpc/bitops.h
include/asm-powerpc/iommu.h
include/asm-powerpc/kdebug.h
include/asm-powerpc/kexec.h
include/asm-powerpc/kprobes.h
include/asm-powerpc/local.h
include/asm-powerpc/machdep.h
include/asm-powerpc/mmu-44x.h [new file with mode: 0644]
include/asm-powerpc/mmu-hash64.h
include/asm-powerpc/mmu.h
include/asm-powerpc/mpc52xx.h
include/asm-powerpc/mpic.h
include/asm-powerpc/of_device.h
include/asm-powerpc/paca.h
include/asm-powerpc/page.h
include/asm-powerpc/page_32.h
include/asm-powerpc/page_64.h
include/asm-powerpc/parport.h
include/asm-powerpc/pgalloc-32.h [new file with mode: 0644]
include/asm-powerpc/pgalloc-64.h [new file with mode: 0644]
include/asm-powerpc/pgalloc.h
include/asm-powerpc/pgtable-4k.h
include/asm-powerpc/pgtable-64k.h
include/asm-powerpc/pgtable-ppc32.h [new file with mode: 0644]
include/asm-powerpc/pgtable-ppc64.h [new file with mode: 0644]
include/asm-powerpc/pgtable.h
include/asm-powerpc/pmac_feature.h
include/asm-powerpc/ppc-pci.h
include/asm-powerpc/prom.h
include/asm-powerpc/ps3.h
include/asm-powerpc/smp.h
include/asm-powerpc/spu_csa.h
include/asm-powerpc/suspend.h [new file with mode: 0644]
include/asm-powerpc/system.h
include/asm-powerpc/tsi108.h
include/asm-powerpc/tsi108_pci.h [new file with mode: 0644]
include/asm-powerpc/udbg.h
include/asm-ppc/hydra.h
include/asm-ppc/kdebug.h [new file with mode: 0644]
include/asm-ppc/pgtable.h
include/asm-ppc/system.h
include/asm-s390/kdebug.h
include/asm-s390/kexec.h
include/asm-s390/qdio.h
include/asm-s390/smp.h
include/asm-sh/bug.h
include/asm-sh/cpu-features.h
include/asm-sh/cpu-sh3/dma.h
include/asm-sh/cpu-sh4/dma-sh7780.h
include/asm-sh/cpu-sh4/dma.h
include/asm-sh/dmabrg.h [new file with mode: 0644]
include/asm-sh/edosk7705.h
include/asm-sh/kdebug.h
include/asm-sh/kexec.h
include/asm-sh/pgalloc.h
include/asm-sh/pgtable.h
include/asm-sh/snapgear.h
include/asm-sh/system.h
include/asm-sh/timer.h
include/asm-sh/unistd.h
include/asm-sh64/kdebug.h [new file with mode: 0644]
include/asm-sh64/pgtable.h
include/asm-sh64/system.h
include/asm-sparc/kdebug.h
include/asm-sparc/smp.h
include/asm-sparc/system.h
include/asm-sparc/unistd.h
include/asm-sparc64/Kbuild
include/asm-sparc64/atomic.h
include/asm-sparc64/const.h [deleted file]
include/asm-sparc64/kdebug.h
include/asm-sparc64/kprobes.h
include/asm-sparc64/local.h
include/asm-sparc64/lsu.h
include/asm-sparc64/mmu.h
include/asm-sparc64/page.h
include/asm-sparc64/pbm.h [deleted file]
include/asm-sparc64/pgtable.h
include/asm-sparc64/pstate.h
include/asm-sparc64/sfafsr.h
include/asm-sparc64/smp.h
include/asm-sparc64/system.h
include/asm-sparc64/unistd.h
include/asm-um/cmpxchg.h [new file with mode: 0644]
include/asm-um/kdebug.h [new file with mode: 0644]
include/asm-um/required-features.h [new file with mode: 0644]
include/asm-um/smp.h
include/asm-v850/kdebug.h [new file with mode: 0644]
include/asm-v850/system.h
include/asm-x86_64/Kbuild
include/asm-x86_64/atomic.h
include/asm-x86_64/cmpxchg.h [new file with mode: 0644]
include/asm-x86_64/kdebug.h
include/asm-x86_64/kexec.h
include/asm-x86_64/local.h
include/asm-x86_64/msr.h
include/asm-x86_64/page.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/serial.h
include/asm-x86_64/smp.h
include/asm-x86_64/system.h
include/asm-x86_64/termbits.h
include/asm-x86_64/thread_info.h
include/asm-x86_64/unistd.h
include/asm-xtensa/atomic.h
include/asm-xtensa/kdebug.h [new file with mode: 0644]
include/asm-xtensa/platform-iss/simcall.h
include/asm-xtensa/system.h
include/linux/Kbuild
include/linux/aio.h
include/linux/awe_voice.h [deleted file]
include/linux/blkdev.h
include/linux/byteorder/generic.h
include/linux/byteorder/swab.h
include/linux/clockchips.h
include/linux/clocksource.h
include/linux/compat.h
include/linux/compat_ioctl.h [deleted file]
include/linux/compiler-gcc.h
include/linux/compiler-gcc3.h
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/console.h
include/linux/console_struct.h
include/linux/const.h [moved from include/asm-x86_64/const.h with 70% similarity]
include/linux/cpu.h
include/linux/cyclades.h
include/linux/dcache.h
include/linux/device.h
include/linux/display.h [new file with mode: 0644]
include/linux/ds1wm.h [new file with mode: 0644]
include/linux/efi.h
include/linux/ext3_fs.h
include/linux/ext3_fs_i.h
include/linux/ext4_fs_i.h
include/linux/fb.h
include/linux/font.h
include/linux/fs.h
include/linux/futex.h
include/linux/generic_acl.h
include/linux/genhd.h
include/linux/gfp.h
include/linux/highmem.h
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/init.h
include/linux/init_task.h
include/linux/interrupt.h
include/linux/ioctl32.h [deleted file]
include/linux/ipc.h
include/linux/irda.h
include/linux/irq.h
include/linux/isdn/capiutil.h
include/linux/isdn_divertif.h
include/linux/kallsyms.h
include/linux/kdebug.h [new file with mode: 0644]
include/linux/kexec.h
include/linux/kprobes.h
include/linux/kthread.h
include/linux/ktime.h
include/linux/libata.h
include/linux/list.h
include/linux/loop.h
include/linux/mc146818rtc.h
include/linux/mca.h
include/linux/meye.h
include/linux/mmzone.h
include/linux/mnt_namespace.h
include/linux/module.h
include/linux/mount.h
include/linux/msdos_fs.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mutex.h
include/linux/nfs4_acl.h
include/linux/nfs_fs_sb.h
include/linux/notifier.h
include/linux/nsproxy.h
include/linux/pagemap.h
include/linux/parport.h
include/linux/parport_pc.h
include/linux/phantom.h [new file with mode: 0644]
include/linux/pid_namespace.h
include/linux/pm.h
include/linux/pmu.h
include/linux/pnp.h
include/linux/poison.h
include/linux/proc_fs.h
include/linux/quota.h
include/linux/quotaops.h
include/linux/radix-tree.h
include/linux/raid/md_k.h
include/linux/reiserfs_fs_sb.h
include/linux/relay.h
include/linux/rslib.h
include/linux/rtc.h
include/linux/sched.h
include/linux/security.h
include/linux/signal.h
include/linux/smp.h
include/linux/sonypi.h
include/linux/spi/Kbuild [new file with mode: 0644]
include/linux/spi/spi.h
include/linux/spi/spidev.h [new file with mode: 0644]
include/linux/spinlock_types.h
include/linux/stacktrace.h
include/linux/stat.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcsock.h
include/linux/suspend.h
include/linux/svga.h
include/linux/syscalls.h
include/linux/sysdev.h
include/linux/tifm.h
include/linux/time.h
include/linux/timer.h
include/linux/tty.h
include/linux/uinput.h
include/linux/usb.h
include/linux/utsname.h
include/linux/vmalloc.h
include/linux/vmstat.h
include/linux/vt_kern.h
include/linux/workqueue.h
include/math-emu/extended.h [deleted file]
include/net/irda/af_irda.h
include/net/irda/irda.h
include/net/irda/iriap.h
include/net/irda/iriap_event.h
include/net/irda/irias_object.h
include/net/irda/irlan_client.h
include/net/irda/irlan_common.h
include/net/irda/irlan_eth.h
include/net/irda/irlan_event.h
include/net/irda/irlan_filter.h
include/net/irda/irlan_provider.h
include/net/irda/irlap.h
include/net/irda/irlmp.h
include/net/irda/irlmp_event.h
include/net/irda/irlmp_frame.h
include/net/irda/irmod.h
include/net/irda/irqueue.h
include/net/irda/irttp.h
include/net/irda/parameters.h
include/net/irda/timer.h
include/net/irda/wrapper.h
include/net/sock.h
include/scsi/libsas.h
include/video/mach64.h
include/video/permedia2.h
include/video/tgafb.h
init/Kconfig
init/do_mounts.c
init/main.c
ipc/compat.c
ipc/sem.c
ipc/util.c
kernel/Kconfig.preempt
kernel/Makefile
kernel/audit.c
kernel/configs.c
kernel/cpu.c
kernel/cpuset.c
kernel/die_notifier.c [new file with mode: 0644]
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/futex_compat.c
kernel/hrtimer.c
kernel/irq/handle.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/irq/spurious.c
kernel/itimer.c
kernel/kallsyms.c
kernel/kexec.c
kernel/kmod.c
kernel/kprobes.c
kernel/kthread.c
kernel/lockdep.c
kernel/module.c
kernel/mutex.c
kernel/nsproxy.c
kernel/params.c
kernel/pid.c
kernel/posix-cpu-timers.c
kernel/posix-timers.c
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/swap.c
kernel/power/user.c
kernel/printk.c
kernel/profile.c
kernel/rcupdate.c
kernel/rcutorture.c
kernel/relay.c
kernel/rtmutex.c
kernel/rtmutex_common.h
kernel/rwsem.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/softlockup.c
kernel/stop_machine.c
kernel/sys.c
kernel/sysctl.c
kernel/time.c
kernel/time/Makefile
kernel/time/clocksource.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-sched.c
kernel/time/timekeeping.c [new file with mode: 0644]
kernel/time/timer_list.c
kernel/time/timer_stats.c
kernel/timer.c
kernel/uid16.c
kernel/utsname.c
kernel/wait.c
kernel/workqueue.c
lib/Kconfig.debug
lib/fault-inject.c
lib/radix-tree.c
lib/reed_solomon/reed_solomon.c
lib/swiotlb.c
lib/vsprintf.c
mm/Kconfig
mm/filemap.c
mm/filemap_xip.c
mm/hugetlb.c
mm/mmap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/rmap.c
mm/slab.c
mm/slub.c
mm/sparse.c
mm/swap.c
mm/truncate.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/bluetooth/bnep/core.c
net/bluetooth/hci_sysfs.c
net/bridge/br_stp.c
net/bridge/br_stp_if.c
net/bridge/br_stp_timer.c
net/core/dev.c
net/core/flow.c
net/core/netpoll.c
net/core/pktgen.c
net/decnet/af_decnet.c
net/ipv4/Kconfig
net/ipv4/af_inet.c
net/ipv4/cipso_ipv4.c
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_sed.c
net/ipv4/tcp.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/netfilter/Kconfig
net/ipx/af_ipx.c
net/irda/af_irda.c
net/iucv/iucv.c
net/llc/af_llc.c
net/netfilter/Kconfig
net/netfilter/nf_conntrack_expect.c
net/netlink/af_netlink.c
net/sctp/chunk.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc.c
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/unix/af_unix.c
net/x25/af_x25.c
scripts/basic/docproc.c
scripts/kernel-doc
scripts/mod/modpost.c
security/capability.c
security/commoncap.c
security/selinux/Kconfig
security/selinux/hooks.c
sound/aoa/codecs/snd-aoa-codec-onyx.c
sound/aoa/codecs/snd-aoa-codec-tas.c
sound/aoa/soundbus/i2sbus/i2sbus-core.c
sound/core/Kconfig
sound/core/control.c
sound/core/hwdep.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/seq/oss/seq_oss.c
sound/core/seq/seq_clientmgr.c
sound/core/timer.c
sound/oss/Kconfig
sound/oss/btaudio.c
sound/oss/dmasound/Kconfig
sound/oss/dmasound/dmasound_awacs.c
sound/oss/es1371.c
sound/oss/pas2_pcm.c
sound/oss/swarm_cs4297a.c
sound/oss/trident.c
sound/oss/via82cxxx_audio.c
sound/pci/ac97/ac97_codec.c
sound/pci/ice1712/delta.h
sound/pci/mixart/mixart.c
sound/ppc/pmac.c
sound/ppc/tumbler.c
sound/soc/pxa/pxa2xx-ac97.h
sound/soc/pxa/pxa2xx-i2s.h
sound/sparc/dbri.c

diff --git a/CREDITS b/CREDITS
index c5f819bacda3e28322c391af965558dd37ab2dd8..6829e91a88d43f5827be72eef88f17e06eaab377 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -380,7 +380,7 @@ S: FutureTV Labs Ltd
 S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG
 S: United Kingdom
 
-N: Thomas Bogendörfer
+N: Thomas Bogendörfer
 E: tsbogend@alpha.franken.de
 D: PCnet32 driver, SONIC driver, JAZZ_ESP driver
 D: newport abscon driver, g364 framebuffer driver
@@ -400,7 +400,7 @@ W: http://math-www.uni-paderborn.de/~axel/
 D: Configuration help text support
 D: Linux CD and Support Giveaway List
 
-N: Erik Inge Bolsø
+N: Erik Inge Bolsø
 E: knan@mo.himolde.no
 D: Misc kernel hacks
 
@@ -428,7 +428,7 @@ D: Various fixes (mostly networking)
 S: Montreal, Quebec
 S: Canada
 
-N: Zoltán Böszörményi
+N: Zoltán Böszörményi
 E: zboszor@mail.externet.hu
 D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
 
@@ -661,7 +661,7 @@ N: Kees Cook
 E: kees@outflux.net
 W: http://outflux.net/
 P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
-D: Minor updates to SCSI code for the Communications type
+D: Minor updates to SCSI types, added /proc/pid/maps protection
 S: (ask for current address)
 S: USA
 
@@ -1029,11 +1029,11 @@ D: Future Domain TMC-16x0 SCSI driver (author)
 D: APM driver (early port)
 D: DRM drivers (author of several)
 
-N: János Farkas
+N: János Farkas
 E: chexum@shadow.banki.hu
 D: romfs, various (mostly networking) fixes
 P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71  6D 9C F3 9F F2 BF DF 6E
-S: Madarász Viktor utca 25
+S: Madarász Viktor utca 25
 S: 1131 Budapest
 S: Hungary
 
@@ -1044,10 +1044,10 @@ D: UDF filesystem
 S: (ask for current address)
 S: USA
 
-N: Jürgen Fischer
-E: fischer@norbit.de (=?iso-8859-1?q?J=FCrgen?= Fischer)
+N: Jürgen Fischer
+E: fischer@norbit.de
 D: Author of Adaptec AHA-152x SCSI driver
-S: Schulstraße 18
+S: Schulstraße 18
 S: 26506 Norden
 S: Germany
 
@@ -1113,7 +1113,7 @@ E: fuganti@netbank.com.br
 D: random kernel hacker, ZF MachZ Watchdog driver
 S: Conectiva S.A.
 S: R. Tocantins, 89 - Cristo Rei
-S: 80050-430 - Curitiba - Paraná
+S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
 N: Kumar Gala
@@ -1258,12 +1258,12 @@ S: 44 St. Joseph Street, Suite 506
 S: Toronto, Ontario, M4Y 2W4
 S: Canada
 
-N: Richard Günther
+N: Richard Günther
 E: rguenth@tat.physik.uni-tuebingen.de
 W: http://www.tat.physik.uni-tuebingen.de/~rguenth
 P: 2048/2E829319 2F 83 FC 93 E9 E4 19 E2  93 7A 32 42 45 37 23 57
 D: binfmt_misc
-S: 72074 Tübingen
+S: 72074 Tübingen
 S: Germany
 
 N: Justin Guyett
@@ -1287,7 +1287,7 @@ N: Bruno Haible
 E: haible@ma2s2.mathematik.uni-karlsruhe.de
 D: SysV FS, shm swapping, memory management fixes
 S: 17 rue Danton
-S: F - 94270 Le Kremlin-Bicêtre
+S: F - 94270 Le Kremlin-Bicêtre
 S: France
 
 N: Greg Hankins
@@ -1701,7 +1701,7 @@ S: Czech Republic
 N: Jakob Kemi
 E: jakob.kemi@telia.com
 D: V4L W9966 Webcam driver
-S: Forsbyvägen 33
+S: Forsbyvägen 33
 S: 74143 Knivsta
 S: Sweden
 
@@ -2065,7 +2065,7 @@ D: misc. kernel hacking and debugging
 S: Cambridge, MA 02139
 S: USA
 
-N: Martin von Löwis
+N: Martin von Löwis
 E: loewis@informatik.hu-berlin.de
 D: script binary format
 D: NTFS driver
@@ -2142,7 +2142,7 @@ S: PO BOX 220, HFX. CENTRAL
 S: Halifax, Nova Scotia
 S: Canada B3J 3C8
 
-N: Kai Mäkisara
+N: Kai Mäkisara
 E: Kai.Makisara@kolumbus.fi
 D: SCSI Tape Driver
 
@@ -2580,10 +2580,9 @@ S: Australia
 
 N: Miguel Ojeda Sandonis
 E: maxextreme@gmail.com
-D: Author: Auxiliary LCD Controller driver (ks0108)
-D: Author: Auxiliary LCD driver (cfag12864b)
-D: Author: Auxiliary LCD framebuffer driver (cfag12864bfb)
-D: Maintainer: Auxiliary display drivers tree (drivers/auxdisplay/*)
+W: http://maxextreme.googlepages.com/
+D: Author of the ks0108, cfag12864b and cfag12864bfb auxiliary display drivers.
+D: Maintainer of the auxiliary display drivers tree (drivers/auxdisplay/*)
 S: C/ Mieses 20, 9-B
 S: Valladolid 47009
 S: Spain
@@ -2786,10 +2785,10 @@ N: Juan Quintela
 E: quintela@fi.udc.es
 D: Memory Management hacking
 S: LFCIA
-S: Departamento de Computación
-S: Universidade da Coruña
+S: Departamento de Computación
+S: Universidade da Coruña
 S: E-15071
-S: A Coruña
+S: A Coruña
 S: Spain
 
 N: Augusto Cesar Radtke
@@ -2940,7 +2939,7 @@ E: aris@cathedrallabs.org
 D: Support for EtherExpress 10 ISA (i82595) in eepro driver
 D: User level driver support for input
 S: R. Jose Serrato, 130 - Santa Candida
-S: 82640-320 - Curitiba - Paraná
+S: 82640-320 - Curitiba - Paraná
 S: Brazil
 
 N: Alessandro Rubini
@@ -3346,15 +3345,15 @@ P: 1024D/D0FE7AFB B24A 65C9 1D71 2AC2 DE87  CA26 189B 9946 D0FE 7AFB
 D: rcutorture maintainer
 D: lock annotations, finding and fixing lock bugs
 
-N: Winfried Trümper
+N: Winfried Trümper
 E: winni@xpilot.org
 W: http://www.shop.de/~winni/
 D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages)
 D: CD-Writing HOWTO, various mini-HOWTOs
 D: One-week tutorials on Linux twice a year (free of charge)
-D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests
+D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests
 S: Tacitusstr. 6
-S: D-50968 Köln
+S: D-50968 Köln
 
 N: Tsu-Sheng Tsao
 E: tsusheng@scf.usc.edu
index 8195c4e0d0a1002b75c55e78f43dd5855f9b3c5f..8ffd28bf65982b575b8d97013aade37fbecd1645 100644 (file)
@@ -6,7 +6,7 @@ Description:
        races, contains a naming policy within the kernel that is
        against the LSB, and can be replaced by using udev.
        The files fs/devfs/*, include/linux/devfs_fs*.h were removed,
-       along with the the assorted devfs function calls throughout the
+       along with the assorted devfs function calls throughout the
        kernel tree.
 
 Users:
index 9069189e78ef3c7ec272bbeebda291d509b2b66a..afc2867758914e952e9bc33f2cce4751acc70cfc 100644 (file)
@@ -160,6 +160,21 @@ supply of new-lines on your screen is not a renewable resource (think
 25-line terminal screens here), you have more empty lines to put
 comments on.
 
+Do not unnecessarily use braces where a single statement will do.
+
+if (condition)
+       action();
+
+This does not apply if one branch of a conditional statement is a single
+statement. Use braces in both branches.
+
+if (condition) {
+       do_this();
+       do_that();
+} else {
+       otherwise();
+}
+
                3.1:  Spaces
 
 Linux kernel style for use of spaces depends (mostly) on
@@ -625,7 +640,7 @@ language.
 
 There appears to be a common misperception that gcc has a magic "make me
 faster" speedup option called "inline". While the use of inlines can be
-appropriate (for example as a means of replacing macros, see Chapter 11), it
+appropriate (for example as a means of replacing macros, see Chapter 12), it
 very often is not. Abundant use of the inline keyword leads to a much bigger
 kernel, which in turn slows the system as a whole down, due to a bigger
 icache footprint for the CPU and simply because there is less memory
index 10b5cd6c54a03f1cf23a67eb227af37aa92b2edb..6fd1646d3204d8b17555ac436667b5ffe1b9de95 100644 (file)
@@ -43,6 +43,7 @@ pdfdocs: $(PDF)
 
 HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
 htmldocs: $(HTML)
+       $(call build_main_index)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
@@ -132,10 +133,17 @@ quiet_cmd_db2pdf = PDF      $@
 %.pdf : %.xml
        $(call cmd,db2pdf)
 
+
+main_idx = Documentation/DocBook/index.html
+build_main_index = rm -rf $(main_idx) && \
+                  echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \
+                  echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \
+                  cat $(HTML) >> $(main_idx)
+
 quiet_cmd_db2html = HTML   $@
       cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
                echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
-         Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
+        $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
 
 %.html:        %.xml
        @(which xmlto > /dev/null 2>&1) || \
index b61dfc79e1b87904b4280ad8a9fba47b733e0bef..38f88b6ae405a16606134db8aedf7a89ccf8e643 100644 (file)
@@ -84,6 +84,10 @@ X!Iinclude/linux/kobject.h
 !Ekernel/rcupdate.c
      </sect1>
 
+     <sect1><title>Device Resource Management</title>
+!Edrivers/base/devres.c
+     </sect1>
+
   </chapter>
 
   <chapter id="adt">
@@ -576,4 +580,67 @@ X!Idrivers/video/console/fonts.c
 !Edrivers/input/ff-core.c
 !Edrivers/input/ff-memless.c
   </chapter>
+
+  <chapter id="spi">
+      <title>Serial Peripheral Interface (SPI)</title>
+  <para>
+       SPI is the "Serial Peripheral Interface", widely used with
+       embedded systems because it is a simple and efficient
+       interface:  basically a multiplexed shift register.
+       Its three signal wires hold a clock (SCK, often in the range
+       of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
+       a "Master In, Slave Out" (MISO) data line.
+       SPI is a full duplex protocol; for each bit shifted out the
+       MOSI line (one per clock) another is shifted in on the MISO line.
+       Those bits are assembled into words of various sizes on the
+       way to and from system memory.
+       An additional chipselect line is usually active-low (nCS);
+       four signals are normally used for each peripheral, plus
+       sometimes an interrupt.
+  </para>
+  <para>
+       The SPI bus facilities listed here provide a generalized
+       interface to declare SPI busses and devices, manage them
+       according to the standard Linux driver model, and perform
+       input/output operations.
+       At this time, only "master" side interfaces are supported,
+       where Linux talks to SPI peripherals and does not implement
+       such a peripheral itself.
+       (Interfaces to support implementing SPI slaves would
+       necessarily look different.)
+  </para>
+  <para>
+       The programming interface is structured around two kinds of driver,
+       and two kinds of device.
+       A "Controller Driver" abstracts the controller hardware, which may
+       be as simple as a set of GPIO pins or as complex as a pair of FIFOs
+       connected to dual DMA engines on the other side of the SPI shift
+       register (maximizing throughput).  Such drivers bridge between
+       whatever bus they sit on (often the platform bus) and SPI, and
+       expose the SPI side of their device as a
+       <structname>struct spi_master</structname>.
+       SPI devices are children of that master, represented as a
+       <structname>struct spi_device</structname> and manufactured from
+       <structname>struct spi_board_info</structname> descriptors which
+       are usually provided by board-specific initialization code.
+       A <structname>struct spi_driver</structname> is called a
+       "Protocol Driver", and is bound to a spi_device using normal
+       driver model calls.
+  </para>
+  <para>
+       The I/O model is a set of queued messages.  Protocol drivers
+       submit one or more <structname>struct spi_message</structname>
+       objects, which are processed and completed asynchronously.
+       (There are synchronous wrappers, however.)  Messages are
+       built from one or more <structname>struct spi_transfer</structname>
+       objects, each of which wraps a full duplex SPI transfer.
+       A variety of protocol tweaking options are needed, because
+       different chips adopt very different policies for how they
+       use the bits transferred with SPI.
+  </para>
+!Iinclude/linux/spi/spi.h
+!Fdrivers/spi/spi.c spi_register_board_info
+!Edrivers/spi/spi.c
+  </chapter>
+
 </book>
index 3ff39bafc00e1be692e6f351a6516fe692ac002d..94f21361e0edaa2778cfa4e8b1e4b5ab2cc0d1cf 100644 (file)
   <chapter id="usage">
        <title>Usage</title>
        <para>
-               This chapter provides examples how to use the library.
+               This chapter provides examples of how to use the library.
        </para>
        <sect1>
                <title>Initializing</title>
                <para>
-                       The init function init_rs returns a pointer to a
+                       The init function init_rs returns a pointer to an
                        rs decoder structure, which holds the necessary
                        information for encoding, decoding and error correction
                        with the given polynomial. It either uses an existing
 static struct rs_control *rs_decoder;
 
 /* Symbolsize is 10 (bits)
- * Primitve polynomial is x^10+x^3+1
+ * Primitive polynomial is x^10+x^3+1
  * first consecutive root is 0
- * primitve element to generate roots = 1
- * generator polinomial degree (number of roots) = 6
+ * primitive element to generate roots = 1
+ * generator polynomial degree (number of roots) = 6
  */
 rs_decoder = init_rs (10, 0x409, 0, 1, 6);
                </programlisting>
@@ -116,12 +116,12 @@ rs_decoder = init_rs (10, 0x409, 0, 1, 6);
                </para>
                <para>
                        The expanded data can be inverted on the fly by
-                       providing a non zero inversion mask. The expanded data is
+                       providing a non-zero inversion mask. The expanded data is
                        XOR'ed with the mask. This is used e.g. for FLASH
                        ECC, where the all 0xFF is inverted to an all 0x00.
                        The Reed-Solomon code for all 0x00 is all 0x00. The
                        code is inverted before storing to FLASH so it is 0xFF
-                       too. This prevent's that reading from an erased FLASH
+                       too. This prevents that reading from an erased FLASH
                        results in ECC errors.
                </para>
                <para>
@@ -273,7 +273,7 @@ free_rs(rs_decoder);
                May be used under the terms of the GNU General Public License (GPL)
        </programlisting>
        <para>
-               The wrapper functions and interfaces are written by Thomas Gleixner
+               The wrapper functions and interfaces are written by Thomas Gleixner.
        </para>
        <para>
                Many users have provided bugfixes, improvements and helping hands for testing.
index d389388c733e6c718f87de37a885132af6519930..0d8240774fca2d3bc00454ce5bc65ec20fe09e2e 100644 (file)
@@ -480,8 +480,8 @@ The PCI stack provides 3 possible levels of MSI disabling:
 
 6.1. Disabling MSI on a single device
 
-Under some circumstances, it might be required to disable MSI on a
-single device, It may be achived by either not calling pci_enable_msi()
+Under some circumstances it might be required to disable MSI on a
+single device.  This may be achieved by either not calling pci_enable_msi()
 or all, or setting the pci_dev->no_msi flag before (most of the time
 in a quirk).
 
@@ -492,7 +492,7 @@ being able to route MSI between busses. In this case, MSI have to be
 disabled on all devices behind this bridge. It is achieves by setting
 the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge
 subordinate bus. There is no need to set the same flag on bridges that
-are below the broken brigde. When pci_enable_msi() is called to enable
+are below the broken bridge. When pci_enable_msi() is called to enable
 MSI on a device, pci_msi_supported() takes care of checking the NO_MSI
 flag in all parent busses of the device.
 
index bd23dc0bc0c7c9ced4323b761396377d700fad83..6491b2c45dd48af654e411278559d537ec237330 100644 (file)
@@ -80,3 +80,7 @@ kernel patches.
 23: Tested after it has been merged into the -mm patchset to make sure
     that it still works with all of the other queued patches and various
     changes in the VM, VFS, and other subsystems.
+
+24: Avoid whitespace damage such as indenting with spaces or whitespace
+    at the end of lines.  You can test this by feeding the patch to
+    "git apply --check --whitespace=error-all"
index 58bead05eabb057fb777bdd5fe7a56b44f35b0e0..d7e26427e426929a35b339c35799c476c8f3573b 100644 (file)
@@ -87,6 +87,21 @@ Clarity:     It helps if anyone can see how to fix the driver. It helps
                driver that intentionally obfuscates how the hardware works
                it will go in the bitbucket.
 
+PM support:    Since Linux is used on many portable and desktop systems, your
+               driver is likely to be used on such a system and therefore it
+               should support basic power management by implementing, if
+               necessary, the .suspend and .resume methods used during the
+               system-wide suspend and resume transitions.  You should verify
+               that your driver correctly handles the suspend and resume, but
+               if you are unable to ensure that, please at least define the
+               .suspend method returning the -ENOSYS ("Function not
+               implemented") error.  You should also try to make sure that your
+               driver uses as little power as possible when it's not doing
+               anything.  For the driver testing instructions see
+               Documentation/power/drivers-testing.txt and for a relatively
+               complete overview of the power management issues related to
+               drivers see Documentation/power/devices.txt .
+
 Control:       In general if there is active maintainance of a driver by
                the author then patches will be redirected to them unless
                they are totally obvious and without need of checking.
index b0d0043f7c46cdde154f6be25fe33ba3a98b645d..a417b25fb1aa40f62234c222db0a4be1cfaa938d 100644 (file)
@@ -363,7 +363,8 @@ area or subsystem of the kernel is being patched.
 The "summary phrase" in the email's Subject should concisely
 describe the patch which that email contains.  The "summary
 phrase" should not be a filename.  Do not use the same "summary
-phrase" for every patch in a whole patch series.
+phrase" for every patch in a whole patch series (where a "patch
+series" is an ordered sequence of multiple, related patches).
 
 Bear in mind that the "summary phrase" of your email becomes
 a globally-unique identifier for that patch.  It propagates
index e9126e794ed7c04c19c42fb318dd36295d8806da..71acc28ed0d1b8b6b3692362bcf9d6ef4d7fcd02 100644 (file)
@@ -61,8 +61,6 @@ __u64 stime, utime;
 #define MAX_MSG_SIZE   1024
 /* Maximum number of cpus expected to be specified in a cpumask */
 #define MAX_CPUS       32
-/* Maximum length of pathname to log file */
-#define MAX_FILENAME   256
 
 struct msgtemplate {
        struct nlmsghdr n;
@@ -72,6 +70,16 @@ struct msgtemplate {
 
 char cpumask[100+6*MAX_CPUS];
 
+static void usage(void)
+{
+       fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] "
+                       "[-m cpumask] [-t tgid] [-p pid]\n");
+       fprintf(stderr, "  -d: print delayacct stats\n");
+       fprintf(stderr, "  -i: print IO accounting (works only with -p)\n");
+       fprintf(stderr, "  -l: listen forever\n");
+       fprintf(stderr, "  -v: debug on\n");
+}
+
 /*
  * Create a raw netlink socket and bind
  */
@@ -221,13 +229,13 @@ int main(int argc, char *argv[])
        int count = 0;
        int write_file = 0;
        int maskset = 0;
-       char logfile[128];
+       char *logfile = NULL;
        int loop = 0;
 
        struct msgtemplate msg;
 
        while (1) {
-               c = getopt(argc, argv, "diw:r:m:t:p:v:l");
+               c = getopt(argc, argv, "diw:r:m:t:p:vl");
                if (c < 0)
                        break;
 
@@ -241,7 +249,7 @@ int main(int argc, char *argv[])
                        print_io_accounting = 1;
                        break;
                case 'w':
-                       strncpy(logfile, optarg, MAX_FILENAME);
+                       logfile = strdup(optarg);
                        printf("write to file %s\n", logfile);
                        write_file = 1;
                        break;
@@ -277,7 +285,7 @@ int main(int argc, char *argv[])
                        loop = 1;
                        break;
                default:
-                       printf("Unknown option %d\n", c);
+                       usage();
                        exit(-1);
                }
        }
index 72c93de8cd4e2ef306aedca82034fe1e207b7d45..0d3dbf1099bcc90cae1b364002ef32e15dcdc06a 100644 (file)
@@ -149,7 +149,7 @@ So, what's changed?
 
 3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
 
-4. Direct access to SA1111 INTPOL is depreciated.  Use set_irq_type instead.
+4. Direct access to SA1111 INTPOL is deprecated.  Use set_irq_type instead.
 
 5. A handler is expected to perform any necessary acknowledgement of the
    parent IRQ via the correct chip specific function.  For instance, if
index d6b1de92b1115e37dda8ca8aae4d6bcb34992f2c..f4a7b22c8664be44c398ab4325c951b084b965e8 100644 (file)
@@ -23,7 +23,7 @@ Support
 
     http://handhelds.org/moin/moin.cgi/HpIpaqH1940
 
-  Herbert Pötzl pages:
+  Herbert Pötzl pages:
 
     http://vserver.13thfloor.at/H1940/
 
@@ -32,7 +32,7 @@ Maintainers
 -----------
 
   This project is being maintained and developed by a variety
-  of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
+  of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
 
   Thanks to the many others who have also provided support.
 
index 3572b98f45b8378460dc75bbe730571c90e4172c..b714183d412515abc2a39c32e898cdab52d21eff 100644 (file)
@@ -78,9 +78,9 @@ Select (17)------------------------------(16) Data / Instruction
 Ground (18)---[GND]              [+5v]---(19) LED +
 Ground (19)---[GND]
 Ground (20)---[GND]              E    A             Values:
-Ground (21)---[GND]       [GND]---[P1]---(18) Vee    · R = Resistor = 22 ohm
-Ground (22)---[GND]                |                 · P1 = Preset = 10 Kohm
-Ground (23)---[GND]       ----   S ------( 3) V0     · P2 = Preset = 1 Kohm
+Ground (21)---[GND]       [GND]---[P1]---(18) Vee    - R = Resistor = 22 ohm
+Ground (22)---[GND]                |                 - P1 = Preset = 10 Kohm
+Ground (23)---[GND]       ----   S ------( 3) V0     - P2 = Preset = 1 Kohm
 Ground (24)---[GND]       |  |
 Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED -
 
index d097f09ee15ad21c1dc56c2f0d75e06e156368ff..f609ebf9c78fe4023d87a50c0fa73d415846d4b1 100644 (file)
@@ -113,4 +113,4 @@ cause unexpected behaviour and can be a security hazard.
 There is a web page about binfmt_misc at
 http://www.tat.physik.uni-tuebingen.de/~rguenth/linux/binfmt_misc.html
 
-Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
+Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
index 96ccf681075e9d5a95c62b402ef11646aaf8cc02..1b930ef5a079a9f9dcbceca52851e6c14cd722ee 100644 (file)
@@ -6,10 +6,10 @@ Intro
 -----
 
 With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io
-priorities is supported for reads on files. This enables users to io nice
-processes or process groups, similar to what has been possible to cpu
-scheduling for ages. This document mainly details the current possibilites
-with cfq, other io schedulers do not support io priorities so far.
+priorities are supported for reads on files.  This enables users to io nice
+processes or process groups, similar to what has been possible with cpu
+scheduling for ages.  This document mainly details the current possibilities
+with cfq; other io schedulers do not support io priorities thus far.
 
 Scheduling classes
 ------------------
index f74affe5c8297f58b4d36dfac566e7411899f2c5..e65736c6b8bc890448c81de9ade727cee9f43ca4 100644 (file)
@@ -22,14 +22,21 @@ This driver is known to work with the following cards:
        * SA E200i
        * SA E500
 
-If nodes are not already created in the /dev/cciss directory, run as root:
+Detecting drive failures:
+-------------------------
 
-# cd /dev
-# ./MAKEDEV cciss
+To get the status of logical volumes and to detect physical drive
+failures, you can use the cciss_vol_status program found here:
+http://cciss.sourceforge.net/#cciss_utils
 
 Device Naming:
 --------------
 
+If nodes are not already created in the /dev/cciss directory, run as root:
+
+# cd /dev
+# ./MAKEDEV cciss
+
 You need some entries in /dev for the cciss device.  The MAKEDEV script
 can make device nodes for you automatically.  Currently the device setup
 is as follows:
index 53d62c1e1c94f68531756d20c80e50c48aa718b3..fc647492e940539be1f37b02335ac1bbc7829820 100644 (file)
@@ -17,7 +17,7 @@ Contents
 
 1. Introduction
 
-cpufreq-stats is a driver that provices CPU frequency statistics for each CPU.
+cpufreq-stats is a driver that provides CPU frequency statistics for each CPU.
 These statistics are provided in /sysfs as a bunch of read_only interfaces. This
 interface (when configured) will appear in a separate directory under cpufreq
 in /sysfs (<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU.
index cc60d29b954cd394ccd1eba1c27b06bfc049302d..b6d24c22274b8dfb0ea28c3e841594779f5b20e7 100644 (file)
@@ -217,14 +217,17 @@ Q: What happens when a CPU is being logically offlined?
 A: The following happen, listed in no particular order :-)
 
 - A notification is sent to in-kernel registered modules by sending an event
-  CPU_DOWN_PREPARE
+  CPU_DOWN_PREPARE or CPU_DOWN_PREPARE_FROZEN, depending on whether or not the
+  CPU is being offlined while tasks are frozen due to a suspend operation in
+  progress
 - All process is migrated away from this outgoing CPU to a new CPU
 - All interrupts targeted to this CPU is migrated to a new CPU
 - timers/bottom half/task lets are also migrated to a new CPU
 - Once all services are migrated, kernel calls an arch specific routine
   __cpu_disable() to perform arch specific cleanup.
 - Once this is successful, an event for successful cleanup is sent by an event
-  CPU_DEAD.
+  CPU_DEAD (or CPU_DEAD_FROZEN if tasks are frozen due to a suspend while the
+  CPU is being offlined).
 
   "It is expected that each service cleans up when the CPU_DOWN_PREPARE
   notifier is called, when CPU_DEAD is called its expected there is nothing
@@ -242,9 +245,11 @@ A: This is what you would need in your kernel code to receive notifications.
 
                switch (action) {
                case CPU_ONLINE:
+               case CPU_ONLINE_FROZEN:
                        foobar_online_action(cpu);
                        break;
                case CPU_DEAD:
+               case CPU_DEAD_FROZEN:
                        foobar_dead_action(cpu);
                        break;
                }
index 9b84b805ab759114fc1b7ccb9d1bd5af3ecfefb0..a2ac6d2947932022ddd8b6d906d13bd5882a0719 100644 (file)
@@ -177,7 +177,7 @@ Portions of this API were derived from the following projects:
 and;
   
   Nettle (http://www.lysator.liu.se/~nisse/nettle/)
-    Niels Möller
+    Niels Möller
 
 Original developers of the crypto algorithms:
 
@@ -200,8 +200,8 @@ SHA1 algorithm contributors:
   
 DES algorithm contributors:
   Raimar Falke
-  Gisle Sælensminde
-  Niels Möller
+  Gisle Sælensminde
+  Niels Möller
 
 Blowfish algorithm contributors:
   Herbert Valerio Riedel
diff --git a/Documentation/device-mapper/delay.txt b/Documentation/device-mapper/delay.txt
new file mode 100644 (file)
index 0000000..15adc55
--- /dev/null
@@ -0,0 +1,26 @@
+dm-delay
+========
+
+Device-Mapper's "delay" target delays reads and/or writes
+and maps them to different devices.
+
+Parameters:
+    <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
+
+With separate write parameters, the first set is only used for reads.
+Delays are specified in milliseconds.
+
+Example scripts
+===============
+[[
+#!/bin/sh
+# Create device delaying rw operation for 500ms
+echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
+]]
+
+[[
+#!/bin/sh
+# Create device delaying only write operation for 500ms and
+# splitting reads and writes to different devices $1 $2
+echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
+]]
index f7c9262b2dc8543aa2808931e2cb5c316efacb06..19c4a6e136760750365483d49751edb4853daad6 100644 (file)
@@ -16,7 +16,7 @@ host bridges to peripheral buses, and most controllers integrated
 into system-on-chip platforms.  What they usually have in common
 is direct addressing from a CPU bus.  Rarely, a platform_device will
 be connected through a segment of some other kind of bus; but its
-registers will still be directly addressible.
+registers will still be directly addressable.
 
 Platform devices are given a name, used in driver binding, and a
 list of resources such as addresses and IRQs.
@@ -125,7 +125,7 @@ three different ways to find such a match:
       usually register later during booting, or by module loading.
 
     - Registering a driver using platform_driver_probe() works just like
-      using platform_driver_register(), except that the the driver won't
+      using platform_driver_register(), except that the driver won't
       be probed later if another device registers.  (Which is OK, since
       this interface is only for use with non-hotpluggable devices.)
 
index 46b78b7331c27e4f0fe131336f08c25235138ad5..bf2a9cdfe7bbc2077001308ae40089a6fa33ca07 100644 (file)
@@ -228,5 +228,5 @@ Patches, comments and suggestions are very very welcome.
 
    Ulf Hermenau for helping me out with traditional chinese.
 
-   André Smoktun and Christian Frömmel for supporting me with
+   André Smoktun and Christian Frömmel for supporting me with
     hardware and listening to my problems very patiently.
index 4c33cced5f657fd25be698d01a25473a11c0dfd4..4865addebe1cb92145d9f88c1de3c1cf586c8f4a 100644 (file)
@@ -66,7 +66,7 @@ Michael Dreher <michael@5dot1.de>
 Andreas 'randy' Weinberger
   for the support of the Fujitsu-Siemens Activy budget DVB-S
 
-Kenneth Aafløy <ke-aa@frisurf.no>
+Kenneth Aafløy <ke-aa@frisurf.no>
   for adding support for Typhoon DVB-S budget card
 
 Ernst Peinlich <e.peinlich@inode.at>
diff --git a/Documentation/fb/arkfb.txt b/Documentation/fb/arkfb.txt
new file mode 100644 (file)
index 0000000..e8487a9
--- /dev/null
@@ -0,0 +1,68 @@
+
+       arkfb - fbdev driver for ARK Logic chips
+       ========================================
+
+
+Supported Hardware
+==================
+
+       ARK 2000PV chip
+       ICS 5342 ramdac
+
+       - only BIOS initialized VGA devices supported
+       - probably not working on big endian
+
+
+Supported Features
+==================
+
+       *  4 bpp pseudocolor modes (with 18bit palette, two variants)
+       *  8 bpp pseudocolor mode (with 18bit palette)
+       * 16 bpp truecolor modes (RGB 555 and RGB 565)
+       * 24 bpp truecolor mode (RGB 888)
+       * 32 bpp truecolor mode (RGB 888)
+       * text mode (activated by bpp = 0)
+       * doublescan mode variant (not available in text mode)
+       * panning in both directions
+       * suspend/resume support
+
+Text mode is supported even in higher resolutions, but there is limitation to
+lower pixclocks (i got maximum about 70 MHz, it is dependent on specific
+hardware). This limitation is not enforced by driver. Text mode supports 8bit
+wide fonts only (hardware limitation) and 16bit tall fonts (driver
+limitation). Unfortunately character attributes (like color) in text mode are
+broken for unknown reason, so its usefulness is limited.
+
+There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
+packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
+with interleaved planes (1 byte interleave), MSB first. Both modes support
+8bit wide fonts only (driver limitation).
+
+Suspend/resume works on systems that initialize video card during resume and
+if device is active (for example used by fbcon).
+
+
+Missing Features
+================
+(alias TODO list)
+
+       * secondary (not initialized by BIOS) device support
+       * big endian support
+       * DPMS support
+       * MMIO support
+       * interlaced mode variant
+       * support for fontwidths != 8 in 4 bpp modes
+       * support for fontheight != 16 in text mode
+       * hardware cursor
+       * vsync synchronization
+       * feature connector support
+       * acceleration support (8514-like 2D)
+
+
+Known bugs
+==========
+
+       * character attributes (and cursor) in text mode are broken
+
+--
+Ondrej Zajicek <santiago@crfreenet.org>
index 069262fb619dfce82735bef6e639aa6abf6fc8f5..b605204fcfe1c797ab25c1a4a6cee09719f0ab37 100644 (file)
@@ -54,8 +54,8 @@ Accepted options:
 
 noaccel  - do not use acceleration engine. It is default.
 accel    - use acceleration engine. Not finished.
-vmode:x  - chooses PowerMacintosh video mode <x>. Depreciated.
-cmode:x  - chooses PowerMacintosh colour mode <x>. Depreciated.
+vmode:x  - chooses PowerMacintosh video mode <x>. Deprecated.
+cmode:x  - chooses PowerMacintosh colour mode <x>. Deprecated.
 <XxX@X>  - selects startup videomode. See modedb.txt for detailed
           explanation. Default is 640x480x8bpp.
 
diff --git a/Documentation/fb/deferred_io.txt b/Documentation/fb/deferred_io.txt
new file mode 100644 (file)
index 0000000..73cf9fb
--- /dev/null
@@ -0,0 +1,75 @@
+Deferred IO
+-----------
+
+Deferred IO is a way to delay and repurpose IO. It uses host memory as a
+buffer and the MMU pagefault as a pretrigger for when to perform the device
+IO. The following example may be a useful explaination of how one such setup
+works:
+
+- userspace app like Xfbdev mmaps framebuffer
+- deferred IO and driver sets up nopage and page_mkwrite handlers
+- userspace app tries to write to mmaped vaddress
+- we get pagefault and reach nopage handler
+- nopage handler finds and returns physical page
+- we get page_mkwrite where we add this page to a list
+- schedule a workqueue task to be run after a delay
+- app continues writing to that page with no additional cost. this is
+  the key benefit.
+- the workqueue task comes in and mkcleans the pages on the list, then
+ completes the work associated with updating the framebuffer. this is
+  the real work talking to the device.
+- app tries to write to the address (that has now been mkcleaned)
+- get pagefault and the above sequence occurs again
+
+As can be seen from above, one benefit is roughly to allow bursty framebuffer
+writes to occur at minimum cost. Then after some time when hopefully things
+have gone quiet, we go and really update the framebuffer which would be
+a relatively more expensive operation.
+
+For some types of nonvolatile high latency displays, the desired image is
+the final image rather than the intermediate stages which is why it's okay
+to not update for each write that is occuring.
+
+It may be the case that this is useful in other scenarios as well. Paul Mundt
+has mentioned a case where it is beneficial to use the page count to decide
+whether to coalesce and issue SG DMA or to do memory bursts.
+
+Another one may be if one has a device framebuffer that is in an usual format,
+say diagonally shifting RGB, this may then be a mechanism for you to allow
+apps to pretend to have a normal framebuffer but reswizzle for the device
+framebuffer at vsync time based on the touched pagelist.
+
+How to use it: (for applications)
+---------------------------------
+No changes needed. mmap the framebuffer like normal and just use it.
+
+How to use it: (for fbdev drivers)
+----------------------------------
+The following example may be helpful.
+
+1. Setup your structure. Eg:
+
+static struct fb_deferred_io hecubafb_defio = {
+       .delay          = HZ,
+       .deferred_io    = hecubafb_dpy_deferred_io,
+};
+
+The delay is the minimum delay between when the page_mkwrite trigger occurs
+and when the deferred_io callback is called. The deferred_io callback is
+explained below.
+
+2. Setup your deferred IO callback. Eg:
+static void hecubafb_dpy_deferred_io(struct fb_info *info,
+                               struct list_head *pagelist)
+
+The deferred_io callback is where you would perform all your IO to the display
+device. You receive the pagelist which is the list of pages that were written
+to during the delay. You must not modify this list. This callback is called
+from a workqueue.
+
+3. Call init
+       info->fbdefio = &hecubafb_defio;
+       fb_deferred_io_init(info);
+
+4. Call cleanup
+       fb_deferred_io_cleanup(info);
index 610e7801207b5248a5f32e6ccffb921e1ff010f6..b3e3a035683993edc8391cefd11ea3ef6be9eb08 100644 (file)
@@ -215,11 +215,11 @@ vertical retrace time is the sum of the upper margin, the lower margin and the
 vsync length.
 
   +----------+---------------------------------------------+----------+-------+
-  |          |                ^                            |          |       |
+  |          |                                            |          |       |
   |          |                |upper_margin                |          |       |
-  |          |                ¥                            |          |       |
+  |          |                                            |          |       |
   +----------###############################################----------+-------+
-  |          #                ^                            #          |       |
+  |          #                                            #          |       |
   |          #                |                            #          |       |
   |          #                |                            #          |       |
   |          #                |                            #          |       |
@@ -238,15 +238,15 @@ vsync length.
   |          #                |                            #          |       |
   |          #                |                            #          |       |
   |          #                |                            #          |       |
-  |          #                ¥                            #          |       |
+  |          #                                            #          |       |
   +----------###############################################----------+-------+
-  |          |                ^                            |          |       |
+  |          |                                            |          |       |
   |          |                |lower_margin                |          |       |
-  |          |                ¥                            |          |       |
+  |          |                                            |          |       |
   +----------+---------------------------------------------+----------+-------+
-  |          |                ^                            |          |       |
+  |          |                                            |          |       |
   |          |                |vsync_len                   |          |       |
-  |          |                ¥                            |          |       |
+  |          |                                            |          |       |
   +----------+---------------------------------------------+----------+-------+
 
 The frame buffer device expects all horizontal timings in number of dotclocks
index 759028545a7ee833c90c4726bcf9ff83c9337102..316ec9bb7debd5f79ac76e9cbbea5f957ba25e74 100644 (file)
@@ -17,7 +17,7 @@ How to use it?
 ==============
 
 Imacfb does not have any kind of autodetection of your machine.
-You have to add the fillowing kernel parameters in your elilo.conf:
+You have to add the following kernel parameters in your elilo.conf:
        Macbook :
                video=imacfb:macbook
        MacMini :
index 8a04c0da0c91b46c2aed8d311b0407365273db7c..2c97770bdbaa01b9fef902def986c1da818df12c 100644 (file)
@@ -35,10 +35,12 @@ Supported Features
        * suspend/resume support
        * DPMS support
 
-Text mode is supported even in higher resolutions, but there is limitation
-to lower pixclocks (maximum between 50-60 MHz, depending on specific hardware).
-This limitation is not enforced by driver. Text mode supports 8bit wide fonts
-only (hardware limitation) and 16bit tall fonts (driver limitation).
+Text mode is supported even in higher resolutions, but there is limitation to
+lower pixclocks (maximum usually between 50-60 MHz, depending on specific
+hardware, i get best results from plain S3 Trio32 card - about 75 MHz). This
+limitation is not enforced by driver. Text mode supports 8bit wide fonts only
+(hardware limitation) and 16bit tall fonts (driver limitation). Text mode
+support is broken on S3 Trio64 V2/DX.
 
 There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
 packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
@@ -73,6 +75,8 @@ Known bugs
 ==========
 
        * cursor disable in text mode doesn't work
+       * text mode broken on S3 Trio64 V2/DX
+
 
 --
 Ondrej Zajicek <santiago@crfreenet.org>
index df27f5bf15dbc4cef4e0285085b4adc2709b279a..550ca775a4cbbe78ef623a2d5c0ed96fc72d550e 100644 (file)
@@ -2,9 +2,9 @@
 Introduction
 
          This is a frame buffer device driver for 3dfx' Voodoo Graphics 
-       (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based 
+       (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based 
        video boards. It's highly experimental code, but is guaranteed to work
-       on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards,
+       on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards,
        and with me "between chair and keyboard". Some people tested other
        combinations and it seems that it works.
          The main page is located at <http://sstfb.sourceforge.net>, and if
diff --git a/Documentation/fb/vt8623fb.txt b/Documentation/fb/vt8623fb.txt
new file mode 100644 (file)
index 0000000..f654576
--- /dev/null
@@ -0,0 +1,64 @@
+
+       vt8623fb - fbdev driver for graphics core in VIA VT8623 chipset
+       ===============================================================
+
+
+Supported Hardware
+==================
+
+       VIA VT8623 [CLE266] chipset and its graphics core
+               (known as CastleRock or Unichrome)
+
+I tested vt8623fb on VIA EPIA ML-6000
+
+
+Supported Features
+==================
+
+       *  4 bpp pseudocolor modes (with 18bit palette, two variants)
+       *  8 bpp pseudocolor mode (with 18bit palette)
+       * 16 bpp truecolor mode (RGB 565)
+       * 32 bpp truecolor mode (RGB 888)
+       * text mode (activated by bpp = 0)
+       * doublescan mode variant (not available in text mode)
+       * panning in both directions
+       * suspend/resume support
+       * DPMS support
+
+Text mode is supported even in higher resolutions, but there is limitation to
+lower pixclocks (maximum about 100 MHz). This limitation is not enforced by
+driver. Text mode supports 8bit wide fonts only (hardware limitation) and
+16bit tall fonts (driver limitation).
+
+There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
+packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
+with interleaved planes (1 byte interleave), MSB first. Both modes support
+8bit wide fonts only (driver limitation).
+
+Suspend/resume works on systems that initialize video card during resume and
+if device is active (for example used by fbcon).
+
+
+Missing Features
+================
+(alias TODO list)
+
+       * secondary (not initialized by BIOS) device support
+       * MMIO support
+       * interlaced mode variant
+       * support for fontwidths != 8 in 4 bpp modes
+       * support for fontheight != 16 in text mode
+       * hardware cursor
+       * video overlay support
+       * vsync synchronization
+       * acceleration support (8514-like 2D, busmaster transfers)
+
+
+Known bugs
+==========
+
+       * cursor disable in text mode doesn't work
+
+
+--
+Ondrej Zajicek <santiago@crfreenet.org>
index 5f96cb33743e44d6a3f1ea1ba055150e9e88fb47..676b7981adb771d5185c5bedd4c286ebc81d66f3 100644 (file)
@@ -6,6 +6,14 @@ be removed from this file.
 
 ---------------------------
 
+What:  MXSER
+When:  December 2007
+Why:   Old mxser driver is obsoleted by the mxser_new. Give it some time yet
+       and remove it.
+Who:   Jiri Slaby <jirislaby@gmail.com>
+
+---------------------------
+
 What:  V4L2 VIDIOC_G_MPEGCOMP and VIDIOC_S_MPEGCOMP
 When:  October 2007
 Why:   Broken attempt to set MPEG compression parameters. These ioctls are
@@ -51,6 +59,15 @@ Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
 
 ---------------------------
 
+What:  old NCR53C9x driver
+When:  October 2007
+Why:   Replaced by the much better esp_scsi driver.  Actual low-level
+       driver can ported over almost trivially.
+Who:   David Miller <davem@davemloft.net>
+       Christoph Hellwig <hch@lst.de>
+
+---------------------------
+
 What:  Video4Linux API 1 ioctls and video_decoder.h from Video devices.
 When:  December 2006
 Why:   V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
@@ -117,18 +134,6 @@ Who:   Adrian Bunk <bunk@stusta.de>
 
 ---------------------------
 
-What:  Usage of invalid timevals in setitimer
-When:  March 2007
-Why:   POSIX requires to validate timevals in the setitimer call. This
-       was never done by Linux. The invalid (e.g. negative timevals) were
-       silently converted to more or less random timeouts and intervals.
-       Until the removal a per boot limited number of warnings is printed
-       and the timevals are sanitized.
-
-Who:   Thomas Gleixner <tglx@linutronix.de>
-
----------------------------
-
 What:  Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
        (temporary transition config option provided until then)
        The transition config option will also be removed at the same time.
@@ -156,7 +161,7 @@ Who:        Greg Kroah-Hartman <gregkh@suse.de>
 ---------------------------
 
 What:  Interrupt only SA_* flags
-When:  Januar 2007
+When:  September 2007
 Why:   The interrupt related SA_* flags are replaced by IRQF_* to move them
        out of the signal namespace.
 
@@ -323,3 +328,11 @@ Why:       Obsolete. The new i2c-gpio driver replaces all hardware-specific
 Who:   Jean Delvare <khali@linux-fr.org>
 
 ---------------------------
+
+What:  drivers depending on OSS_OBSOLETE
+When:  options in 2.6.23, code in 2.6.25
+Why:   obsolete OSS drivers
+Who:   Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
index 28bfea75bcf26151ac5594d131cbbc71d0dc93d0..d866551be03790c20a00b5f96c41f9226260bcfa 100644 (file)
@@ -15,6 +15,7 @@ prototypes:
        int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
+       char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
 
 locking rules:
        none have BKL
@@ -25,6 +26,7 @@ d_compare:    no              yes             no              no
 d_delete:      yes             no              yes             no
 d_release:     no              no              no              yes
 d_iput:                no              no              no              yes
+d_dname:       no              no              no              no
 
 --------------------------- inode_operations --------------------------- 
 prototypes:
@@ -52,7 +54,7 @@ ata *);
 
 locking rules:
        all may block, none have BKL
-               i_sem(inode)
+               i_mutex(inode)
 lookup:                yes
 create:                yes
 link:          yes (both)
@@ -72,7 +74,7 @@ setxattr:     yes
 getxattr:      no
 listxattr:     no
 removexattr:   yes
-       Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on
+       Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
        cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
        ->truncate() is never called directly - it's a callback, not a
@@ -459,7 +461,7 @@ doesn't take the BKL.
 ->read on directories probably must go away - we should just enforce -EISDIR
 in sys_read() and friends.
 
-->fsync() has i_sem on inode.
+->fsync() has i_mutex on inode.
 
 --------------------------- dquot_operations -------------------------------
 prototypes:
index 38aba03efc5e1451e91f63d3c9ea0afa3022d90f..fa45c3baed98a7b06418862ccab7d3a2d7a6f49a 100644 (file)
@@ -290,7 +290,7 @@ History
 2.07 More fixes for Warp Server. Now it really works
 2.08 Creating new files is not so slow on large disks
      An attempt to sync deleted file does not generate filesystem error
-2.09 Fixed error on extremly fragmented files
+2.09 Fixed error on extremely fragmented files
 
 
  vim: set textwidth=80:
index bae128663748ebcac0df61ab910827bfaf932f96..26ebde77e821cecf11062032dfec702513eecd66 100644 (file)
@@ -29,7 +29,13 @@ errors=continue              Keep going on a filesystem error.
 errors=remount-ro      Default. Remount the filesystem read-only on an error.
 errors=panic           Panic and halt the machine if an error occurs.
 
-Please send bugs, comments, cards and letters to shaggy@austin.ibm.com.
+uid=value      Override on-disk uid with specified value
+gid=value      Override on-disk gid with specified value
+umask=value    Override on-disk umask with specified octal value.  For
+               directories, the execute bit will be set if the corresponding
+               read bit is set.
+
+Please send bugs, comments, cards and letters to shaggy@linux.vnet.ibm.com.
 
 The JFS mailing list can be subscribed to by using the link labeled
 "Mail list Subscribe" at our web page http://jfs.sourceforge.net/
index 81779068b09bc4b63274460cf0a40977bf4b1bfd..8ee10ec882936d1725e948554da052b3c7d09426 100644 (file)
@@ -349,7 +349,7 @@ end of the line.
 Note the "Should sync?" parameter "nosync" means that the two mirrors are
 already in sync which will be the case on a clean shutdown of Windows.  If the
 mirrors are not clean, you can specify the "sync" option instead of "nosync"
-and the Device-Mapper driver will then copy the entirey of the "Source Device"
+and the Device-Mapper driver will then copy the entirety of the "Source Device"
 to the "Target Device" or if you specified multipled target devices to all of
 them.
 
index 3f4b226572e7fd39cea5cd6547dd80a2627f928b..8756a07f4dc34abf3368935f5abb7a1adee228ef 100644 (file)
@@ -229,7 +229,7 @@ Table 1-3: Kernel info in /proc
  mounts      Mounted filesystems                               
  net         Networking info (see text)                        
  partitions  Table of partitions known to the system           
- pci        Depreciated info of PCI bus (new way -> /proc/bus/pci/, 
+ pci        Deprecated info of PCI bus (new way -> /proc/bus/pci/,
              decoupled by lspci                                        (2.4)
  rtc         Real time clock                                   
  scsi        SCSI info (see text)                              
@@ -1138,6 +1138,13 @@ determine whether or not they are still functioning properly.
 Because the NMI watchdog shares registers with oprofile, by disabling the NMI
 watchdog, oprofile may have more registers to utilize.
 
+maps_protect
+------------
+
+Enables/Disables the protection of the per-process proc entries "maps" and
+"smaps".  When enabled, the contents of these files are visible only to
+readers that are allowed to ptrace() the given process.
+
 
 2.4 /proc/sys/vm - The virtual memory subsystem
 -----------------------------------------------
index 7fbb6ffe576910695a5aecabd21c1c428497304f..18d23f9a18c74663e1a7cbcc07232e7879945c5e 100644 (file)
@@ -351,7 +351,7 @@ 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 the relay
+to make sense, the consumer is responsible for notifying the relay
 interface 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
index 069cb10943001e92da62cd24c30000af5e50a930..fcc123ffa2523d2dc3d932ddb63c240cf9052840 100644 (file)
@@ -57,6 +57,13 @@ nonumtail=<bool> -- When creating 8.3 aliases, normally the alias will
                  currently exist in the directory, 'longfile.txt' will
                  be the short alias instead of 'longfi~1.txt'. 
                   
+usefree       -- Use the "free clusters" value stored on FSINFO. It'll
+                 be used to determine number of free clusters without
+                 scanning disk. But it's not used by default, because
+                 recent Windows don't update it correctly in some
+                 case. If you are sure the "free clusters" on FSINFO is
+                 correct, by this option you can avoid scanning disk.
+
 quiet         -- Stops printing certain warning messages.
 
 check=s|r|n   -- Case sensitivity checking setting.
index ea271f2d395400b82cd8023db74fed76d878ce06..a47cc819f37bb7f5535afbf2bf720766ae51dfdd 100644 (file)
@@ -827,7 +827,7 @@ This describes how a filesystem can overload the standard dentry
 operations. Dentries and the dcache are the domain of the VFS and the
 individual filesystem implementations. Device drivers have no business
 here. These methods may be set to NULL, as they are either optional or
-the VFS uses a default. As of kernel 2.6.13, the following members are
+the VFS uses a default. As of kernel 2.6.22, the following members are
 defined:
 
 struct dentry_operations {
@@ -837,6 +837,7 @@ struct dentry_operations {
        int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
+       char *(*d_dname)(struct dentry *, char *, int);
 };
 
   d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -859,6 +860,26 @@ struct dentry_operations {
        VFS calls iput(). If you define this method, you must call
        iput() yourself
 
+  d_dname: called when the pathname of a dentry should be generated.
+       Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay
+       pathname generation. (Instead of doing it when dentry is created,
+       its done only when the path is needed.). Real filesystems probably
+       dont want to use it, because their dentries are present in global
+       dcache hash, so their hash should be an invariant. As no lock is
+       held, d_dname() should not try to modify the dentry itself, unless
+       appropriate SMP safety is used. CAUTION : d_path() logic is quite
+       tricky. The correct way to return for example "Hello" is to put it
+       at the end of the buffer, and returns a pointer to the first char.
+       dynamic_dname() helper function is provided to take care of this.
+
+Example :
+
+static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
+{
+       return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
+                               dentry->d_inode->i_ino);
+}
+
 Each dentry has a pointer to its parent dentry, as well as a hash list
 of child dentries. Child dentries are basically like files in a
 directory.
index 6c0cef10eb4d95a9cfe48eed7ec27c0a3a160bee..3cc4010521a019562e68eb070aa83ad78b0e8c4b 100644 (file)
@@ -19,7 +19,7 @@ completely. With execute-in-place, read&write type operations are performed
 directly from/to the memory backed storage device. For file mappings, the
 storage device itself is mapped directly into userspace.
 
-This implementation was initialy written for shared memory segments between
+This implementation was initially written for shared memory segments between
 different virtual machines on s390 hardware to allow multiple machines to
 share the same binaries and libraries.
 
index 9304fb36ae8a91671693bde1fd2644b3085f42f2..b92bfd902a4e4e5784bf34561c189d5493e0f025 100644 (file)
@@ -126,5 +126,5 @@ GDB stub and the debugger:
 
 Furthermore, the GDB stub will intercept a number of exceptions automatically
 if they are caused by kernel execution. It will also intercept BUG() macro
-invokation.
+invocation.
 
index 473c689d79245761ae3c1ba353391f9277222656..f4327db2307e3105c57db9820b91036fc9be1b97 100644 (file)
@@ -80,7 +80,7 @@ temperature sensor inputs. Both the PWM output and the DAC output can be
 used to control fan speed. Usually only one of these two outputs will be
 used. Write the minimum PWM or DAC value to the appropriate control
 register. Then set the low temperature limit in the tmin values for each
-temperature sensor. The range of control is fixed at 20 °C, and the
+temperature sensor. The range of control is fixed at 20 Â°C, and the
 largest difference between current and tmin of the temperature sensors sets
 the control output. See the datasheet for several example circuits for
 controlling fan speed with the PWM and DAC outputs. The fan speed sensors
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp
new file mode 100644 (file)
index 0000000..870cda9
--- /dev/null
@@ -0,0 +1,36 @@
+Kernel driver coretemp
+======================
+
+Supported chips:
+  * All Intel Core family
+    Prefix: 'coretemp'
+    CPUID: family 0x6, models 0xe, 0xf
+    Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual
+               Volume 3A: System Programming Guide
+
+Author: Rudolf Marek
+
+Description
+-----------
+
+This driver permits reading temperature sensor embedded inside Intel Core CPU.
+Temperature is measured in degrees Celsius and measurement resolution is
+1 degree C. Valid temperatures are from 0 to TjMax degrees C, because
+the actual value of temperature register is in fact a delta from TjMax.
+
+Temperature known as TjMax is the maximum junction temperature of processor.
+Intel defines this temperature as 85C or 100C. At this temperature, protection
+mechanism will perform actions to forcibly cool down the processor. Alarm
+may be raised, if the temperature grows enough (more than TjMax) to trigger
+the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
+
+temp1_input     - Core temperature (in millidegrees Celsius).
+temp1_crit      - Maximum junction temperature  (in millidegrees Celsius).
+temp1_crit_alarm - Set when Out-of-spec bit is set, never clears.
+                  Correct CPU operation is no longer guaranteed.
+temp1_label     - Contains string "Core X", where X is processor
+                  number.
+
+The TjMax temperature is set to 85 degrees C if undocumented model specific
+register (UMSR) 0xee has bit 30 set. If not the TjMax is 100 degrees C as
+(sometimes) documented in processor datasheet.
index ce0881883bca8ce02479342cdd037dc3daf6dfef..229f8b7891859db136217bc4c6ed7ff60f00694f 100644 (file)
@@ -13,7 +13,7 @@ Supported chips:
 
 Authors:
         Frodo Looijaard <frodol@dds.nl>,
-        Kyösti Mälkki <kmalkki@cc.hut.fi>
+        Kyösti Mälkki <kmalkki@cc.hut.fi>
         Hong-Gunn Chew <hglinux@gunnet.org>
         Jean Delvare <khali@linux-fr.org>
 
index f7aad1489cb00a63ac675f11348f9b8d4cfa8e93..a04d1fe9269cc9f2e129de63a2cdd18625704bca 100644 (file)
@@ -45,7 +45,7 @@ Unconfirmed motherboards:
 The LM82 is confirmed to have been found on most AMD Geode reference
 designs and test platforms.
 
-The driver has been successfully tested by Magnus Forsström, who I'd
+The driver has been successfully tested by Magnus Forsström, who I'd
 like to thank here. More testers will be of course welcome.
 
 The fact that the LM83 is only scarcely used can be easily explained.
diff --git a/Documentation/hwmon/max6650 b/Documentation/hwmon/max6650
new file mode 100644 (file)
index 0000000..8be7beb
--- /dev/null
@@ -0,0 +1,53 @@
+Kernel driver max6650
+=====================
+
+Supported chips:
+  * Maxim 6650 / 6651
+    Prefix: 'max6650'
+    Addresses scanned: I2C 0x1b, 0x1f, 0x48, 0x4b
+    Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
+
+Authors:
+    Hans J. Koch <hjk@linutronix.de>
+    John Morris <john.morris@spirentcom.com>
+    Claus Gindhart <claus.gindhart@kontron.com>
+
+Description
+-----------
+
+This driver implements support for the Maxim 6650/6651
+
+The 2 devices are very similar, but the Maxim 6550 has a reduced feature
+set, e.g. only one fan-input, instead of 4 for the 6651.
+
+The driver is not able to distinguish between the 2 devices.
+
+The driver provides the following sensor accesses in sysfs:
+
+fan1_input     ro      fan tachometer speed in RPM
+fan2_input     ro      "
+fan3_input     ro      "
+fan4_input     ro      "
+fan1_target    rw      desired fan speed in RPM (closed loop mode only)
+pwm1_enable    rw      regulator mode, 0=full on, 1=open loop, 2=closed loop
+pwm1           rw      relative speed (0-255), 255=max. speed.
+                       Used in open loop mode only.
+fan1_div       rw      sets the speed range the inputs can handle. Legal
+                       values are 1, 2, 4, and 8. Use lower values for
+                       faster fans.
+
+Module parameters
+-----------------
+
+If your board has a BIOS that initializes the MAX6650/6651 correctly, you can
+simply load your module without parameters. It won't touch the configuration
+registers then. If your board BIOS doesn't initialize the chip, or you want
+different settings, you can set the following parameters:
+
+voltage_12V: 5=5V fan, 12=12V fan, 0=don't change
+prescaler: Possible values are 1,2,4,8,16, or 0 for don't change
+clock: The clock frequency in Hz of the chip the driver should assume [254000]
+
+Please have a look at the MAX6650/6651 data sheet and make sure that you fully
+understand the meaning of these parameters before you attempt to change them.
+
index b7ae36b8cdf53bc1ed82c727687543754edf9e92..4f8877a34f37509ac9741627978b8a6d2e157882 100644 (file)
@@ -8,7 +8,7 @@ Supported chips:
     Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
 
 Authors:
-        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
         Mark D. Studebaker <mdsxyz123@yahoo.com>,
         Aurelien Jarno <aurelien@aurel32.net> 2.6 port
 
index 04a11124f667756b9a4225b81624d9d9225eb1ae..42c8431b3c9dc37bf612a308cb5d0b56bb89fb3e 100644 (file)
@@ -14,6 +14,10 @@ Supported chips:
         http://www.smsc.com/main/datasheets/47m14x.pdf
         http://www.smsc.com/main/tools/discontinued/47m15x.pdf
         http://www.smsc.com/main/datasheets/47m192.pdf
+  * SMSC LPC47M292
+    Addresses scanned: none, address read from Super I/O config space
+    Prefix: 'smsc47m2'
+    Datasheet: Not public
   * SMSC LPC47M997
     Addresses scanned: none, address read from Super I/O config space
     Prefix: 'smsc47m1'
@@ -32,9 +36,10 @@ Description
 The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips
 contain monitoring and PWM control circuitry for two fans.
 
-The 47M15x and 47M192 chips contain a full 'hardware monitoring block'
-in addition to the fan monitoring and control. The hardware monitoring
-block is not supported by the driver.
+The LPC47M15x, LPC47M192 and LPC47M292 chips contain a full 'hardware
+monitoring block' in addition to the fan monitoring and control. The
+hardware monitoring block is not supported by this driver, use the
+smsc47m192 driver for that.
 
 No documentation is available for the 47M997, but it has the same device
 ID as the 47M15x and 47M192 chips and seems to be compatible.
index 45d6453cd435d7f4cb63b497ad5da7f6c839fd02..6d54ecb7b3f8ea2d7f6c2ca6194a094d4e54c501 100644 (file)
@@ -2,12 +2,13 @@ Kernel driver smsc47m192
 ========================
 
 Supported chips:
-  * SMSC LPC47M192 and LPC47M997
+  * SMSC LPC47M192, LPC47M15x, LPC47M292 and LPC47M997
     Prefix: 'smsc47m192'
     Addresses scanned: I2C 0x2c - 0x2d
     Datasheet: The datasheet for LPC47M192 is publicly available from
                http://www.smsc.com/
-               The LPC47M997 is compatible for hardware monitoring.
+               The LPC47M15x, LPC47M292 and LPC47M997 are compatible for
+               hardware monitoring.
 
 Author: Hartmut Rick <linux@rick.claranet.de>
         Special thanks to Jean Delvare for careful checking
@@ -18,7 +19,7 @@ Description
 -----------
 
 This driver implements support for the hardware sensor capabilities
-of the SMSC LPC47M192 and LPC47M997 Super-I/O chips.
+of the SMSC LPC47M192 and compatible Super-I/O chips.
 
 These chips support 3 temperature channels and 8 voltage inputs
 as well as CPU voltage VID input.
index d73d2e8c75344ca86b8e432e4620451d930bdeb7..a9a18ad0d17ab6c17be017615602827320ee93e5 100644 (file)
@@ -152,6 +152,13 @@ fan[1-*]_div       Fan divisor.
                Note that this is actually an internal clock divisor, which
                affects the measurable speed range, not the read value.
 
+fan[1-*]_target
+               Desired fan speed
+               Unit: revolution/min (RPM)
+               RW
+               Only makes sense if the chip supports closed-loop fan speed
+               control based on the measured fan speed.
+
 Also see the Alarms section for status flags associated with fans.
 
 
index a936fb3824b248c3a3b8bcd6e0efec3314c36432..d651b25f751971df193f3928356d4d492df05bc6 100644 (file)
@@ -8,7 +8,7 @@ Supported chips:
     Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/)
 
 Authors:
-        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
         Mark D. Studebaker <mdsxyz123@yahoo.com>
         Bob Dougherty <bobd@stanford.edu>
         (Some conversion-factor data were contributed by
index 8171c285bb55ae198d985b85dc31bd4538f8db71..14a668ed8aaa483a36496c2230778745263ec9fb 100644 (file)
@@ -107,7 +107,7 @@ Known problems:
          by CR[0x49h].
        - The function of vid and vrm has not been finished, because I'm NOT
          very familiar with them. Adding support is welcome.
-       - The function of chassis open detection needs more tests.
+      - The function of chassis open detection needs more tests.
        - If you have ASUS server board and chip was not found: Then you will
          need to upgrade to latest (or beta) BIOS. If it does not help please
          contact us.
index 83c3b9743c3c9cf01702760452dad4fade20ff61..778210ee158381f7219368af99311009d6a59e4f 100644 (file)
@@ -7,7 +7,7 @@ Supported adapters:
 Authors: 
        Frodo Looijaard <frodol@dds.nl>, 
        Philip Edelbrock <phil@netroedge.com>,
-        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
        Ralph Metzler <rjkm@thp.uni-koeln.de>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>
 
index 08d7b2dac69af0dd016e5799402c190e626293ae..266481fd26e2de612cd3a87075c6cc103501e961 100644 (file)
@@ -60,7 +60,7 @@ Mark D. Studebaker <mdsxyz123@yahoo.com>
  - design hints and bug fixes
 Alexander Maylsh <amalysh@web.de>
  - ditto, plus an important datasheet... almost the one I really wanted
-Hans-Günter Lütke Uphues <hg_lu@t-online.de>
+Hans-Günter Lütke Uphues <hg_lu@t-online.de>
  - patch for SiS735
 Robert Zwerus <arzie@dds.nl>
  - testing for SiS645DX
index 55edfe1a640be08d1aac5a49dcd5a2f9dd6d9e6c..343870661ac3d01a7d89187629b7690f1d90263d 100644 (file)
@@ -4,7 +4,7 @@ Supported adapters:
   * VIA Technologies, InC. VT82C586B
     Datasheet: Publicly available at the VIA website
 
-Author: Kyösti Mälkki <kmalkki@cc.hut.fi>
+Author: Kyösti Mälkki <kmalkki@cc.hut.fi>
 
 Description
 -----------
index 775f489e86f63162d9abe00b1588f4b515704521..06b4be3ef6d8eb0e7f3c94343df92e0009e25c7b 100644 (file)
@@ -17,7 +17,7 @@ Supported adapters:
     Datasheet: available on request and under NDA from VIA
 
 Authors:
-       Kyösti Mälkki <kmalkki@cc.hut.fi>,
+       Kyösti Mälkki <kmalkki@cc.hut.fi>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
        Jean Delvare <khali@linux-fr.org>
 
index b4022c914210ef10a5a0acf79405dc369c20df0e..579b92d5f3a38c4796d6bcf4c1de559277090974 100644 (file)
@@ -68,7 +68,7 @@ We have found some I2C devices that needs the following modifications:
 
   Flags I2C_M_IGNORE_NAK
     Normally message is interrupted immediately if there is [NA] from the
-    client. Setting this flag treats any [NA] as [A], and all of
+    client. Setting this flag treats any [NA] as [A], and all of
     message is sent.
     These messages may still fail to SCL lo->hi timeout.
 
index 9aa6ddb446eb25d26e43cb7912f38244733b605e..0ebf58c73f54e9acd6bd611033c9639f160e6880 100644 (file)
@@ -30,13 +30,13 @@ Juha Sievanen, University of Helsinki Finland
        Bug fixes
        Core code extensions
 
-Auvo Häkkinen, University of Helsinki Finland
+Auvo Häkkinen, University of Helsinki Finland
        LAN OSM code
        /Proc interface to LAN class
        Bug fixes
        Core code extensions
 
-Taneli Vähäkangas, University of Helsinki Finland
+Taneli Vähäkangas, University of Helsinki Finland
        Fixes to i2o_config
 
 CREDITS
index 6498666ea3307dea2e6e67748c5a4983f0fec590..d01b7a2a0f2eea6bdfa219fb88490fcbb6b80a0e 100644 (file)
@@ -2,7 +2,7 @@
                     ----------------------------
 
                    H. Peter Anvin <hpa@zytor.com>
-                       Last update 2007-03-06
+                       Last update 2007-05-07
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -11,7 +11,7 @@ bootable image, the complicated PC memory model and due to changed
 expectations in the PC industry caused by the effective demise of
 real-mode DOS as a mainstream operating system.
 
-Currently, four versions of the Linux/i386 boot protocol exist.
+Currently, the following versions of the Linux/i386 boot protocol exist.
 
 Old kernels:   zImage/Image support only.  Some very early kernels
                may not even support a command line.
@@ -183,9 +183,9 @@ filled out, however:
        a version number.  Otherwise, enter 0xFF here.
 
        Assigned boot loader ids:
-       0  LILO
+       0  LILO                 (0x00 reserved for pre-2.00 bootloader)
        1  Loadlin
-       2  bootsect-loader
+       2  bootsect-loader      (0x20, all other values reserved)
        3  SYSLINUX
        4  EtherBoot
        5  ELILO
@@ -210,6 +210,9 @@ filled out, however:
        additional data (such as the kernel command line) moved in
        addition to the real-mode kernel itself.
 
+       The unit is bytes starting with the beginning of the boot
+       sector.
+
   ramdisk_image, ramdisk_size:
        If your boot loader has loaded an initial ramdisk (initrd),
        set ramdisk_image to the 32-bit pointer to the ramdisk data
@@ -278,14 +281,54 @@ command line is entered using the following protocol:
        field.
 
 
+**** MEMORY LAYOUT OF THE REAL-MODE CODE
+
+The real-mode code requires a stack/heap to be set up, as well as
+memory allocated for the kernel command line.  This needs to be done
+in the real-mode accessible memory in bottom megabyte.
+
+It should be noted that modern machines often have a sizable Extended
+BIOS Data Area (EBDA).  As a result, it is advisable to use as little
+of the low megabyte as possible.
+
+Unfortunately, under the following circumstances the 0x90000 memory
+segment has to be used:
+
+       - When loading a zImage kernel ((loadflags & 0x01) == 0).
+       - When loading a 2.01 or earlier boot protocol kernel.
+
+         -> For the 2.00 and 2.01 boot protocols, the real-mode code
+            can be loaded at another address, but it is internally
+            relocated to 0x90000.  For the "old" protocol, the
+            real-mode code must be loaded at 0x90000.
+
+When loading at 0x90000, avoid using memory above 0x9a000.
+
+For boot protocol 2.02 or higher, the command line does not have to be
+located in the same 64K segment as the real-mode setup code; it is
+thus permitted to give the stack/heap the full 64K segment and locate
+the command line above it.
+
+The kernel command line should not be located below the real-mode
+code, nor should it be located in high memory.
+
+
 **** SAMPLE BOOT CONFIGURATION
 
 As a sample configuration, assume the following layout of the real
-mode segment (this is a typical, and recommended layout):
+mode segment:
+
+    When loading below 0x90000, use the entire segment:
+
+       0x0000-0x7fff   Real mode kernel
+       0x8000-0xdfff   Stack and heap
+       0xe000-0xffff   Kernel command line
 
-       0x0000-0x7FFF   Real mode kernel
-       0x8000-0x8FFF   Stack and heap
-       0x9000-0x90FF   Kernel command line
+    When loading at 0x90000 OR the protocol version is 2.01 or earlier:
+
+       0x0000-0x7fff   Real mode kernel
+       0x8000-0x97ff   Stack and heap
+       0x9800-0x9fff   Kernel command line
 
 Such a boot loader should enter the following fields in the header:
 
@@ -301,22 +344,33 @@ Such a boot loader should enter the following fields in the header:
                        ramdisk_image = <initrd_address>;
                        ramdisk_size = <initrd_size>;
                }
+
+               if ( protocol >= 0x0202 && loadflags & 0x01 )
+                       heap_end = 0xe000;
+               else
+                       heap_end = 0x9800;
+
                if ( protocol >= 0x0201 ) {
-                       heap_end_ptr = 0x9000 - 0x200;
+                       heap_end_ptr = heap_end - 0x200;
                        loadflags |= 0x80; /* CAN_USE_HEAP */
                }
+
                if ( protocol >= 0x0202 ) {
-                       cmd_line_ptr = base_ptr + 0x9000;
+                       cmd_line_ptr = base_ptr + heap_end;
+                       strcpy(cmd_line_ptr, cmdline);
                } else {
                        cmd_line_magic  = 0xA33F;
-                       cmd_line_offset = 0x9000;
-                       setup_move_size = 0x9100;
+                       cmd_line_offset = heap_end;
+                       setup_move_size = heap_end + strlen(cmdline)+1;
+                       strcpy(base_ptr+cmd_line_offset, cmdline);
                }
        } else {
                /* Very old kernel */
 
+               heap_end = 0x9800;
+
                cmd_line_magic  = 0xA33F;
-               cmd_line_offset = 0x9000;
+               cmd_line_offset = heap_end;
 
                /* A very old kernel MUST have its real-mode code
                   loaded at 0x90000 */
@@ -324,12 +378,11 @@ Such a boot loader should enter the following fields in the header:
                if ( base_ptr != 0x90000 ) {
                        /* Copy the real-mode kernel */
                        memcpy(0x90000, base_ptr, (setup_sects+1)*512);
-                       /* Copy the command line */
-                       memcpy(0x99000, base_ptr+0x9000, 256);
-
                        base_ptr = 0x90000;              /* Relocated */
                }
 
+               strcpy(0x90000+cmd_line_offset, cmdline);
+
                /* It is recommended to clear memory up to the 32K mark */
                memset(0x90000 + (setup_sects+1)*512, 0,
                       (64-(setup_sects+1))*512);
@@ -375,10 +428,11 @@ conflict with actual kernel options now or in the future.
        line is parsed.
 
   mem=<size>
-       <size> is an integer in C notation optionally followed by K, M
-       or G (meaning << 10, << 20 or << 30).  This specifies the end
-       of memory to the kernel. This affects the possible placement
-       of an initrd, since an initrd should be placed near end of
+       <size> is an integer in C notation optionally followed by
+       (case insensitive) K, M, G, T, P or E (meaning << 10, << 20,
+       << 30, << 40, << 50 or << 60).  This specifies the end of
+       memory to the kernel. This affects the possible placement of
+       an initrd, since an initrd should be placed near end of
        memory.  Note that this is an option to *both* the kernel and
        the bootloader!
 
@@ -428,7 +482,7 @@ In our example from above, we would do:
 
        /* Set up the real-mode kernel stack */
        _SS = seg;
-       _SP = 0x9000;   /* Load SP immediately after loading SS! */
+       _SP = heap_end;
 
        _DS = _ES = _FS = _GS = seg;
        jmp_far(seg+0x20, 0);   /* Run the kernel */
@@ -460,8 +514,9 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
   code32_start:
        A 32-bit flat-mode routine *jumped* to immediately after the
        transition to protected mode, but before the kernel is
-       uncompressed.  No segments, except CS, are set up; you should
-       set them up to KERNEL_DS (0x18) yourself.
+       uncompressed.  No segments, except CS, are guaranteed to be
+       set up (current kernels do, but older ones do not); you should
+       set them up to BOOT_DS (0x18) yourself.
 
        After completing your hook, you should jump to the address
        that was in this field before your boot loader overwrote it.
index 668f4d0d97d60efe0f8fd99538e4b259b19874ff..ab050621e20f7878f19c19392f1007718fd6dddc 100644 (file)
@@ -179,9 +179,9 @@ reporting mode for joystick 1, with both buttons being logically assigned to
 the mouse. After any joystick command, the ikbd assumes that joysticks are
 connected to both Joystick0 and Joystick1. Any mouse command (except MOUSE
 DISABLE) then causes port 0 to again be scanned as if it were a mouse, and
-both buttons are logically connected to it. If a mouse diable command is
+both buttons are logically connected to it. If a mouse disable command is
 received while port 0 is presumed to be a mouse, the button is logically
-assigned to Joystick1 ( until the mouse is reenabled by another mouse command).
+assigned to Joystick1 (until the mouse is reenabled by another mouse command).
 
 9. ikbd Command Set
 
index 5427bdf225ed0392372ff6ce428dd1e68a2aab83..aae0d404c5666a15aba9f56703b4fdb997f009aa 100644 (file)
@@ -65,15 +65,15 @@ of buttons, see section 0.3 - Unknown Controllers
 I've tested this with Stepmania, and it works quite well.
 
 
-0.3 Unkown Controllers
+0.3 Unknown Controllers
 ----------------------
-If you have an unkown xbox controller, it should work just fine with
+If you have an unknown xbox controller, it should work just fine with
 the default settings.
 
 HOWEVER if you have an unknown dance pad not listed below, it will not
 work UNLESS you set "dpad_to_buttons" to 1 in the module configuration.
 
-PLEASE if you have an unkown controller, email Dom <binary1230@yahoo.com> with
+PLEASE, if you have an unknown controller, email Dom <binary1230@yahoo.com> with
 a dump from /proc/bus/usb and a description of the pad (manufacturer, country,
 whether it is a dance pad or normal controller) so that we can add your pad
 to the list of supported devices, ensuring that it will work out of the
index 8f750c0efed5ed0adc5329ff5bd6a5e17d5c9113..3de7d379cf077d3c933c931133b5f17132d1fa3a 100644 (file)
@@ -138,7 +138,8 @@ Code        Seq#    Include File            Comments
 'm'    00-1F   net/irda/irmod.h        conflict!
 'n'    00-7F   linux/ncp_fs.h
 'n'    E0-FF   video/matrox.h          matroxfb
-'p'    00-3F   linux/mc146818rtc.h
+'p'    00-0F   linux/phantom.h         conflict! (OpenHaptics needs this)
+'p'    00-3F   linux/mc146818rtc.h     conflict!
 'p'    40-7F   linux/nvram.h
 'p'    80-9F                           user-space parport
                                        <mailto:tim@cyberelk.net>
index e1b3023efaa8701f31886d695adb478a55fcd07f..7c17c837064fbfe7cd5f688de32947f5c4182fe2 100644 (file)
@@ -2,7 +2,7 @@
 I want to thank all who contributed to this project and especially to:
 (in alphabetical order)
 
-Thomas Bogendörfer (tsbogend@bigbug.franken.de)
+Thomas Bogendörfer (tsbogend@bigbug.franken.de)
   Tester, lots of bugfixes and hints.
 
 Alan Cox (alan@redhat.com)
@@ -11,7 +11,7 @@ Alan Cox (alan@redhat.com)
 Henner Eisen (eis@baty.hanse.de)
   For X.25 implementation.
 
-Volker Götz (volker@oops.franken.de)
+Volker Götz (volker@oops.franken.de)
   For contribution of man-pages, the imontty-tool and a perfect
   maintaining of the mailing-list at hub-wue.
 
index 761595243931a93bf300875adcc638a1dbb469b4..6783437f21c2df8563312706fe72974e3f0a0c4c 100644 (file)
@@ -402,7 +402,7 @@ README for the ISDN-subsystem
      the script tools/tcltk/isdnmon. You can add actions for line-status
      changes. See the comments at the beginning of the script for how to
      do that. There are other tty-based tools in the tools-subdirectory
-     contributed by Michael Knigge (imon), Volker Götz (imontty) and
+     contributed by Michael Knigge (imon), Volker Götz (imontty) and
      Andreas Kool (isdnmon).
 
    l) For initial testing, you can set the verbose-level to 2 (default: 0).
index a5f55eadb3ca5d45ad88734e24a93222c2e12675..13f833d4e910c3b385f267359f3b451a38b1ad40 100644 (file)
@@ -3,8 +3,8 @@ $Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $
 You can get the ICN-ISDN-card from:
 
 Thinking Objects Software GmbH
-Versbacher Röthe 159
-97078 Würzburg
+Versbacher Röthe 159
+97078 Würzburg
 Tel: +49 931 2877950
 Fax: +49 931 2877951
 
index c768dc63b34e9c73c629a7e15b6444d76a8692e9..3cce3fbb664437a2fb1acf65fda6ff3360e36273 100644 (file)
@@ -390,7 +390,7 @@ the execution bit, then just do
 
 
 originally by Brian A. Lantz, brian@lantz.com
-heavily edited for binfmt_misc by Richard Günther
+heavily edited for binfmt_misc by Richard Günther
 new scripts by Colin J. Watson <cjw44@cam.ac.uk>
 added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>
 
index c68dafeda7a70ae6db56523816fa2280cd13e1b9..d9e3b199929bd6fb158576a040e88ee01276561f 100644 (file)
 
      * Title: "Design and Implementation of the Second Extended
        Filesystem"
-       Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
+       Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
        URL: http://web.mit.edu/tytso/www/linux/ext2intro.html
        Keywords: ext2, linux fs history, inode, directory, link, devices,
        VFS, physical structure, performance, benchmarks, ext2fs library,
index 38d7db3262c7e85f7e9d327f4ed2a30eee47ba1c..6b8ad06846c449550212b08974f0e6c9de50786a 100644 (file)
@@ -496,6 +496,30 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: <area>[,<node>]
                        See also Documentation/networking/decnet.txt.
 
+       default_blu=    [VT]
+                       Format: <blue0>,<blue1>,<blue2>,...,<blue15>
+                       Change the default blue palette of the console.
+                       This is a 16-member array composed of values
+                       ranging from 0-255.
+
+       default_grn=    [VT]
+                       Format: <green0>,<green1>,<green2>,...,<green15>
+                       Change the default green palette of the console.
+                       This is a 16-member array composed of values
+                       ranging from 0-255.
+
+       default_red=    [VT]
+                       Format: <red0>,<red1>,<red2>,...,<red15>
+                       Change the default red palette of the console.
+                       This is a 16-member array composed of values
+                       ranging from 0-255.
+
+       default_utf8=   [VT]
+                       Format=<0|1>
+                       Set system-wide default UTF-8 mode for all tty's.
+                       Default is 0 and by setting to 1, it enables UTF-8
+                       mode for all newly opened or allocated terminals.
+
        dhash_entries=  [KNL]
                        Set number of hash buckets for dentry cache.
 
@@ -816,6 +840,11 @@ and is between 256 and 4096 characters. It is defined in the file
        lasi=           [HW,SCSI] PARISC LASI driver for the 53c700 chip
                        Format: addr:<io>,irq:<irq>
 
+       legacy_serial.force [HW,IA-32,X86-64]
+                       Probe for COM ports at legacy addresses even
+                       if PNPBIOS or ACPI should describe them.  This
+                       is for working around firmware defects.
+
        llsc*=          [IA64] See function print_params() in
                        arch/ia64/sn/kernel/llsc4.c.
 
@@ -1578,6 +1607,17 @@ and is between 256 and 4096 characters. It is defined in the file
        smp-alt-once    [IA-32,SMP] On a hotplug CPU system, only
                        attempt to substitute SMP alternatives once at boot.
 
+       smsc-ircc2.nopnp        [HW] Don't use PNP to discover SMC devices
+       smsc-ircc2.ircc_cfg=    [HW] Device configuration I/O port
+       smsc-ircc2.ircc_sir=    [HW] SIR base I/O port
+       smsc-ircc2.ircc_fir=    [HW] FIR base I/O port
+       smsc-ircc2.ircc_irq=    [HW] IRQ line
+       smsc-ircc2.ircc_dma=    [HW] DMA channel
+       smsc-ircc2.ircc_transceiver= [HW] Transceiver type:
+                               0: Toshiba Satellite 1800 (GP data pin select)
+                               1: Fast pin select (default)
+                               2: ATC IRMode
+
        snd-ad1816a=    [HW,ALSA]
 
        snd-ad1848=     [HW,ALSA]
index d71fafffce90de81cba916c5d98dae7db5e9eb63..da5404ab75691c58e3d69c89ea1a3f8ba1fd993b 100644 (file)
@@ -14,6 +14,7 @@ CONTENTS
 8. Kprobes Example
 9. Jprobes Example
 10. Kretprobes Example
+Appendix A: The kprobes debugfs interface
 
 1. Concepts: Kprobes, Jprobes, Return Probes
 
@@ -349,9 +350,12 @@ for instrumentation and error reporting.)
 
 If the number of times a function is called does not match the number
 of times it returns, registering a return probe on that function may
-produce undesirable results.  We have the do_exit() case covered.
-do_execve() and do_fork() are not an issue.  We're unaware of other
-specific cases where this could be a problem.
+produce undesirable results. In such a case, a line:
+kretprobe BUG!: Processing kretprobe d000000000041aa8 @ c00000000004f48c
+gets printed. With this information, one will be able to correlate the
+exact instance of the kretprobe that caused the problem. We have the
+do_exit() case covered. do_execve() and do_fork() are not an issue.
+We're unaware of other specific cases where this could be a problem.
 
 If, upon entry to or exit from a function, the CPU is running on
 a stack other than that of the current task, registering a return
@@ -614,3 +618,27 @@ http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe
 http://www.redhat.com/magazine/005mar05/features/kprobes/
 http://www-users.cs.umn.edu/~boutcher/kprobes/
 http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115)
+
+
+Appendix A: The kprobes debugfs interface
+
+With recent kernels (> 2.6.20) the list of registered kprobes is visible
+under the /debug/kprobes/ directory (assuming debugfs is mounted at /debug).
+
+/debug/kprobes/list: Lists all registered probes on the system
+
+c015d71a  k  vfs_read+0x0
+c011a316  j  do_fork+0x0
+c03dedc5  r  tcp_v4_rcv+0x0
+
+The first column provides the kernel address where the probe is inserted.
+The second column identifies the type of probe (k - kprobe, r - kretprobe
+and j - jprobe), while the third column specifies the symbol+offset of
+the probe. If the probed function belongs to a module, the module name
+is also specified.
+
+/debug/kprobes/enabled: Turn kprobes ON/OFF
+
+Provides a knob to globally turn registered kprobes ON or OFF. By default,
+all kprobes are enabled. By echoing "0" to this file, all registered probes
+will be disarmed, till such time a "1" is echoed to this file.
index 6f639e3473af550bbf384a506fcb9074a60dca2b..eeedee11c8c2bd44c16011b804166a78c04955bf 100644 (file)
@@ -33,7 +33,7 @@ or anything. Simply install all the files included in this document, and
 laptop mode will automatically be started when you're on battery. For
 your convenience, a tarball containing an installer can be downloaded at:
 
-http://www.xs4all.nl/~bsamwel/laptop_mode/tools/
+http://www.samwel.tk/laptop_mode/laptop_mode/
 
 To configure laptop mode, you need to edit the configuration file, which is
 located in /etc/default/laptop-mode on Debian-based systems, or in
index ef484a719bb9d528cdce84cbecbfbb06f3c6bf69..3ea9827ba3c797e51b6d531364f5bfb529f5ed05 100644 (file)
@@ -204,7 +204,7 @@ always  shows a "no IRQ here" on the Buddha, and accesses to
 the  third  IDE  port  are  going into data's Nirwana on the
 Buddha.
 
-                           Jens Schönfeld february 19th, 1997
+                           Jens Schönfeld february 19th, 1997
                                        updated may 27th, 1997
                             eMail: sysop@nostlgic.tng.oche.de
 
index 0e740c812d12e4dc3ea77c67601a3937c26b26cb..bd450e797558f5df225f4d7de661e166275e41e4 100644 (file)
@@ -129,7 +129,7 @@ SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
 GDA_MAGIC             0x58464552  gda               include/asm-mips64/sn/gda.h
 RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
 STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
-EEPROM_MAGIC_VALUE    0X5ab478d2  lanai_dev         drivers/atm/lanai.c
+EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
 EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
index 2202f5dc8ac208381a241bd5fc6b56b73c81ea9a..5818628207b5ec8b5f32ed6d727857f5f6dcbbec 100644 (file)
@@ -178,6 +178,21 @@ All md devices contain:
      The size should be at least PAGE_SIZE (4k) and should be a power
      of 2.  This can only be set while assembling an array
 
+  layout
+     The "layout" for the array for the particular level.  This is
+     simply a number that is interpretted differently by different
+     levels.  It can be written while assembling an array.
+
+  reshape_position
+     This is either "none" or a sector number within the devices of
+     the array where "reshape" is up to.  If this is set, the three
+     attributes mentioned above (raid_disks, chunk_size, layout) can
+     potentially have 2 values, an old and a new value.  If these
+     values differ, reading the attribute returns
+        new (old)
+     and writing will effect the 'new' value, leaving the 'old'
+     unchanged.
+
   component_size
      For arrays with data redundancy (i.e. not raid0, linear, faulty,
      multipath), all components must be the same size - or at least
@@ -193,11 +208,6 @@ All md devices contain:
      1.2 (newer format in varying locations) or "none" indicating that
      the kernel isn't managing metadata at all.
 
-  layout
-     The "layout" for the array for the particular level.  This is
-     simply a number that is interpretted differently by different
-     levels.  It can be written while assembling an array.
-
   resync_start
      The point at which resync should start.  If no resync is needed,
      this will be a very large number.  At array creation it will
@@ -259,29 +269,6 @@ All md devices contain:
          like active, but no writes have been seen for a while (safe_mode_delay).
 
 
-   sync_speed_min
-   sync_speed_max
-     This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
-     however they only apply to the particular array.
-     If no value has been written to these, of if the word 'system'
-     is written, then the system-wide value is used.  If a value,
-     in kibibytes-per-second is written, then it is used.
-     When the files are read, they show the currently active value
-     followed by "(local)" or "(system)" depending on whether it is
-     a locally set or system-wide value.
-
-   sync_completed
-     This shows the number of sectors that have been completed of
-     whatever the current sync_action is, followed by the number of
-     sectors in total that could need to be processed.  The two
-     numbers are separated by a '/'  thus effectively showing one
-     value, a fraction of the process that is complete.
-
-   sync_speed
-     This shows the current actual speed, in K/sec, of the current
-     sync_action.  It is averaged over the last 30 seconds.
-
-
 As component devices are added to an md array, they appear in the 'md'
 directory as new directories named
       dev-XXX
@@ -412,6 +399,35 @@ also have
       Note that the numbers are 'bit' numbers, not 'block' numbers.
       They should be scaled by the bitmap_chunksize.
 
+   sync_speed_min
+   sync_speed_max
+     This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
+     however they only apply to the particular array.
+     If no value has been written to these, of if the word 'system'
+     is written, then the system-wide value is used.  If a value,
+     in kibibytes-per-second is written, then it is used.
+     When the files are read, they show the currently active value
+     followed by "(local)" or "(system)" depending on whether it is
+     a locally set or system-wide value.
+
+   sync_completed
+     This shows the number of sectors that have been completed of
+     whatever the current sync_action is, followed by the number of
+     sectors in total that could need to be processed.  The two
+     numbers are separated by a '/'  thus effectively showing one
+     value, a fraction of the process that is complete.
+
+   sync_speed
+     This shows the current actual speed, in K/sec, of the current
+     sync_action.  It is averaged over the last 30 seconds.
+
+   suspend_lo
+   suspend_hi
+     The two values, given as numbers of sectors, indicate a range
+     within the array where IO will be blocked.  This is currently
+     only supported for raid4/5/6.
+
+
 Each active md device may also have attributes specific to the
 personality module that manages it.
 These are specific to the implementation of the module and could
index a4ffba1694c8fc928ba933c336bee7525c4d02d2..5ecd8d1dcf4e5d93c1031e8fe2ad281fe6b39e76 100644 (file)
@@ -30,7 +30,7 @@ The communication layer exists to allow NetLabel configuration and monitoring
 from user space.  The NetLabel communication layer uses a message based
 protocol built on top of the Generic NETLINK transport mechanism.  The exact
 formatting of these NetLabel messages as well as the Generic NETLINK family
-names can be found in the the 'net/netlabel/' directory as comments in the
+names can be found in the 'net/netlabel/' directory as comments in the
 header files as well as in 'include/net/netlabel.h'.
 
  * Security Module API
index 48ed2b711bd270cce9ccd9fb454bee17a40e3dd6..d0777a1200e1a3a3c224db65cac7fe0d866ea44f 100644 (file)
@@ -1,6 +1,6 @@
 This is the 6pack-mini-HOWTO, written by
 
-Andreas Könsgen DG3KQ
+Andreas Könsgen DG3KQ
 Internet: ajk@iehk.rwth-aachen.de
 AMPR-net: dg3kq@db0pra.ampr.org
 AX.25:    dg3kq@db0ach.#nrw.deu.eu
index fb8dc6422a5212488f362e1a48711afe452f0482..7907435a661c3ed463a2718021f7b5fe4d394f31 100644 (file)
@@ -160,7 +160,7 @@ on current cpu. This primitive is called by dev->poll(), when
 it completes its work. The device cannot be out of poll list at this
 call, if it is then clearly it is a BUG(). You'll know ;->
 
-All these above nethods are used below. So keep reading for clarity.
+All of the above methods are used below, so keep reading for clarity.
 
 Device driver changes to be made when porting NAPI
 ==================================================
index 5a232d946be39fd425c1f9b6c5e821b902b2d465..db0cd51695812cfe2c8850bb80471b422f994e25 100644 (file)
@@ -13,7 +13,7 @@ You can find the latest version of this document at
 
 Please send me your comments to
 
-    Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
+    Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
 
 -------------------------------------------------------------------------------
 + Why use PACKET_MMAP
index 5acf1918694a01e76e89828ee5a345d42e19cd23..bed2f045e5501ea78e9e3ed9755330fa589b5ed3 100644 (file)
@@ -1,7 +1,7 @@
 
 SliceCOM adapter felhasznaloi dokumentacioja - 0.51 verziohoz
 
-Bartók István <bartoki@itc.hu>
+Bartók István <bartoki@itc.hu>
 Utolso modositas: Wed Aug 29 17:26:58 CEST 2001
 
 -----------------------------------------------------------------
index 32d3b916afadfe19718ce5f00ffd436a97481402..c82c0cf981b48aafcca1dbd503fdf9351f95922a 100644 (file)
@@ -1,9 +1,9 @@
 
 SliceCOM adapter user's documentation - for the 0.51 driver version
 
-Written by Bartók István <bartoki@itc.hu>
+Written by Bartók István <bartoki@itc.hu>
 
-English translation: Lakatos György <gyuri@itc.hu>
+English translation: Lakatos György <gyuri@itc.hu>
 Mon Dec 11 15:28:42 CET 2000
 
 Last modified: Wed Aug 29 17:25:37 CEST 2001
index c169a57bc92584704817e116faa9be02a1f9dde7..1f73e13058df6377ea6922b1576a12a9fd5a3169 100644 (file)
@@ -71,24 +71,24 @@ Below find attached the setting for the SK NET TR 4/16 ISA adapters
   CHAPTER 1     LOCATION OF DIP-SWITCH
   ==============================================================
 
-UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
-þUÄÄÄÄÄÄ¿                         UÄÄÄÄÄ¿            UÄÄÄ¿         þ
-þAÄÄÄÄÄÄU                      W1 AÄÄÄÄÄU     UÄÄÄÄ¿ þ   þ         þ
-þUÄÄÄÄÄÄ¿                                     þ    þ þ   þ      UÄÄÅ¿
-þAÄÄÄÄÄÄU              UÄÄÄÄÄÄÄÄÄÄÄ¿          AÄÄÄÄU þ   þ      þ  þþ
-þUÄÄÄÄÄÄ¿              þ           þ          UÄÄÄ¿  AÄÄÄU      AÄÄÅU
-þAÄÄÄÄÄÄU              þ TMS380C26 þ          þ   þ                þ
-þUÄÄÄÄÄÄ¿              þ           þ          AÄÄÄU                AÄ¿
-þAÄÄÄÄÄÄU              þ           þ                               þ þ
-þ                      AÄÄÄÄÄÄÄÄÄÄÄU                               þ þ
-þ                                                                  þ þ
-þ                                                                  AÄU
-þ                                                                  þ
-þ                                                                  þ
-þ                                                                  þ
-þ                                                                  þ
-AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
-             AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU  AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
+UÃ\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84Ã\84¿
+þUÄÄÄÄÄÄ¿                         UÄÄÄÄÄ¿            UÄÄÄ¿         þ
+þAÄÄÄÄÄÄU                      W1 AÄÄÄÄÄU     UÄÄÄÄ¿ þ   þ         þ
+þUÃ\84Ã\84Ã\84Ã\84Ã\84Ã\84¿                                     Ã¾    Ã¾ Ã¾   Ã¾      UÃ\84Ã\84Ã\85¿
+þAÄÄÄÄÄÄU              UÄÄÄÄÄÄÄÄÄÄÄ¿          AÄÄÄÄU þ   þ      þ  þþ
+þUÄÄÄÄÄÄ¿              þ           þ          UÄÄÄ¿  AÄÄÄU      AÄÄÅU
+þAÄÄÄÄÄÄU              þ TMS380C26 þ          þ   þ                þ
+þUÃ\84Ã\84Ã\84Ã\84Ã\84Ã\84¿              Ã¾           Ã¾          AÃ\84Ã\84Ã\84U                AÃ\84¿
+þAÄÄÄÄÄÄU              þ           þ                               þ þ
+þ                      AÄÄÄÄÄÄÄÄÄÄÄU                               þ þ
+þ                                                                  þ þ
+þ                                                                  AÄU
+þ                                                                  þ
+þ                                                                  þ
+þ                                                                  þ
+þ                                                                  þ
+AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
+             AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU  AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
 
   ==============================================================
   CHAPTER 2     DEFAULT SETTINGS
@@ -108,9 +108,9 @@ A
   CHAPTER 3     DIP SWITCH W1 DESCRIPTION
   ==============================================================
 
-      UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿  ON
-      þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ
-      AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU  OFF
+      UÃ\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84\84Ã\84Ã\84¿  ON
+      þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ
+      AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU  OFF
       |AD | BootROM Addr. |  I/O      |
       +-+-+-------+-------+-----+-----+
         |         |             |
index dd6f46b83dab126f70463b3c476a8ad42997979c..6be09ba24a365f25e1c16881f7560d63a2cef3e3 100644 (file)
   3) Disabling the Checksum Computation
 
   On both sender and receiver, checksumming will always be performed
-  and can not be disabled using SO_NO_CHECK. Thus
+  and cannot be disabled using SO_NO_CHECK. Thus
 
         setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK,  ... );
 
index 07dd6d9930a14d22fe30e783e6e59ed38918ad9f..bc2ab419a74aff2f60f147860cc66ff9713ef60f 100644 (file)
@@ -335,7 +335,7 @@ REVISION HISTORY
                                creating applications using BiSync
                                streaming.        
 
-2.0.5   Aug 04, 1999           CHDLC initializatin bug fix.
+2.0.5   Aug 04, 1999           CHDLC initialization bug fix.
                                PPP interrupt driven driver: 
                                Fix to the PPP line hangup problem.
                                New PPP firmware
@@ -372,7 +372,7 @@ REVISION HISTORY
                                o cfgft1 GUI csu/dsu configurator
                                o wancfg GUI configuration file 
                                  configurator.
-                               o Architectual directory changes.
+                               o Architectural directory changes.
 
 beta-2.1.4 Jul 2000            o Dynamic interface configuration:
                                        Network interfaces reflect the state
index ea55ea8bc8ef0c32de234e612adf742d72214167..7d5b60dea551daacec4cc81006678957a38f1795 100644 (file)
@@ -234,9 +234,6 @@ characters, each representing a particular tainted value.
   6: 'B' if a page-release function has found a bad page reference or
      some unexpected page flags.
 
-  7: 'U' if a user specifically requested that the Tainted flag be set,
-     ' ' otherwise.
-
   7: 'U' if a user or user application specifically requested that the
      Tainted flag be set, ' ' otherwise.
 
index e2c9d0a0c43de9de21efbbc5c6e74fe7f544aa06..d38261b679053255986f380acdb91e11dabb354a 100644 (file)
@@ -373,7 +373,7 @@ E.g. clearing pending interrupts.
 
 3.6 Register IRQ handler
 ~~~~~~~~~~~~~~~~~~~~~~~~
-While calling request_irq() is the the last step described here,
+While calling request_irq() is the last step described here,
 this is often just another intermediate step to initialize a device.
 This step can often be deferred until the device is opened for use.
 
index 16c251230c82398a1ad26a3754762e49fc819922..d5da86170106489e608fd032dfee2cb553b398d0 100644 (file)
@@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as
 well as how to enable the drivers of endpoint devices to conform with
 PCI Express AER driver.
 
-1.2 Copyright © Intel Corporation 2006.
+1.2 Copyright Â© Intel Corporation 2006.
 
 1.3 What is the PCI Express AER Driver?
 
index 28037aa1846c89bbf8082007b5e10e470000ac94..481faf515d5360e608b6f4541ef03f759612bc4f 100644 (file)
@@ -140,7 +140,7 @@ Plug and Play but it is planned to be in the near future.
 Requirements for a Linux PnP protocol:
 1.) the protocol must use EISA IDs
 2.) the protocol must inform the PnP Layer of a devices current configuration
-- the ability to set resources is optional but prefered.
+- the ability to set resources is optional but preferred.
 
 The following are PnP protocol related functions:
 
diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt
new file mode 100644 (file)
index 0000000..1a85e2b
--- /dev/null
@@ -0,0 +1,106 @@
+Debugging suspend and resume
+       (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+1. Testing suspend to disk (STD)
+
+To verify that the STD works, you can try to suspend in the "reboot" mode:
+
+# echo reboot > /sys/power/disk
+# echo disk > /sys/power/state
+
+and the system should suspend, reboot, resume and get back to the command prompt
+where you have started the transition.  If that happens, the STD is most likely
+to work correctly, but you need to repeat the test at least a couple of times in
+a row for confidence.  This is necessary, because some problems only show up on
+a second attempt at suspending and resuming the system.  You should also test
+the "platform" and "shutdown" modes of suspend:
+
+# echo platform > /sys/power/disk
+# echo disk > /sys/power/state
+
+or
+
+# echo shutdown > /sys/power/disk
+# echo disk > /sys/power/state
+
+in which cases you will have to press the power button to make the system
+resume.  If that does not work, you will need to identify what goes wrong.
+
+a) Test mode of STD
+
+To verify if there are any drivers that cause problems you can run the STD
+in the test mode:
+
+# echo test > /sys/power/disk
+# echo disk > /sys/power/state
+
+in which case the system should freeze tasks, suspend devices, disable nonboot
+CPUs (if any), wait for 5 seconds, enable nonboot CPUs, resume devices, thaw
+tasks and return to your command prompt.  If that fails, most likely there is
+a driver that fails to either suspend or resume (in the latter case the system
+may hang or be unstable after the test, so please take that into consideration).
+To find this driver, you can carry out a binary search according to the rules:
+- if the test fails, unload a half of the drivers currently loaded and repeat
+(that would probably involve rebooting the system, so always note what drivers
+have been loaded before the test),
+- if the test succeeds, load a half of the drivers you have unloaded most
+recently and repeat.
+
+Once you have found the failing driver (there can be more than just one of
+them), you have to unload it every time before the STD transition.  In that case
+please make sure to report the problem with the driver.
+
+It is also possible that a cycle can still fail after you have unloaded
+all modules. In that case, you would want to look in your kernel configuration
+for the drivers that can be compiled as modules (testing again with them as
+modules), and possibly also try boot time options such as "noapic" or "noacpi".
+
+b) Testing minimal configuration
+
+If the test mode of STD works, you can boot the system with "init=/bin/bash"
+and attempt to suspend in the "reboot", "shutdown" and "platform" modes.  If
+that does not work, there probably is a problem with a driver statically
+compiled into the kernel and you can try to compile more drivers as modules,
+so that they can be tested individually.  Otherwise, there is a problem with a
+modular driver and you can find it by loading a half of the modules you normally
+use and binary searching in accordance with the algorithm:
+- if there are n modules loaded and the attempt to suspend and resume fails,
+unload n/2 of the modules and try again (that would probably involve rebooting
+the system),
+- if there are n modules loaded and the attempt to suspend and resume succeeds,
+load n/2 modules more and try again.
+
+Again, if you find the offending module(s), it(they) must be unloaded every time
+before the STD transition, and please report the problem with it(them).
+
+c) Advanced debugging
+
+In case the STD does not work on your system even in the minimal configuration
+and compiling more drivers as modules is not practical or some modules cannot
+be unloaded, you can use one of the more advanced debugging techniques to find
+the problem.  First, if there is a serial port in your box, you can set the
+CONFIG_DISABLE_CONSOLE_SUSPEND kernel configuration option and try to log kernel
+messages using the serial console.  This may provide you with some information
+about the reasons of the suspend (resume) failure.  Alternatively, it may be
+possible to use a FireWire port for debugging with firescope
+(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On i386 it is also possible to
+use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
+
+2. Testing suspend to RAM (STR)
+
+To verify that the STR works, it is generally more convenient to use the s2ram
+tool available from http://suspend.sf.net and documented at
+http://en.opensuse.org/s2ram .  However, before doing that it is recommended to
+carry out the procedure described in section 1.
+
+Assume you have resolved the problems with the STD and you have found some
+failing drivers.  These drivers are also likely to fail during the STR or
+during the resume, so it is better to unload them every time before the STR
+transition.  Now, you can follow the instructions at
+http://en.opensuse.org/s2ram to test the system, but if it does not work
+"out of the box", you may need to boot it with "init=/bin/bash" and test
+s2ram in the minimal configuration.  In that case, you may be able to search
+for failing drivers by following the procedure analogous to the one described in
+1b).  If you find some failing drivers, you will have to unload them every time
+before the STR transition (ie. before you run s2ram), and please report the
+problems with them.
diff --git a/Documentation/power/drivers-testing.txt b/Documentation/power/drivers-testing.txt
new file mode 100644 (file)
index 0000000..33016c2
--- /dev/null
@@ -0,0 +1,42 @@
+Testing suspend and resume support in device drivers
+       (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+1. Preparing the test system
+
+Unfortunately, to effectively test the support for the system-wide suspend and
+resume transitions in a driver, it is necessary to suspend and resume a fully
+functional system with this driver loaded.  Moreover, that should be done
+several times, preferably several times in a row, and separately for the suspend
+to disk (STD) and the suspend to RAM (STR) transitions, because each of these
+cases involves different ordering of operations and different interactions with
+the machine's BIOS.
+
+Of course, for this purpose the test system has to be known to suspend and
+resume without the driver being tested.  Thus, if possible, you should first
+resolve all suspend/resume-related problems in the test system before you start
+testing the new driver.  Please see Documents/power/basic-pm-debugging.txt for
+more information about the debugging of suspend/resume functionality.
+
+2. Testing the driver
+
+Once you have resolved the suspend/resume-related problems with your test system
+without the new driver, you are ready to test it:
+
+a) Build the driver as a module, load it and try the STD in the test mode (see:
+Documents/power/basic-pm-debugging.txt, 1a)).
+
+b) Load the driver and attempt to suspend to disk in the "reboot", "shutdown"
+and "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
+
+c) Compile the driver directly into the kernel and try the STD in the test mode.
+
+d) Attempt to suspend to disk with the driver compiled directly into the kernel
+in the "reboot", "shutdown" and "platform" modes.
+
+e) Attempt to suspend to RAM using the s2ram tool with the driver loaded (see:
+Documents/power/basic-pm-debugging.txt, 2).  As far as the STR tests are
+concerned, it should not matter whether or not the driver is built as a module.
+
+Each of the above tests should be repeated several times and the STD tests
+should be mixed with the STR tests.  If any of them fails, the driver cannot be
+regarded as suspend/resume-safe.
index c55bd5079b90e4ddc654fb8755e93bfca8144560..5b8d6953f05e741b6b6a3dd88e1ee0c6681f680a 100644 (file)
@@ -48,7 +48,7 @@ before suspend (it is limited to 500 MB by default).
 
 Article about goals and implementation of Software Suspend for Linux
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Author: G\82ábor Kuti
+Author: G\82ábor Kuti
 Last revised: 2003-10-20 by Pavel Machek
 
 Idea and goals to achieve
index 000556c932e9fc4a4ede893f997d66833c4902c9..e00c6cf09e85aad17e587f0ac9d19d0a543a4cad 100644 (file)
@@ -93,21 +93,23 @@ SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to
        to resume the system from RAM if there's enough battery power or restore
        its state on the basis of the saved suspend image otherwise)
 
-SNAPSHOT_PMOPS - enable the usage of the pmops->prepare, pmops->enter and
-       pmops->finish methods (the in-kernel swsusp knows these as the "platform
-       method") which are needed on many machines to (among others) speed up
-       the resume by letting the BIOS skip some steps or to let the system
-       recognise the correct state of the hardware after the resume (in
-       particular on many machines this ensures that unplugged AC
-       adapters get correctly detected and that kacpid does not run wild after
-       the resume).  The last ioctl() argument can take one of the three
-       values, defined in kernel/power/power.h:
+SNAPSHOT_PMOPS - enable the usage of the hibernation_ops->prepare,
+       hibernate_ops->enter and hibernation_ops->finish methods (the in-kernel
+       swsusp knows these as the "platform method") which are needed on many
+       machines to (among others) speed up the resume by letting the BIOS skip
+       some steps or to let the system recognise the correct state of the
+       hardware after the resume (in particular on many machines this ensures
+       that unplugged AC adapters get correctly detected and that kacpid does
+       not run wild after the resume).  The last ioctl() argument can take one
+       of the three values, defined in kernel/power/power.h:
        PMOPS_PREPARE - make the kernel carry out the
-               pm_ops->prepare(PM_SUSPEND_DISK) operation
+               hibernation_ops->prepare() operation
        PMOPS_ENTER - make the kernel power off the system by calling
-               pm_ops->enter(PM_SUSPEND_DISK)
+               hibernation_ops->enter()
        PMOPS_FINISH - make the kernel carry out the
-               pm_ops->finish(PM_SUSPEND_DISK) operation
+               hibernation_ops->finish() operation
+       Note that the actual constants are misnamed because they surface
+       internal kernel implementation details that have changed.
 
 The device's read() operation can be used to transfer the snapshot image from
 the kernel.  It has the following limitations:
index 033a3f3b3ab77b65d146ec38ec63acba35982c88..b49ce169a63aa27d75271a45948b0c1ed8d15ecd 100644 (file)
@@ -1444,7 +1444,7 @@ platforms are moved over to use the flattened-device-tree model.
    Basically, it is a bus of devices, that could act more or less
    as a complete entity (UCC, USB etc ). All of them should be siblings on
    the "root" qe node, using the common properties from there.
-   The description below applies to the the qe of MPC8360 and
+   The description below applies to the qe of MPC8360 and
    more nodes and properties would be extended in the future.
 
    i) Root QE device
@@ -1560,6 +1560,9 @@ platforms are moved over to use the flattened-device-tree model.
      network device.  This is used by the bootwrapper to interpret
      MAC addresses passed by the firmware when no information other
      than indices is available to associate an address with a device.
+   - phy-connection-type : a string naming the controller/PHY interface type,
+     i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "tbi",
+     or "rtbi".
 
    Example:
        ucc@2000 {
@@ -1574,6 +1577,7 @@ platforms are moved over to use the flattened-device-tree model.
                rx-clock = "none";
                tx-clock = "clk9";
                phy-handle = <212000>;
+               phy-connection-type = "gmii";
                pio-handle = <140001>;
        };
 
@@ -1629,7 +1633,7 @@ platforms are moved over to use the flattened-device-tree model.
      - assignment : function number of the pin according to the Pin Assignment
        tables in User Manual.  Each pin can have up to 4 possible functions in
        QE and two options for CPM.
-     - has_irq : indicates if the pin is used as source of exteral
+     - has_irq : indicates if the pin is used as source of external
        interrupts.
 
    Example:
index 1ef6bb88cd0003ad05a0d813533689e130a72002..7c701b88d6d59dd4e1068a8ad22a4321704737a0 100644 (file)
@@ -147,7 +147,7 @@ RTC class framework, but can't be supported by the older driver.
 
     *  RTC_AIE_ON, RTC_AIE_OFF, RTC_ALM_SET, RTC_ALM_READ ... when the RTC
        is connected to an IRQ line, it can often issue an alarm IRQ up to
-       24 hours in the future.
+       24 hours in the future.  (Use RTC_WKALM_* by preference.)
 
     *  RTC_WKALM_SET, RTC_WKALM_RD ... RTCs that can issue alarms beyond
        the next 24 hours use a slightly more powerful API, which supports
@@ -175,10 +175,7 @@ driver returns ENOIOCTLCMD.  Some common examples:
        called with appropriate values.
 
     *  RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
-       set_alarm/read_alarm functions will be called.  To differentiate
-       between the ALM and WKALM, check the larger fields of the rtc_wkalrm
-       struct (like tm_year).  These will be set to -1 when using ALM and
-       will be set to proper values when using WKALM.
+       set_alarm/read_alarm functions will be called.
 
     *  RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
        to set the frequency while the framework will handle the read for you
index 0993969609cf497e50232847aa319716a7b3663b..d30a281c570f025c35234fd52f2a899e29bc0ec2 100644 (file)
@@ -2209,7 +2209,7 @@ Breakpoint 2 at 0x4d87a4: file top.c, line 2609.
 #3  0x5167e6 in readline_internal_char () at readline.c:454
 #4  0x5168ee in readline_internal_charloop () at readline.c:507
 #5  0x51692c in readline_internal () at readline.c:521
-#6  0x5164fe in readline (prompt=0x7ffff810 "\177\81ÿ\81øx\177\81ÿ\81÷\81Ø\177\81ÿ\81øx\81À")
+#6  0x5164fe in readline (prompt=0x7ffff810 "\177\81ÿ\81øx\177\81ÿ\81÷\81Ø\177\81ÿ\81øx\81À")
     at readline.c:349
 #7  0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1,
     annotation_suffix=0x4d6b44 "prompt") at top.c:2091
index 2368e7e4a8cfa9d64c27c0b9932c79e5e3f378f0..ce3cb42507bd1edd5c0495af1a1ba6edb1b764a8 100644 (file)
@@ -98,8 +98,8 @@ Supported Cards/Chipsets
        9005:0285:9005:02b0             (Sunrise Lake ARK)
        9005:0285:9005:02b1     Adaptec (Voodoo 8 internal 8 external)
        9005:0285:108e:7aac     SUN     STK RAID REM (Voodoo44 Coyote)
-       9005:0285:108e:0286     SUN     SG-XPCIESAS-R-IN (Cougar)
-       9005:0285:108e:0287     SUN     SG-XPCIESAS-R-EX (Prometheus)
+       9005:0285:108e:0286     SUN     STK RAID INT (Cougar)
+       9005:0285:108e:0287     SUN     STK RAID EXT (Prometheus)
 
 People
 -------------------------
index 2ce022cec9be6a57cc3bc26926f19e386672a81f..29ce6d87e451b37627b5fe6fbbfd584fbc79b165 100644 (file)
@@ -1,7 +1,7 @@
 $Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $
 Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x)
 
-Copyright 1993-1999 Jürgen Fischer <fischer@norbit.de>
+Copyright 1993-1999 Jürgen Fischer <fischer@norbit.de>
 TC1550 patches by Luuk van Dijk (ldz@xs4all.nl)
 
 
index 9b894f116d95b364d3c8cc862eaf1d7eb97d1b4e..5f34d2ba69b47ce0e4571ac5288a3415c314c05d 100644 (file)
@@ -40,7 +40,7 @@ The following information is available in this file:
    2.   Multi-function Twin Channel Device - Two controllers on one chip.
    3.   Command Channel Secondary DMA Engine - Allows scatter gather list
         and SCB prefetch.
-   4.   64 Byte SCB Support - Allows disconnected, unttagged request table
+   4.   64 Byte SCB Support - Allows disconnected, untagged request table
         for all possible target/lun combinations.
    5.   Block Move Instruction Support - Doubles the speed of certain
         sequencer operations.
index 05667e7308d40cfecad6cefbedfcc7bbaedcffd0..7bd210ab45a1baacc566c551ab4f248ef51874a9 100644 (file)
@@ -356,7 +356,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
         or enable Tagged Command Queueing (TCQ) on specific devices.  As of
        driver version 5.1.11, TCQ is now either on or off by default
        according to the setting you choose during the make config process.
-       In order to en/disable TCQ for certian devices at boot time, a user
+       In order to en/disable TCQ for certain devices at boot time, a user
        may use this boot param.  The driver will then parse this message out
         and en/disable the specific device entries that are present based upon
         the value given.  The param line is parsed in the following manner:
index 88ef88b949f7140bf4d59476aecf7fbca09f7409..39d409a8efe57709e2c1c17b6f5e76f0fceef483 100644 (file)
@@ -1260,7 +1260,7 @@ then the request of the IRQ obviously will not succeed for all the drivers.
 15.1 Problem tracking
 
 Most SCSI problems are due to a non conformant SCSI bus or to buggy
-devices.  If infortunately you have SCSI problems, you can check the
+devices.  If unfortunately you have SCSI problems, you can check the
 following things:
 
 - SCSI bus cables
index 3c12422f7f41bf67cc6d365937090a81176eb0e0..b7be95b5bd24f1a53431ef0d45ddb85b2832c3a9 100644 (file)
@@ -1,5 +1,5 @@
 This file contains brief information about the SCSI tape driver.
-The driver is currently maintained by Kai Mäkisara (email
+The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
 Last modified: Mon Mar  7 21:14:44 2005 by kai.makisara
index 2c1745a9df0052fa634489d3f4b43dd1828a078b..3d9f06bb3d005df531abccda5ba5ad11f820b363 100644 (file)
@@ -587,7 +587,7 @@ devices, ... may cause a SCSI signal to be wrong when te driver reads it.
 15.1 Problem tracking
 
 Most SCSI problems are due to a non conformant SCSI bus or too buggy
-devices.  If infortunately you have SCSI problems, you can check the
+devices.  If unfortunately you have SCSI problems, you can check the
 following things:
 
 - SCSI bus cables
index 8b2168aa4fc7e25d318b9127d1f58d43629665ad..61c0531e044a75f68f4eea49f846d78d42f55194 100644 (file)
@@ -426,7 +426,7 @@ Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and
 all the others for the wonderful OS and software.
 Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver
 release and support.
-Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding.
+Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding.
 Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert 
 Tonneau) for intensively testing the driver (and even risking data loss
 doing this during early revisions).
index c1237a9255055635475552c519f8199303789c8e..4857acfc50f1fa025f71b7d49cd0066381642750 100644 (file)
@@ -1,7 +1,7 @@
 Sony Programmable I/O Control Device Driver Readme
 --------------------------------------------------
        Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
-       Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+       Copyright (C) 2001-2002 Alcôve <www.alcove.com>
        Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
        Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
        Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
index 858334bb46b08890cba4168e208e6eff5868c2c5..5fbcb160927589fc54f38ac423a54a85692ff11c 100644 (file)
@@ -163,7 +163,7 @@ OR the Default= line COULD be
 Default=SBPRO
 
 Reboot to Windows 95 and choose Linux. When booted, use sndconfig to configure
-the sound modules and voilà - ThinkPad sound with Linux.
+the sound modules and voilà - ThinkPad sound with Linux.
 
 Now the gotchas - you can either have CD sound OR Mixers but not both. That's a
 problem with the SB1.5 (CD sound) or SBPRO (Mixers) settings. No one knows why
index ecc7c9eb9f2938ee00b38aa30863050c3ac01c0d..795fbb48ffa7f080c88ccfd39e5afc7827183d3d 100644 (file)
@@ -8,7 +8,7 @@ What is SPI?
 The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial
 link used to connect microcontrollers to sensors, memory, and peripherals.
 
-The three signal wires hold a clock (SCLK, often on the order of 10 MHz),
+The three signal wires hold a clock (SCK, often on the order of 10 MHz),
 and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In,
 Slave Out" (MISO) signals.  (Other names are also used.)  There are four
 clocking modes through which data is exchanged; mode-0 and mode-3 are most
@@ -22,7 +22,7 @@ other signals, often including an interrupt to the master.
 
 Unlike serial busses like USB or SMBUS, even low level protocols for
 SPI slave functions are usually not interoperable between vendors
-(except for cases like SPI memory chips).
+(except for commodities like SPI memory chips).
 
   - SPI may be used for request/response style device protocols, as with
     touchscreen sensors and memory chips.
@@ -77,8 +77,9 @@ cards without needing a special purpose MMC/SD/SDIO controller.
 How do these driver programming interfaces work?
 ------------------------------------------------
 The <linux/spi/spi.h> header file includes kerneldoc, as does the
-main source code, and you should certainly read that.  This is just
-an overview, so you get the big picture before the details.
+main source code, and you should certainly read that chapter of the
+kernel API document.  This is just an overview, so you get the big
+picture before those details.
 
 SPI requests always go into I/O queues.  Requests for a given SPI device
 are always executed in FIFO order, and complete asynchronously through
@@ -88,7 +89,7 @@ a command and then reading its response.
 
 There are two types of SPI driver, here called:
 
-  Controller drivers ... these are often built in to System-On-Chip
+  Controller drivers ... controllers may be built in to System-On-Chip
        processors, and often support both Master and Slave roles.
        These drivers touch hardware registers and may use DMA.
        Or they can be PIO bitbangers, needing just GPIO pins.
@@ -108,18 +109,18 @@ those two types of driver.  At this writing, Linux has no slave side
 programming interface.
 
 There is a minimal core of SPI programming interfaces, focussing on
-using driver model to connect controller and protocol drivers using
+using the driver model to connect controller and protocol drivers using
 device tables provided by board specific initialization code.  SPI
 shows up in sysfs in several locations:
 
-   /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B",
+   /sys/devices/.../CTLR/spiB.C ... spi_device on bus "B",
        chipselect C, accessed through CTLR.
 
    /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver
        that should be used with this device (for hotplug/coldplug)
 
    /sys/bus/spi/devices/spiB.C ... symlink to the physical
-       spiB-C device
+       spiB.C device
 
    /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices
 
@@ -240,7 +241,7 @@ The board_info should provide enough information to let the system work
 without the chip's driver being loaded.  The most troublesome aspect of
 that is likely the SPI_CS_HIGH bit in the spi_device.mode field, since
 sharing a bus with a device that interprets chipselect "backwards" is
-not possible.
+not possible until the infrastructure knows how to deselect it.
 
 Then your board initialization code would register that table with the SPI
 infrastructure, so that it's available later when the SPI master controller
@@ -268,16 +269,14 @@ board info based on the board that was hotplugged.  Of course, you'd later
 call at least spi_unregister_device() when that board is removed.
 
 When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those
-configurations will also be dynamic.  Fortunately, those devices all support
-basic device identification probes, so that support should hotplug normally.
+configurations will also be dynamic.  Fortunately, such devices all support
+basic device identification probes, so they should hotplug normally.
 
 
 How do I write an "SPI Protocol Driver"?
 ----------------------------------------
-All SPI drivers are currently kernel drivers.  A userspace driver API
-would just be another kernel driver, probably offering some lowlevel
-access through aio_read(), aio_write(), and ioctl() calls and using the
-standard userspace sysfs mechanisms to bind to a given SPI device.
+Most SPI drivers are currently kernel drivers, but there's also support
+for userspace drivers.  Here we talk only about kernel drivers.
 
 SPI protocol drivers somewhat resemble platform device drivers:
 
@@ -319,7 +318,8 @@ might look like this unless you're creating a class_device:
 
 As soon as it enters probe(), the driver may issue I/O requests to
 the SPI device using "struct spi_message".  When remove() returns,
-the driver guarantees that it won't submit any more such messages.
+or after probe() fails, the driver guarantees that it won't submit
+any more such messages.
 
   - An spi_message is a sequence of protocol operations, executed
     as one atomic sequence.  SPI driver controls include:
@@ -368,7 +368,8 @@ the driver guarantees that it won't submit any more such messages.
 Some drivers may need to modify spi_device characteristics like the
 transfer mode, wordsize, or clock rate.  This is done with spi_setup(),
 which would normally be called from probe() before the first I/O is
-done to the device.
+done to the device.  However, that can also be called at any time
+that no message is pending for that device.
 
 While "spi_device" would be the bottom boundary of the driver, the
 upper boundaries might include sysfs (especially for sensor readings),
@@ -445,11 +446,15 @@ SPI MASTER METHODS
        This sets up the device clock rate, SPI mode, and word sizes.
        Drivers may change the defaults provided by board_info, and then
        call spi_setup(spi) to invoke this routine.  It may sleep.
+       Unless each SPI slave has its own configuration registers, don't
+       change them right away ... otherwise drivers could corrupt I/O
+       that's in progress for other SPI devices.
 
     master->transfer(struct spi_device *spi, struct spi_message *message)
        This must not sleep.  Its responsibility is arrange that the
-       transfer happens and its complete() callback is issued; the two
-       will normally happen later, after other transfers complete.
+       transfer happens and its complete() callback is issued.  The two
+       will normally happen later, after other transfers complete, and
+       if the controller is idle it will need to be kickstarted.
 
     master->cleanup(struct spi_device *spi)
        Your controller driver may use spi_device.controller_state to hold
diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev
new file mode 100644 (file)
index 0000000..5c8e1b9
--- /dev/null
@@ -0,0 +1,307 @@
+SPI devices have a limited userspace API, supporting basic half-duplex
+read() and write() access to SPI slave devices.  Using ioctl() requests,
+full duplex transfers and device I/O configuration are also available.
+
+       #include <fcntl.h>
+       #include <unistd.h>
+       #include <sys/ioctl.h>
+       #include <linux/types.h>
+       #include <linux/spi/spidev.h>
+
+Some reasons you might want to use this programming interface include:
+
+ * Prototyping in an environment that's not crash-prone; stray pointers
+   in userspace won't normally bring down any Linux system.
+
+ * Developing simple protocols used to talk to microcontrollers acting
+   as SPI slaves, which you may need to change quite often.
+
+Of course there are drivers that can never be written in userspace, because
+they need to access kernel interfaces (such as IRQ handlers or other layers
+of the driver stack) that are not accessible to userspace.
+
+
+DEVICE CREATION, DRIVER BINDING
+===============================
+The simplest way to arrange to use this driver is to just list it in the
+spi_board_info for a device as the driver it should use:  the "modalias"
+entry is "spidev", matching the name of the driver exposing this API.
+Set up the other device characteristics (bits per word, SPI clocking,
+chipselect polarity, etc) as usual, so you won't always need to override
+them later.
+
+(Sysfs also supports userspace driven binding/unbinding of drivers to
+devices.  That mechanism might be supported here in the future.)
+
+When you do that, the sysfs node for the SPI device will include a child
+device node with a "dev" attribute that will be understood by udev or mdev.
+(Larger systems will have "udev".  Smaller ones may configure "mdev" into
+busybox; it's less featureful, but often enough.)  For a SPI device with
+chipselect C on bus B, you should see:
+
+    /dev/spidevB.C ... character special device, major number 153 with
+       a dynamically chosen minor device number.  This is the node
+       that userspace programs will open, created by "udev" or "mdev".
+
+    /sys/devices/.../spiB.C ... as usual, the SPI device node will
+       be a child of its SPI master controller.
+
+    /sys/class/spidev/spidevB.C ... created when the "spidev" driver
+       binds to that device.  (Directory or symlink, based on whether
+       or not you enabled the "deprecated sysfs files" Kconfig option.)
+
+Do not try to manage the /dev character device special file nodes by hand.
+That's error prone, and you'd need to pay careful attention to system
+security issues; udev/mdev should already be configured securely.
+
+If you unbind the "spidev" driver from that device, those two "spidev" nodes
+(in sysfs and in /dev) should automatically be removed (respectively by the
+kernel and by udev/mdev).  You can unbind by removing the "spidev" driver
+module, which will affect all devices using this driver.  You can also unbind
+by having kernel code remove the SPI device, probably by removing the driver
+for its SPI controller (so its spi_master vanishes).
+
+Since this is a standard Linux device driver -- even though it just happens
+to expose a low level API to userspace -- it can be associated with any number
+of devices at a time.  Just provide one spi_board_info record for each such
+SPI device, and you'll get a /dev device node for each device.
+
+
+BASIC CHARACTER DEVICE API
+==========================
+Normal open() and close() operations on /dev/spidevB.D files work as you
+would expect.
+
+Standard read() and write() operations are obviously only half-duplex, and
+the chipselect is deactivated between those operations.  Full-duplex access,
+and composite operation without chipselect de-activation, is available using
+the SPI_IOC_MESSAGE(N) request.
+
+Several ioctl() requests let your driver read or override the device's current
+settings for data transfer parameters:
+
+    SPI_IOC_RD_MODE, SPI_IOC_WR_MODE ... pass a pointer to a byte which will
+       return (RD) or assign (WR) the SPI transfer mode.  Use the constants
+       SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
+       (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
+       sample on trailing edge iff this is set) flags.
+
+    SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
+       which will return (RD) or assign (WR) the bit justification used to
+       transfer SPI words.  Zero indicates MSB-first; other values indicate
+       the less common LSB-first encoding.  In both cases the specified value
+       is right-justified in each word, so that unused (TX) or undefined (RX)
+       bits are in the MSBs.
+
+    SPI_IOC_RD_BITS_PER_WORD, SPI_IOC_WR_BITS_PER_WORD ... pass a pointer to
+       a byte which will return (RD) or assign (WR) the number of bits in
+       each SPI transfer word.  The value zero signifies eight bits.
+
+    SPI_IOC_RD_MAX_SPEED_HZ, SPI_IOC_WR_MAX_SPEED_HZ ... pass a pointer to a
+       u32 which will return (RD) or assign (WR) the maximum SPI transfer
+       speed, in Hz.  The controller can't necessarily assign that specific
+       clock speed.
+
+NOTES:
+
+    - At this time there is no async I/O support; everything is purely
+      synchronous.
+
+    - There's currently no way to report the actual bit rate used to
+      shift data to/from a given device.
+
+    - From userspace, you can't currently change the chip select polarity;
+      that could corrupt transfers to other devices sharing the SPI bus.
+      Each SPI device is deselected when it's not in active use, allowing
+      other drivers to talk to other devices.
+
+    - There's a limit on the number of bytes each I/O request can transfer
+      to the SPI device.  It defaults to one page, but that can be changed
+      using a module parameter.
+
+    - Because SPI has no low-level transfer acknowledgement, you usually
+      won't see any I/O errors when talking to a non-existent device.
+
+
+FULL DUPLEX CHARACTER DEVICE API
+================================
+
+See the sample program below for one example showing the use of the full
+duplex programming interface.  (Although it doesn't perform a full duplex
+transfer.)  The model is the same as that used in the kernel spi_sync()
+request; the individual transfers offer the same capabilities as are
+available to kernel drivers (except that it's not asynchronous).
+
+The example shows one half-duplex RPC-style request and response message.
+These requests commonly require that the chip not be deselected between
+the request and response.  Several such requests could be chained into
+a single kernel request, even allowing the chip to be deselected after
+each response.  (Other protocol options include changing the word size
+and bitrate for each transfer segment.)
+
+To make a full duplex request, provide both rx_buf and tx_buf for the
+same transfer.  It's even OK if those are the same buffer.
+
+
+SAMPLE PROGRAM
+==============
+
+--------------------------------       CUT HERE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/types.h>
+#include <linux/spi/spidev.h>
+
+
+static int verbose;
+
+static void do_read(int fd, int len)
+{
+       unsigned char   buf[32], *bp;
+       int             status;
+
+       /* read at least 2 bytes, no more than 32 */
+       if (len < 2)
+               len = 2;
+       else if (len > sizeof(buf))
+               len = sizeof(buf);
+       memset(buf, 0, sizeof buf);
+
+       status = read(fd, buf, len);
+       if (status < 0) {
+               perror("read");
+               return;
+       }
+       if (status != len) {
+               fprintf(stderr, "short read\n");
+               return;
+       }
+
+       printf("read(%2d, %2d): %02x %02x,", len, status,
+               buf[0], buf[1]);
+       status -= 2;
+       bp = buf + 2;
+       while (status-- > 0)
+               printf(" %02x", *bp++);
+       printf("\n");
+}
+
+static void do_msg(int fd, int len)
+{
+       struct spi_ioc_transfer xfer[2];
+       unsigned char           buf[32], *bp;
+       int                     status;
+
+       memset(xfer, 0, sizeof xfer);
+       memset(buf, 0, sizeof buf);
+
+       if (len > sizeof buf)
+               len = sizeof buf;
+
+       buf[0] = 0xaa;
+       xfer[0].tx_buf = (__u64) buf;
+       xfer[0].len = 1;
+
+       xfer[1].rx_buf = (__u64) buf;
+       xfer[1].len = len;
+
+       status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
+       if (status < 0) {
+               perror("SPI_IOC_MESSAGE");
+               return;
+       }
+
+       printf("response(%2d, %2d): ", len, status);
+       for (bp = buf; len; len--)
+               printf(" %02x", *bp++);
+       printf("\n");
+}
+
+static void dumpstat(const char *name, int fd)
+{
+       __u8    mode, lsb, bits;
+       __u32   speed;
+
+       if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
+               perror("SPI rd_mode");
+               return;
+       }
+       if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
+               perror("SPI rd_lsb_fist");
+               return;
+       }
+       if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
+               perror("SPI bits_per_word");
+               return;
+       }
+       if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
+               perror("SPI max_speed_hz");
+               return;
+       }
+
+       printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+               name, mode, bits, lsb ? "(lsb first) " : "", speed);
+}
+
+int main(int argc, char **argv)
+{
+       int             c;
+       int             readcount = 0;
+       int             msglen = 0;
+       int             fd;
+       const char      *name;
+
+       while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
+               switch (c) {
+               case 'm':
+                       msglen = atoi(optarg);
+                       if (msglen < 0)
+                               goto usage;
+                       continue;
+               case 'r':
+                       readcount = atoi(optarg);
+                       if (readcount < 0)
+                               goto usage;
+                       continue;
+               case 'v':
+                       verbose++;
+                       continue;
+               case 'h':
+               case '?':
+usage:
+                       fprintf(stderr,
+                               "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
+                               argv[0]);
+                       return 1;
+               }
+       }
+
+       if ((optind + 1) != argc)
+               goto usage;
+       name = argv[optind];
+
+       fd = open(name, O_RDWR);
+       if (fd < 0) {
+               perror("open");
+               return 1;
+       }
+
+       dumpstat(name, fd);
+
+       if (msglen)
+               do_msg(fd, msglen);
+
+       if (readcount)
+               do_read(fd, readcount);
+
+       close(fd);
+       return 0;
+}
index 5922e84d913340b98891a8e583663ab55ad3c5a6..111fd28727ec3754931d5de68ab21037871382c0 100644 (file)
@@ -221,14 +221,14 @@ Controls the kernel's behaviour when an oops or BUG is encountered.
 
 0: try to continue operation
 
-1: panic immediatly.  If the `panic' sysctl is also non-zero then the
+1: panic immediately.  If the `panic' sysctl is also non-zero then the
    machine will be rebooted.
 
 ==============================================================
 
 pid_max:
 
-PID allocation wrap value.  When the kenrel's next PID value
+PID allocation wrap value.  When the kernel's next PID value
 reaches this value, it wraps back to a minimum PID value.
 PIDs of value pid_max or larger are not allocated.
 
index 5f799e612e039f19f530090cd01161fdfc12c1ca..048a8762cfb548fbe2b2078ea8527a7a9c50bc01 100644 (file)
@@ -108,7 +108,9 @@ hardware driver through the function pointers within the tty->driver
 structure:
 
 write()                        Write a block of characters to the tty device.
-                       Returns the number of characters accepted.
+                       Returns the number of characters accepted. The
+                       character buffer passed to this method is already
+                       in kernel space.
 
 put_char()             Queues a character for writing to the tty device.
                        If there is no room in the queue, the character is
index 27a721635f924808f1953e3a1e9cf3fdecd487a4..67c59cdc9959b4f6d0987fc5d87dee809d24c91b 100644 (file)
@@ -65,7 +65,7 @@ THANKS file in Inaky's driver):
           will sell keyboards to some of the 3 million (at least)
           Linux users.
 
-        - Many thanks to ing büro h doran [http://www.ibhdoran.com]!
+        - Many thanks to ing büro h doran [http://www.ibhdoran.com]!
           It was almost impossible to get a PC backplate USB connector
           for the motherboard here at Europe (mine, home-made, was
           quite lousy :). Now I know where to acquire nice USB stuff!
index b18e86a225068c212e18a141a940b2481be59209..5b635ae849443a1deae12b9f0c0019cc06bcc4e5 100644 (file)
@@ -45,9 +45,9 @@ ConnectTech WhiteHEAT 4 port converter
   Connect Tech's Support Department at support@connecttech.com
 
 
-HandSpring Visor, Palm USB, and Clié USB driver
+HandSpring Visor, Palm USB, and Clié USB driver
 
-  This driver works with all HandSpring USB, Palm USB, and Sony Clié USB
+  This driver works with all HandSpring USB, Palm USB, and Sony Clié USB
   devices.
 
   Only when the device tries to connect to the host, will the device show
@@ -69,7 +69,7 @@ HandSpring Visor, Palm USB, and Cli
   the port to use for the HotSync transfer. The "Generic" port can be used
   for other device communication, such as a PPP link.
 
-  For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the
+  For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the
   device.  This is true for all OS version 3.5 devices, and most devices
   that have had a flash upgrade to a newer version of the OS.  See the
   kernel system log for information on which is the correct port to use.
index a4b7ae800866c4ad6411187d7a65e1f021f7bbe5..a747200fe67c5b7d4bdcae47bdee0ee2508ce3bd 100644 (file)
@@ -8,7 +8,7 @@ Background:
 
   This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which
   is a USB 2.0 hosted TV Tuner.  This driver is a work in progress.
-  Its history started with the reverse-engineering effort by Björn
+  Its history started with the reverse-engineering effort by Björn
   Danielsson <pvrusb2@dax.nu> whose web page can be found here:
 
     http://pvrusb2.dax.nu/
index 85c575ac4fb982dfbfe16e7258c4b7f0909633cb..295462b2317a46a3c191c446030030efea063bdb 100644 (file)
@@ -242,7 +242,7 @@ can generate: PAL , NTSC , SECAM
 
 Conexant bt866 TV encoder
 is used in AVS6EYES, and
-can generate: NTSC/PAL, PAL­M, PAL­N
+can generate: NTSC/PAL, PAL­M, PAL­N
 
 The adv717x, should be able to produce PAL N. But you find nothing PAL N
 specific in the registers. Seem that you have to reuse a other standard
index 5e51c59bf2b024e2915d747e76f63d00e11d53f9..bf3af5fe558f09e37b5ad2d7e06e6c36ca63c2c1 100644 (file)
@@ -1,7 +1,7 @@
 Vaio Picturebook Motion Eye Camera Driver Readme
 ------------------------------------------------
        Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
-       Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+       Copyright (C) 2001-2002 Alcôve <www.alcove.com>
        Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
 
 This driver enable the use of video4linux compatible applications with the
index 79af610d4ba59175ebabcb3cb18c58dfc937d914..b3326b167ada592b0d2b7eb7e408d299509ae92d 100644 (file)
@@ -195,11 +195,11 @@ MODULE PARAMETERS:
   NAME: bandingfilter
   TYPE: integer (Boolean)
   DEFAULT: 0 (off)
-  DESC: Enables the sensor´s banding filter exposure algorithm. This reduces
+  DESC: Enables the sensor´s banding filter exposure algorithm. This reduces
        or stabilizes the "banding" caused by some artificial light sources
        (especially fluorescent). You might have to set lightfreq correctly for
        this to work right. As an added bonus, this sometimes makes it
-       possible to capture your monitor´s output.
+       possible to capture your monitor´s output.
 
   NAME: fastset
   TYPE: integer (Boolean)
index 41710ccf3a29a1f138537de5c96d00f429289096..686a8e04a4f3c3902ff130b571fc8af53776c542 100644 (file)
@@ -16,6 +16,7 @@
 #include <stdarg.h>
 #include <getopt.h>
 #include <regex.h>
+#include <errno.h>
 
 #define MAX_SLABS 500
 #define MAX_ALIASES 500
@@ -41,12 +42,15 @@ struct aliasinfo {
 } aliasinfo[MAX_ALIASES];
 
 int slabs = 0;
+int actual_slabs = 0;
 int aliases = 0;
 int alias_targets = 0;
 int highest_node = 0;
 
 char buffer[4096];
 
+int show_empty = 0;
+int show_report = 0;
 int show_alias = 0;
 int show_slab = 0;
 int skip_zero = 1;
@@ -59,6 +63,15 @@ int show_inverted = 0;
 int show_single_ref = 0;
 int show_totals = 0;
 int sort_size = 0;
+int set_debug = 0;
+int show_ops = 0;
+
+/* Debug options */
+int sanity = 0;
+int redzone = 0;
+int poison = 0;
+int tracking = 0;
+int tracing = 0;
 
 int page_size;
 
@@ -76,20 +89,33 @@ void fatal(const char *x, ...)
 
 void usage(void)
 {
-       printf("slabinfo [-ahnpvtsz] [slab-regexp]\n"
+       printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n"
+               "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
                "-a|--aliases           Show aliases\n"
+               "-d<options>|--debug=<options> Set/Clear Debug options\n"
+               "-e|--empty             Show empty slabs\n"
+               "-f|--first-alias       Show first alias\n"
                "-h|--help              Show usage information\n"
+               "-i|--inverted          Inverted list\n"
+               "-l|--slabs             Show slabs\n"
                "-n|--numa              Show NUMA information\n"
+               "-o|--ops               Show kmem_cache_ops\n"
                "-s|--shrink            Shrink slabs\n"
-               "-v|--validate          Validate slabs\n"
+               "-r|--report            Detailed report on single slabs\n"
+               "-S|--Size              Sort by size\n"
                "-t|--tracking          Show alloc/free information\n"
                "-T|--Totals            Show summary information\n"
-               "-l|--slabs             Show slabs\n"
-               "-S|--Size              Sort by size\n"
+               "-v|--validate          Validate slabs\n"
                "-z|--zero              Include empty slabs\n"
-               "-f|--first-alias       Show first alias\n"
-               "-i|--inverted          Inverted list\n"
                "-1|--1ref              Single reference\n"
+               "\nValid debug options (FZPUT may be combined)\n"
+               "a / A          Switch on all debug options (=FZUP)\n"
+               "-              Switch off all debug options\n"
+               "f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"
+               "z / Z          Redzoning\n"
+               "p / P          Poisoning\n"
+               "u / U          Tracking\n"
+               "t / T          Tracing\n"
        );
 }
 
@@ -143,11 +169,10 @@ unsigned long get_obj_and_str(char *name, char **x)
 void set_obj(struct slabinfo *s, char *name, int n)
 {
        char x[100];
+       FILE *f;
 
        sprintf(x, "%s/%s", s->name, name);
-
-       FILE *f = fopen(x, "w");
-
+       f = fopen(x, "w");
        if (!f)
                fatal("Cannot write to %s\n", x);
 
@@ -155,6 +180,26 @@ void set_obj(struct slabinfo *s, char *name, int n)
        fclose(f);
 }
 
+unsigned long read_slab_obj(struct slabinfo *s, char *name)
+{
+       char x[100];
+       FILE *f;
+       int l;
+
+       sprintf(x, "%s/%s", s->name, name);
+       f = fopen(x, "r");
+       if (!f) {
+               buffer[0] = 0;
+               l = 0;
+       } else {
+               l = fread(buffer, 1, sizeof(buffer), f);
+               buffer[l] = 0;
+               fclose(f);
+       }
+       return l;
+}
+
+
 /*
  * Put a size string together
  */
@@ -226,7 +271,7 @@ int line = 0;
 
 void first_line(void)
 {
-       printf("Name                 Objects   Objsize    Space "
+       printf("Name                   Objects Objsize    Space "
                "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
 }
 
@@ -246,10 +291,7 @@ struct aliasinfo *find_one_alias(struct slabinfo *find)
                                        return best;
                        }
        }
-       if (best)
-               return best;
-       fatal("Cannot find alias for %s\n", find->name);
-       return NULL;
+       return best;
 }
 
 unsigned long slab_size(struct slabinfo *s)
@@ -257,6 +299,126 @@ unsigned long slab_size(struct slabinfo *s)
        return  s->slabs * (page_size << s->order);
 }
 
+void slab_numa(struct slabinfo *s, int mode)
+{
+       int node;
+
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (!highest_node) {
+               printf("\n%s: No NUMA information available.\n", s->name);
+               return;
+       }
+
+       if (skip_zero && !s->slabs)
+               return;
+
+       if (!line) {
+               printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
+               for(node = 0; node <= highest_node; node++)
+                       printf(" %4d", node);
+               printf("\n----------------------");
+               for(node = 0; node <= highest_node; node++)
+                       printf("-----");
+               printf("\n");
+       }
+       printf("%-21s ", mode ? "All slabs" : s->name);
+       for(node = 0; node <= highest_node; node++) {
+               char b[20];
+
+               store_size(b, s->numa[node]);
+               printf(" %4s", b);
+       }
+       printf("\n");
+       if (mode) {
+               printf("%-21s ", "Partial slabs");
+               for(node = 0; node <= highest_node; node++) {
+                       char b[20];
+
+                       store_size(b, s->numa_partial[node]);
+                       printf(" %4s", b);
+               }
+               printf("\n");
+       }
+       line++;
+}
+
+void show_tracking(struct slabinfo *s)
+{
+       printf("\n%s: Kernel object allocation\n", s->name);
+       printf("-----------------------------------------------------------------------\n");
+       if (read_slab_obj(s, "alloc_calls"))
+               printf(buffer);
+       else
+               printf("No Data\n");
+
+       printf("\n%s: Kernel object freeing\n", s->name);
+       printf("------------------------------------------------------------------------\n");
+       if (read_slab_obj(s, "free_calls"))
+               printf(buffer);
+       else
+               printf("No Data\n");
+
+}
+
+void ops(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (read_slab_obj(s, "ops")) {
+               printf("\n%s: kmem_cache operations\n", s->name);
+               printf("--------------------------------------------\n");
+               printf(buffer);
+       } else
+               printf("\n%s has no kmem_cache operations\n", s->name);
+}
+
+const char *onoff(int x)
+{
+       if (x)
+               return "On ";
+       return "Off";
+}
+
+void report(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+       printf("\nSlabcache: %-20s  Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order);
+       if (s->hwcache_align)
+               printf("** Hardware cacheline aligned\n");
+       if (s->cache_dma)
+               printf("** Memory is allocated in a special DMA zone\n");
+       if (s->destroy_by_rcu)
+               printf("** Slabs are destroyed via RCU\n");
+       if (s->reclaim_account)
+               printf("** Reclaim accounting active\n");
+
+       printf("\nSizes (bytes)     Slabs              Debug                Memory\n");
+       printf("------------------------------------------------------------------------\n");
+       printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",
+                       s->object_size, s->slabs, onoff(s->sanity_checks),
+                       s->slabs * (page_size << s->order));
+       printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",
+                       s->slab_size, s->slabs - s->partial - s->cpu_slabs,
+                       onoff(s->red_zone), s->objects * s->object_size);
+       printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",
+                       page_size << s->order, s->partial, onoff(s->poison),
+                       s->slabs * (page_size << s->order) - s->objects * s->object_size);
+       printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",
+                       s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
+                       (s->slab_size - s->object_size) * s->objects);
+       printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",
+                       s->align, s->objs_per_slab, onoff(s->trace),
+                       ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
+                       s->slabs);
+
+       ops(s);
+       show_tracking(s);
+       slab_numa(s, 1);
+}
 
 void slabcache(struct slabinfo *s)
 {
@@ -265,7 +427,18 @@ void slabcache(struct slabinfo *s)
        char flags[20];
        char *p = flags;
 
-       if (skip_zero && !s->slabs)
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (actual_slabs == 1) {
+               report(s);
+               return;
+       }
+
+       if (skip_zero && !show_empty && !s->slabs)
+               return;
+
+       if (show_empty && s->slabs)
                return;
 
        store_size(size_str, slab_size(s));
@@ -303,48 +476,128 @@ void slabcache(struct slabinfo *s)
                flags);
 }
 
-void slab_numa(struct slabinfo *s)
+/*
+ * Analyze debug options. Return false if something is amiss.
+ */
+int debug_opt_scan(char *opt)
 {
-       int node;
+       if (!opt || !opt[0] || strcmp(opt, "-") == 0)
+               return 1;
+
+       if (strcasecmp(opt, "a") == 0) {
+               sanity = 1;
+               poison = 1;
+               redzone = 1;
+               tracking = 1;
+               return 1;
+       }
 
-       if (!highest_node)
-               fatal("No NUMA information available.\n");
+       for ( ; *opt; opt++)
+               switch (*opt) {
+               case 'F' : case 'f':
+                       if (sanity)
+                               return 0;
+                       sanity = 1;
+                       break;
+               case 'P' : case 'p':
+                       if (poison)
+                               return 0;
+                       poison = 1;
+                       break;
 
-       if (skip_zero && !s->slabs)
-               return;
+               case 'Z' : case 'z':
+                       if (redzone)
+                               return 0;
+                       redzone = 1;
+                       break;
 
-       if (!line) {
-               printf("\nSlab             Node ");
-               for(node = 0; node <= highest_node; node++)
-                       printf(" %4d", node);
-               printf("\n----------------------");
-               for(node = 0; node <= highest_node; node++)
-                       printf("-----");
-               printf("\n");
-       }
-       printf("%-21s ", s->name);
-       for(node = 0; node <= highest_node; node++) {
-               char b[20];
+               case 'U' : case 'u':
+                       if (tracking)
+                               return 0;
+                       tracking = 1;
+                       break;
 
-               store_size(b, s->numa[node]);
-               printf(" %4s", b);
-       }
-       printf("\n");
-       line++;
+               case 'T' : case 't':
+                       if (tracing)
+                               return 0;
+                       tracing = 1;
+                       break;
+               default:
+                       return 0;
+               }
+       return 1;
 }
 
-void show_tracking(struct slabinfo *s)
+int slab_empty(struct slabinfo *s)
 {
-       printf("\n%s: Calls to allocate a slab object\n", s->name);
-       printf("---------------------------------------------------\n");
-       if (read_obj("alloc_calls"))
-               printf(buffer);
+       if (s->objects > 0)
+               return 0;
 
-       printf("%s: Calls to free a slab object\n", s->name);
-       printf("-----------------------------------------------\n");
-       if (read_obj("free_calls"))
-               printf(buffer);
+       /*
+        * We may still have slabs even if there are no objects. Shrinking will
+        * remove them.
+        */
+       if (s->slabs != 0)
+               set_obj(s, "shrink", 1);
 
+       return 1;
+}
+
+void slab_debug(struct slabinfo *s)
+{
+       if (sanity && !s->sanity_checks) {
+               set_obj(s, "sanity", 1);
+       }
+       if (!sanity && s->sanity_checks) {
+               if (slab_empty(s))
+                       set_obj(s, "sanity", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
+       }
+       if (redzone && !s->red_zone) {
+               if (slab_empty(s))
+                       set_obj(s, "red_zone", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
+       }
+       if (!redzone && s->red_zone) {
+               if (slab_empty(s))
+                       set_obj(s, "red_zone", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
+       }
+       if (poison && !s->poison) {
+               if (slab_empty(s))
+                       set_obj(s, "poison", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
+       }
+       if (!poison && s->poison) {
+               if (slab_empty(s))
+                       set_obj(s, "poison", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
+       }
+       if (tracking && !s->store_user) {
+               if (slab_empty(s))
+                       set_obj(s, "store_user", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
+       }
+       if (!tracking && s->store_user) {
+               if (slab_empty(s))
+                       set_obj(s, "store_user", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
+       }
+       if (tracing && !s->trace) {
+               if (slabs == 1)
+                       set_obj(s, "trace", 1);
+               else
+                       fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
+       }
+       if (!tracing && s->trace)
+               set_obj(s, "trace", 1);
 }
 
 void totals(void)
@@ -673,7 +926,7 @@ void link_slabs(void)
 
        for (a = aliasinfo; a < aliasinfo + aliases; a++) {
 
-               for(s = slabinfo; s < slabinfo + slabs; s++)
+               for (s = slabinfo; s < slabinfo + slabs; s++)
                        if (strcmp(a->ref, s->name) == 0) {
                                a->slab = s;
                                s->refs++;
@@ -704,7 +957,7 @@ void alias(void)
                                        continue;
                                }
                        }
-                       printf("\n%-20s <- %s", a->slab->name, a->name);
+                       printf("\n%-12s <- %s", a->slab->name, a->name);
                        active = a->slab->name;
                }
                else
@@ -729,7 +982,12 @@ void rename_slabs(void)
 
                a = find_one_alias(s);
 
-               s->name = a->name;
+               if (a)
+                       s->name = a->name;
+               else {
+                       s->name = "*";
+                       actual_slabs--;
+               }
        }
 }
 
@@ -748,11 +1006,14 @@ void read_slab_dir(void)
        char *t;
        int count;
 
+       if (chdir("/sys/slab"))
+               fatal("SYSFS support for SLUB not active\n");
+
        dir = opendir(".");
        while ((de = readdir(dir))) {
                if (de->d_name[0] == '.' ||
-                               slab_mismatch(de->d_name))
-                       continue;
+                       (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
+                               continue;
                switch (de->d_type) {
                   case DT_LNK:
                        alias->name = strdup(de->d_name);
@@ -807,6 +1068,7 @@ void read_slab_dir(void)
        }
        closedir(dir);
        slabs = slab - slabinfo;
+       actual_slabs = slabs;
        aliases = alias - aliasinfo;
        if (slabs > MAX_SLABS)
                fatal("Too many slabs\n");
@@ -825,34 +1087,37 @@ void output_slabs(void)
 
 
                if (show_numa)
-                       slab_numa(slab);
-               else
-               if (show_track)
+                       slab_numa(slab, 0);
+               else if (show_track)
                        show_tracking(slab);
-               else
-               if (validate)
+               else if (validate)
                        slab_validate(slab);
-               else
-               if (shrink)
+               else if (shrink)
                        slab_shrink(slab);
-               else {
-                       if (show_slab)
-                               slabcache(slab);
-               }
+               else if (set_debug)
+                       slab_debug(slab);
+               else if (show_ops)
+                       ops(slab);
+               else if (show_slab)
+                       slabcache(slab);
        }
 }
 
 struct option opts[] = {
        { "aliases", 0, NULL, 'a' },
-       { "slabs", 0, NULL, 'l' },
-       { "numa", 0, NULL, 'n' },
-       { "zero", 0, NULL, 'z' },
-       { "help", 0, NULL, 'h' },
-       { "validate", 0, NULL, 'v' },
+       { "debug", 2, NULL, 'd' },
+       { "empty", 0, NULL, 'e' },
        { "first-alias", 0, NULL, 'f' },
+       { "help", 0, NULL, 'h' },
+       { "inverted", 0, NULL, 'i'},
+       { "numa", 0, NULL, 'n' },
+       { "ops", 0, NULL, 'o' },
+       { "report", 0, NULL, 'r' },
        { "shrink", 0, NULL, 's' },
+       { "slabs", 0, NULL, 'l' },
        { "track", 0, NULL, 't'},
-       { "inverted", 0, NULL, 'i'},
+       { "validate", 0, NULL, 'v' },
+       { "zero", 0, NULL, 'z' },
        { "1ref", 0, NULL, '1'},
        { NULL, 0, NULL, 0 }
 };
@@ -864,10 +1129,9 @@ int main(int argc, char *argv[])
        char *pattern_source;
 
        page_size = getpagesize();
-       if (chdir("/sys/slab"))
-               fatal("This kernel does not have SLUB support.\n");
 
-       while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1)
+       while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS",
+                                               opts, NULL)) != -1)
        switch(c) {
                case '1':
                        show_single_ref = 1;
@@ -875,6 +1139,14 @@ int main(int argc, char *argv[])
                case 'a':
                        show_alias = 1;
                        break;
+               case 'd':
+                       set_debug = 1;
+                       if (!debug_opt_scan(optarg))
+                               fatal("Invalid debug option '%s'\n", optarg);
+                       break;
+               case 'e':
+                       show_empty = 1;
+                       break;
                case 'f':
                        show_first_alias = 1;
                        break;
@@ -887,6 +1159,12 @@ int main(int argc, char *argv[])
                case 'n':
                        show_numa = 1;
                        break;
+               case 'o':
+                       show_ops = 1;
+                       break;
+               case 'r':
+                       show_report = 1;
+                       break;
                case 's':
                        shrink = 1;
                        break;
@@ -914,8 +1192,8 @@ int main(int argc, char *argv[])
 
        }
 
-       if (!show_slab && !show_alias && !show_track
-               && !validate && !shrink)
+       if (!show_slab && !show_alias && !show_track && !show_report
+               && !validate && !shrink && !set_debug && !show_ops)
                        show_slab = 1;
 
        if (argc > optind)
index 6d665ac13f99fca1fcb1838189ae86010b657322..cfd26ddccd7a0997c10ed46e4c15a7dc021c1761 100644 (file)
@@ -382,6 +382,12 @@ L: linux-laptop@vger.kernel.org
 W:     http://www.canb.auug.org.au/~sfr/
 S:     Supported
 
+APPLE SMC DRIVER
+P:     Nicolas Boichat
+M:     nicolas@boichat.ch
+L:     mactel-linux-devel@lists.sourceforge.net
+S:     Maintained
+
 APPLETALK NETWORK LAYER
 P:     Arnaldo Carvalho de Melo
 M:     acme@ghostprotocols.net
@@ -673,6 +679,7 @@ AUXILIARY DISPLAY DRIVERS
 P:     Miguel Ojeda Sandonis
 M:     maxextreme@gmail.com
 L:     linux-kernel@vger.kernel.org
+W:     http://auxdisplay.googlepages.com/
 S:     Maintained
 
 AVR32 ARCHITECTURE
@@ -937,12 +944,14 @@ CFAG12864B LCD DRIVER
 P:     Miguel Ojeda Sandonis
 M:     maxextreme@gmail.com
 L:     linux-kernel@vger.kernel.org
+W:     http://auxdisplay.googlepages.com/
 S:     Maintained
 
 CFAG12864BFB LCD FRAMEBUFFER DRIVER
 P:     Miguel Ojeda Sandonis
 M:     maxextreme@gmail.com
 L:     linux-kernel@vger.kernel.org
+W:     http://auxdisplay.googlepages.com/
 S:     Maintained
 
 CFG80211 and NL80211
@@ -1029,6 +1038,14 @@ S:       Maintained
 CONEXANT ACCESSRUNNER USB DRIVER
 P:     Simon Arlott
 M:     cxacru@fire.lp0.eu
+L:     accessrunner-general@lists.sourceforge.net
+W:     http://accessrunner.sourceforge.net/
+S:     Maintained
+
+CORETEMP HARDWARE MONITORING DRIVER
+P:     Rudolf Marek
+M:     r.marek@assembler.cz
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 COSA/SRP SYNC SERIAL DRIVER
@@ -2021,7 +2038,7 @@ P:        Vivek Goyal
 M:     vgoyal@in.ibm.com
 P:     Haren Myneni
 M:     hbabu@us.ibm.com
-L:     fastboot@lists.linux-foundation.org
+L:     kexec@lists.infradead.org
 L:     linux-kernel@vger.kernel.org
 W:     http://lse.sourceforge.net/kdump/
 S:     Maintained
@@ -2071,7 +2088,7 @@ P:        Eric Biederman
 M:     ebiederm@xmission.com
 W:     http://www.xmission.com/~ebiederm/files/kexec/
 L:     linux-kernel@vger.kernel.org
-L:     fastboot@lists.linux-foundation.org
+L:     kexec@lists.infradead.org
 S:     Maintained
 
 KPROBES
@@ -2090,6 +2107,7 @@ KS0108 LCD CONTROLLER DRIVER
 P:     Miguel Ojeda Sandonis
 M:     maxextreme@gmail.com
 L:     linux-kernel@vger.kernel.org
+W:     http://auxdisplay.googlepages.com/
 S:     Maintained
 
 LAPB module
@@ -2304,6 +2322,12 @@ M:       vandrove@vc.cvut.cz
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
+MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
+P:     Hans J. Koch
+M:     hjk@linutronix.de
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+
 MEGARAID SCSI DRIVERS
 P:     Neela Syam Kolli
 M:     Neela.Kolli@engenio.com
@@ -2624,6 +2648,12 @@ M:       corbet@lwn.net
 L:     video4linux-list@redhat.com
 S:     Maintained
 
+ONENAND FLASH DRIVER
+P:     Kyungmin Park
+M:     kyungmin.park@samsung.com
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+
 ONSTREAM SCSI TAPE DRIVER
 P:     Willem Riede
 M:     osst@riede.org
@@ -2778,7 +2808,7 @@ L:        linux-abi-devel@lists.sourceforge.net
 S:     Maintained
 
 PHRAM MTD DRIVER
-P:     Jörn Engel
+P:     Jörn Engel
 M:     joern@wh.fh-wedel.de
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
@@ -3052,7 +3082,7 @@ T:        git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 S:     Maintained
 
 SCSI TAPE DRIVER
-P:     Kai Mäkisara
+P:     Kai Mäkisara
 M:     Kai.Makisara@kolumbus.fi
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
@@ -3098,6 +3128,11 @@ L:       selinux@tycho.nsa.gov (subscribers-only, general discussion)
 W:     http://www.nsa.gov/selinux
 S:     Supported
 
+SENSABLE PHANTOM
+P:     Jiri Slaby
+M:     jirislaby@gmail.com
+S:     Maintained
+
 SERIAL ATA (SATA) SUBSYSTEM:
 P:     Jeff Garzik
 M:     jgarzik@pobox.com
index 36d0106c32ebe18c3be257b6264bd4be2a573dde..f45f28cc10da94e24c4add02315f950f9787ec37 100644 (file)
@@ -16,14 +16,6 @@ config DEBUG_RWLOCK
          too many attempts.  If you suspect a rwlock problem or a kernel
          hacker asks for this option then say Y.  Otherwise say N.
 
-config DEBUG_SEMAPHORE
-       bool "Semaphore debugging"
-       depends on DEBUG_KERNEL
-       help
-         If you say Y here then semaphore processing will issue lots of
-         verbose debugging messages.  If you suspect a semaphore problem or a
-         kernel hacker asks for this option then say Y.  Otherwise say N.
-
 config ALPHA_LEGACY_START_ADDRESS
        bool "Legacy kernel start address"
        depends on ALPHA_GENERIC
index ea405f5713ce0e75e72a18fb960955f02153c28b..ce857158c1eacc2a1b22ac0f6c278a5501d9d42b 100644 (file)
@@ -953,15 +953,25 @@ osf_setitimer(int which, struct itimerval32 __user *in, struct itimerval32 __use
 asmlinkage int
 osf_utimes(char __user *filename, struct timeval32 __user *tvs)
 {
-       struct timeval ktvs[2];
+       struct timespec tv[2];
 
        if (tvs) {
+               struct timeval ktvs[2];
                if (get_tv32(&ktvs[0], &tvs[0]) ||
                    get_tv32(&ktvs[1], &tvs[1]))
                        return -EFAULT;
+
+               if (ktvs[0].tv_usec < 0 || ktvs[0].tv_usec >= 1000000 ||
+                   ktvs[1].tv_usec < 0 || ktvs[1].tv_usec >= 1000000)
+                       return -EINVAL;
+
+               tv[0].tv_sec = ktvs[0].tv_sec;
+               tv[0].tv_nsec = 1000 * ktvs[0].tv_usec;
+               tv[1].tv_sec = ktvs[1].tv_sec;
+               tv[1].tv_nsec = 1000 * ktvs[1].tv_usec;
        }
 
-       return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL);
+       return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
 }
 
 #define MAX_SELECT_SECONDS \
index c151863906932239309079c0719d8d13b148b2b1..92b61629fe3f5787fe11c2ed2eb319619524ebcb 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
index d352c2b05f1a245503e5af698b4d8ef6a7858aeb..915f26345c45c91a1105d97ed7256c40a859455b 100644 (file)
@@ -744,15 +744,6 @@ setup_arch(char **cmdline_p)
        paging_init();
 }
 
-void __init
-disable_early_printk(void)
-{
-       if (alpha_using_srm && srmcons_output) {
-               unregister_srm_console();
-               srmcons_output = 0;
-       }
-}
-
 static char sys_unknown[] = "Unknown";
 static char systype_names[][16] = {
        "0",
index 741da0945dc4c801c0e97ca2ae2f35aaea5c8bc0..7f64aa767d5a2f92aa8dfca13d466b3983dc64c3 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
index d1ec4f51df1aae6c3678dc85d393edb2d33ee321..80cfb758ee2be787da0b506db3b4353d22b91e08 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mm.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index 85a821aaceb47d68c822e3b656b471ded8a30d65..930cedc8be24120d4b7f876876a1ce017618abbd 100644 (file)
@@ -300,7 +300,7 @@ static struct console srmcons = {
        .write          = srm_console_write,
        .device         = srm_console_device,
        .setup          = srm_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER | CON_BOOT,
        .index          = -1,
 };
 
index 8aa9db834c11551afc1462bf970d2dbc0ab8a157..f5862792a167049b16f625552c2314c20c0681df 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 
index 0d8fac3b03713020cf4ad3dc98eab209cbc0a5a1..d7c0984d4a8662a48fc47f2d922ab8cb7806b030 100644 (file)
@@ -354,6 +354,7 @@ config ARCH_SA1100
 config ARCH_S3C2410
        bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
        select GENERIC_GPIO
+       select GENERIC_TIME
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
index ab9f2d4bd04ed0a15b948381070c99eff7d7626b..00ea4305ad5d2bb1e1d690544235a852793e5986 100644 (file)
@@ -47,8 +47,13 @@ comma = ,
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_CPU_32v7)                :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a)
 arch-$(CONFIG_CPU_32v6)                :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+# Only override the compiler option if ARMv6. The ARMv6K extensions are
+# always available in ARMv7
+ifeq ($(CONFIG_CPU_32v6),y)
 arch-$(CONFIG_CPU_32v6K)       :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
+endif
 arch-$(CONFIG_CPU_32v5)                :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
 arch-$(CONFIG_CPU_32v4T)       :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
 arch-$(CONFIG_CPU_32v4)                :=-D__LINUX_ARM_ARCH__=4 -march=armv4
index 0119c0d5f9788009b30cd135b3a8b51dda9c354d..5d78ffb8a9a7fe0e653f9356d5b873896492a53c 100644 (file)
@@ -33,7 +33,7 @@
  * numbers for r1.
  *
  */
-       __INIT
+       .section ".text.head", "ax"
        .type   stext, %function
 ENTRY(stext)
        msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
index 1d35edacc01113af898946e8d5b33f4b7a0dc17d..41f98b4ba2ee256d5998a514dd20bcf250bad577 100644 (file)
@@ -73,7 +73,7 @@
  * crap here - that's what the boot loader (or in extreme, well justified
  * circumstances, zImage) is for.
  */
-       __INIT
+       .section ".text.head", "ax"
        .type   stext, %function
 ENTRY(stext)
        msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
index a00cca0000bd2782bcfe50eee16e6c7b412f4aef..bd4ef53bc6b95ee03f8eac412e03563146a27a4f 100644 (file)
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(init_mm);
  * The things we do for performance..
  */
 union thread_union init_thread_union
-       __attribute__((__section__(".init.task"))) =
+       __attribute__((__section__(".data.init_task"))) =
                { INIT_THREAD_INFO(init_task) };
 
 /*
index 1b061583408ed7f44158a7dfcf7b996e56f7a53f..79b7e5cf5416cff90059fd145ca6a2c76d253011 100644 (file)
@@ -116,8 +116,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 
                        offset += sym->st_value - loc;
                        if (offset & 3 ||
-                           offset <= (s32)0xfc000000 ||
-                           offset >= (s32)0x04000000) {
+                           offset <= (s32)0xfe000000 ||
+                           offset >= (s32)0x02000000) {
                                printk(KERN_ERR
                                       "%s: relocation out of range, section "
                                       "%d reloc %d sym '%s'\n", module->name,
index 13af4006a40fa3a0022a5331a39111769e99b6f1..6f2f46c2e406ee844632da068353b0167735886e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
index 070bcb7a63068188dfd7b39ad4be75dd3dede3d7..1b76d87fa335de634f7151c630cec6005ec340ec 100644 (file)
@@ -486,7 +486,7 @@ static void ipi_timer(void)
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void do_local_timer(struct pt_regs *regs)
+asmlinkage void __exception do_local_timer(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        int cpu = smp_processor_id();
@@ -551,7 +551,7 @@ static void ipi_cpu_stop(unsigned int cpu)
  *
  *  Bit 0 - Inter-processor function call
  */
-asmlinkage void do_IPI(struct pt_regs *regs)
+asmlinkage void __exception do_IPI(struct pt_regs *regs)
 {
        unsigned int cpu = smp_processor_id();
        struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
index f05e66b0f868df49fcd4e6ca4faeaf7b26c32fe2..10ff36e4e414f96132e0b8f45136d24fb3118a44 100644 (file)
@@ -245,8 +245,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
        do_exit(SIGSEGV);
 }
 
-void notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
-               unsigned long err, unsigned long trap)
+void arm_notify_die(const char *str, struct pt_regs *regs,
+               struct siginfo *info, unsigned long err, unsigned long trap)
 {
        if (user_mode(regs)) {
                current->thread.error_code = err;
@@ -330,7 +330,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
        info.si_code  = ILL_ILLOPC;
        info.si_addr  = pc;
 
-       notify_die("Oops - undefined instruction", regs, &info, 0, 6);
+       arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
 }
 
 asmlinkage void do_unexp_fiq (struct pt_regs *regs)
@@ -384,7 +384,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
        info.si_addr  = (void __user *)instruction_pointer(regs) -
                         (thumb_mode(regs) ? 2 : 4);
 
-       notify_die("Oops - bad syscall", regs, &info, n, 0);
+       arm_notify_die("Oops - bad syscall", regs, &info, n, 0);
 
        return regs->ARM_r0;
 }
@@ -428,7 +428,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                info.si_code  = SEGV_MAPERR;
                info.si_addr  = NULL;
 
-               notify_die("branch through zero", regs, &info, 0, 0);
+               arm_notify_die("branch through zero", regs, &info, 0, 0);
                return 0;
 
        case NR(breakpoint): /* SWI BREAK_POINT */
@@ -564,7 +564,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
        info.si_addr  = (void __user *)instruction_pointer(regs) -
                         (thumb_mode(regs) ? 2 : 4);
 
-       notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
+       arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
        return 0;
 }
 
@@ -638,7 +638,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
        info.si_code  = ILL_ILLOPC;
        info.si_addr  = (void __user *)addr;
 
-       notify_die("unknown data abort code", regs, &info, instr, 0);
+       arm_notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
 void __attribute__((noreturn)) __bug(const char *file, int line)
index 6be67296f33326eea42bc44045cbc16e8f02efd1..e4156e7868ce5987ef5311c1b2c309cda121beb8 100644 (file)
@@ -23,11 +23,15 @@ SECTIONS
 #else
        . = PAGE_OFFSET + TEXT_OFFSET;
 #endif
-       .init : {                       /* Init code and data           */
+       .text.head : {
                _stext = .;
-                       _sinittext = .;
+               _sinittext = .;
+               *(.text.head)
+       }
+
+       .init : {                       /* Init code and data           */
                        *(.init.text)
-                       _einittext = .;
+               _einittext = .;
                __proc_info_begin = .;
                        *(.proc.info.init)
                __proc_info_end = .;
@@ -119,7 +123,7 @@ SECTIONS
                 * first, the init task union, aligned
                 * to an 8192 byte boundary.
                 */
-               *(.init.task)
+               *(.data.init_task)
 
 #ifdef CONFIG_XIP_KERNEL
                . = ALIGN(4096);
index a950160fcfb69c171944f8ea0ef50c6e0c479e07..0446ef2f5bd665e3702e3b0448d2c8e73e282000 100644 (file)
@@ -142,7 +142,7 @@ aaec2000_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction aaec2000_timer_irq = {
        .name           = "AAEC-2000 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = aaec2000_timer_interrupt,
 };
 
index e238ad8cfd8fefbe7d78b3692eb1892140223ad8..018d637f87fcba913048a2896193ec98edf38cd3 100644 (file)
@@ -107,7 +107,7 @@ config ARCH_AT91SAM9260_SAM9XE
        depends on ARCH_AT91SAM9260
        help
          Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
-         They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+         They are basically AT91SAM9260s with various sizes of embedded Flash.
 
 comment "AT91SAM9260 / AT91SAM9XE Board Type"
 
index 949199a244c7bc680ceca9b952c0c55019e4a3a2..a6340357585da93efe24eb9a9b0e4aa1d21b9365 100644 (file)
@@ -87,7 +87,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction at91rm9200_timer_irq = {
        .name           = "at91_tick",
-       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91rm9200_timer_interrupt
 };
 
index a4dded27fa16a0dab13fa674293e7f2873b2a538..5c090c9442f5ee1ba43f6783a417a7ee0c194190 100644 (file)
@@ -66,7 +66,7 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction at91sam926x_timer_irq = {
        .name           = "at91_tick",
-       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91sam926x_timer_interrupt
 };
 
index 428493dd4687a73c6512ba1a3ec4ed2716e8407a..f428af7545b4472da7e4440e017366f037fc03b1 100644 (file)
@@ -58,7 +58,7 @@ p720t_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction clps711x_timer_irq = {
        .name           = "CLPS711x Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = p720t_timer_interrupt,
 };
 
index 231b90004736e131416877747da5d65fbf73e175..4dde34f25e63320e518797f1d8336d363d3e87a3 100644 (file)
@@ -316,7 +316,7 @@ clps7500_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction clps7500_timer_irq = {
        .name           = "CLPS7500 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = clps7500_timer_interrupt,
 };
 
index 8459431cfd71f4a9f38858bfbd147fe45eae28fa..8c1b5690dfe8c52b93662c8fe5fd98ca9c48ed8f 100644 (file)
@@ -199,7 +199,7 @@ ebsa110_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ebsa110_timer_irq = {
        .name           = "EBSA110 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ebsa110_timer_interrupt,
 };
 
index 829aed696d982420b094280e8ff6cd9b3a029c6b..851cc7158ca305bbaa1bc707979cd276a93807f7 100644 (file)
@@ -116,7 +116,7 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ep93xx_timer_irq = {
        .name           = "ep93xx timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ep93xx_timer_interrupt,
 };
 
index fa6be870c6c20cac3896bacfda7f52cbd93d6b85..3a63941d43beceea7a022c5c928ad3caa459afde 100644 (file)
@@ -44,7 +44,7 @@ timer1_interrupt(int irq, void *dev_id)
 static struct irqaction footbridge_timer_irq = {
        .name           = "Timer1 timer tick",
        .handler        = timer1_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 };
 
 /*
index d884a3954fb4c843290e3cb08375adf24eea680e..d08d64139d0051971a4bd57e88424518fa95d83d 100644 (file)
@@ -73,7 +73,7 @@ isa_timer_interrupt(int irq, void *dev_id)
 static struct irqaction isa_timer_irq = {
        .name           = "ISA timer tick",
        .handler        = isa_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 };
 
 static void __init isa_timer_init(void)
index 13f76bdb3d9d6ebacd029eb53d69dd8989de835a..9107b8e2ad6e77889955130462bdc3b237d206ea 100644 (file)
@@ -41,7 +41,7 @@ h7201_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction h7201_timer_irq = {
        .name           = "h7201 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = h7201_timer_interrupt,
 };
 
index 703870f30adf78cc01adb5515e0f7d06da30dce8..82e420d6fd197edfa86eecb959861b507887a3b0 100644 (file)
@@ -170,7 +170,7 @@ static struct irq_chip h7202_timerx_chip = {
 
 static struct irqaction h7202_timer_irq = {
        .name           = "h7202 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = h7202_timer_interrupt,
 };
 
index 2703a730baf77ff5cfd59a40faacc74e8e5cdd07..6960a9d042175d824d080c38cb8e35b21148ef69 100644 (file)
@@ -56,7 +56,7 @@ imx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction imx_timer_irq = {
        .name           = "i.MX Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = imx_timer_interrupt,
 };
 
index 8d880cb9ba39f4795166274d961f7763b87a7083..897c21c2fb5b442f1ef3823f109921688d0cd9b9 100644 (file)
@@ -282,7 +282,7 @@ integrator_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction integrator_timer_irq = {
        .name           = "Integrator Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = integrator_timer_interrupt,
 };
 
index 9cf2498dc99eaaf418082af8e206af2274860911..cb6ad211887a942dea628f469230adf352539a82 100644 (file)
@@ -224,7 +224,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ixp2000_timer_irq = {
        .name           = "IXP2000 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ixp2000_timer_interrupt,
 };
 
index ce6ad635a00c2e6991dd35eca189bce268fb16a5..b644bbab7d0ac2663f0d6e693436079665796572 100644 (file)
@@ -363,7 +363,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id)
 static struct irqaction ixp23xx_timer_irq = {
        .name           = "IXP23xx Timer Tick",
        .handler        = ixp23xx_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 };
 
 void __init ixp23xx_init_timer(void)
index f5cae1e46b7ef1cc9937b6fa727e8f14ec508a30..64685da1462d644c35dbc66434f07cdb105a9e23 100644 (file)
@@ -279,7 +279,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ixp4xx_timer_irq = {
        .name           = "timer1",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ixp4xx_timer_interrupt,
 };
 
index bef3c4b68d3bb3e028521f3c140fb91e4f80f1eb..c25316d02537ef0dc34563b6c4d1bfae1a1de134 100644 (file)
@@ -53,7 +53,7 @@ lh7a40x_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction lh7a40x_timer_irq = {
        .name           = "LHA740x Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = lh7a40x_timer_interrupt,
 };
 
index 7e132fcccd47810de97955d9c3dc4146893027d5..4762e207b0bff82c4819e1314b480449a3188cf3 100644 (file)
@@ -47,7 +47,7 @@ netx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction netx_timer_irq = {
        .name           = "NetX Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = netx_timer_interrupt,
 };
 
index eec05f18714a4a37754ff393e41c0265bea4c233..dd257084441ca8dc14c2a854bfd7c84daa253cc3 100644 (file)
@@ -53,7 +53,7 @@ static unsigned long ns9xxx_timer_gettimeoffset(void)
 
 static struct irqaction ns9xxx_timer_irq = {
        .name = "NS9xxx Timer Tick",
-       .flags = IRQF_DISABLED | IRQF_TIMER,
+       .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler = ns9xxx_timer_interrupt,
 };
 
index 8781aaeb576b2d2738ead294ba6c21a182030b58..856c681ebbbcf9c3e9e64060bd52a1e690316e51 100644 (file)
@@ -22,6 +22,7 @@ comment "OMAP Board Type"
 config MACH_OMAP_INNOVATOR
        bool "TI Innovator"
        depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
+       select OMAP_MCBSP
        help
           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
           have such a board.
@@ -29,6 +30,7 @@ config MACH_OMAP_INNOVATOR
 config MACH_OMAP_H2
        bool "TI H2 Support"
        depends on ARCH_OMAP1 && ARCH_OMAP16XX
+       select OMAP_MCBSP
        help
          TI OMAP 1610/1611B H2 board support. Say Y here if you have such
          a board.
@@ -36,6 +38,7 @@ config MACH_OMAP_H2
 config MACH_OMAP_H3
        bool "TI H3 Support"
        depends on ARCH_OMAP1 && ARCH_OMAP16XX
+       select GPIOEXPANDER_OMAP
        help
          TI OMAP 1710 H3 board support. Say Y here if you have such
          a board.
@@ -43,7 +46,7 @@ config MACH_OMAP_H3
 config MACH_OMAP_OSK
        bool "TI OSK Support"
        depends on ARCH_OMAP1 && ARCH_OMAP16XX
-       select TPS65010
+       select OMAP_MCBSP
        help
          TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
           if you have such a board.
@@ -84,7 +87,7 @@ config MACH_OMAP_PALMTE
           Support for the Palm Tungsten E PDA. Currently only the LCD panel
           is supported. To boot the kernel, you'll need a PalmOS compatible
           bootloader; check out http://palmtelinux.sourceforge.net for more
-          informations.
+          information.
           Say Y here if you have such a PDA, say NO otherwise.
 
 config MACH_NOKIA770
index 7165f74f78dac18f4c5c4f7fc08272ee683a8dd1..a8b9a00cea224d79393e71e68d77144b83522a43 100644 (file)
@@ -37,4 +37,3 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR)     += leds-innovator.o
 led-$(CONFIG_MACH_OMAP_PERSEUS2)       += leds-h2p2-debug.o
 led-$(CONFIG_MACH_OMAP_OSK)            += leds-osk.o
 obj-$(CONFIG_LEDS)                     += $(led-y)
-
index 62e42c7a628e55ac1f86616064667ea2e0188534..f65baa95986ea9717632690404dd77c47a1cc1c5 100644 (file)
@@ -246,7 +246,7 @@ static void __init fsample_init_smc91x(void)
        mdelay(50);
 }
 
-void omap_fsample_init_irq(void)
+static void __init omap_fsample_init_irq(void)
 {
        omap1_init_common_hw();
        omap_init_irq();
index 9d2346fb68f41da85c51dd0211a6e826121c0b33..7b260b7c537bb3040968b46e8284d87bf34ca129 100644 (file)
@@ -455,7 +455,7 @@ static void __init h3_init_smc91x(void)
        }
 }
 
-void h3_init_irq(void)
+static void __init h3_init_irq(void)
 {
        omap1_init_common_hw();
        omap_init_irq();
index cb00530ad279392725581ae81b57c07a215eb1e6..7e63a41e37c699838471a97ab52004f28bd1a71d 100644 (file)
@@ -308,7 +308,7 @@ static void __init innovator_init_smc91x(void)
        }
 }
 
-void innovator_init_irq(void)
+static void __init innovator_init_irq(void)
 {
        omap1_init_common_hw();
        omap_init_irq();
index fa4be962df67b454c09afc2ea956f11251904825..1d5c8d5097222ad1289b4edf8664febb66434b61 100644 (file)
@@ -246,7 +246,7 @@ static void __init perseus2_init_smc91x(void)
        mdelay(50);
 }
 
-void omap_perseus2_init_irq(void)
+static void __init omap_perseus2_init_irq(void)
 {
        omap1_init_common_hw();
        omap_init_irq();
index 6dcd10ab4496f765a7681731e85c1a8ee7c36f30..da8a3ac47e136c52dfc122641d866d207f1233b7 100644 (file)
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
 
-#if    defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
-
-static u64 irda_dmamask = 0xffffffff;
-
-static struct platform_device omap1610ir_device = {
-       .name = "omap1610-ir",
-       .id = -1,
-       .dev = {
-               .dma_mask       = &irda_dmamask,
-       },
-};
-
-static void omap_init_irda(void)
-{
-       /* FIXME define and use a boot tag, members something like:
-        *  u8          uart;           // uart1, or uart3
-        * ... but driver only handles uart3 for now
-        *  s16         fir_sel;        // gpio for SIR vs FIR
-        * ... may prefer a callback for SIR/MIR/FIR mode select;
-        * while h2 uses a GPIO, H3 uses a gpio expander
-        */
-       if (machine_is_omap_h2()
-                       || machine_is_omap_h3())
-               (void) platform_device_register(&omap1610ir_device);
-}
-#else
-static inline void omap_init_irda(void) {}
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -90,6 +61,45 @@ static void omap_init_rtc(void)
 static inline void omap_init_rtc(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+#  define OMAP1_MBOX_SIZE      0x23
+#  define INT_DSP_MAILBOX1     INT_1510_DSP_MAILBOX1
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#  define OMAP1_MBOX_SIZE      0x2f
+#  define INT_DSP_MAILBOX1     INT_1610_DSP_MAILBOX1
+#endif
+
+#define OMAP1_MBOX_BASE                IO_ADDRESS(OMAP16XX_MAILBOX_BASE)
+
+static struct resource mbox_resources[] = {
+       {
+               .start          = OMAP1_MBOX_BASE,
+               .end            = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = INT_DSP_MAILBOX1,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mbox_device = {
+       .name           = "mailbox",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(mbox_resources),
+       .resource       = mbox_resources,
+};
+
+static inline void omap_init_mbox(void)
+{
+       platform_device_register(&mbox_device);
+}
+#else
+static inline void omap_init_mbox(void) { }
+#endif
+
 #if defined(CONFIG_OMAP_STI)
 
 #define OMAP1_STI_BASE         IO_ADDRESS(0xfffea000)
@@ -154,7 +164,8 @@ static int __init omap1_init_devices(void)
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
-       omap_init_irda();
+
+       omap_init_mbox();
        omap_init_rtc();
        omap_init_sti();
 
index fab8b0b27cfbca4dd4c0a809dca6637369a0bcbc..81c4e738506c865430c27534755cde6780d01a19 100644 (file)
 #include <asm/io.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
-#include <asm/arch/omapfb.h>
 
 extern int omap1_clk_init(void);
 extern void omap_check_revision(void);
 extern void omap_sram_init(void);
+extern void omapfb_reserve_sdram(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -121,7 +121,7 @@ void __init omap1_map_common_io(void)
 #endif
 
        omap_sram_init();
-       omapfb_reserve_mem();
+       omapfb_reserve_sdram();
 }
 
 /*
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
new file mode 100644 (file)
index 0000000..d3abf56
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Mailbox reservation modules for DSP
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/resource.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/irqs.h>
+#include <asm/io.h>
+
+#define MAILBOX_ARM2DSP1               0x00
+#define MAILBOX_ARM2DSP1b              0x04
+#define MAILBOX_DSP2ARM1               0x08
+#define MAILBOX_DSP2ARM1b              0x0c
+#define MAILBOX_DSP2ARM2               0x10
+#define MAILBOX_DSP2ARM2b              0x14
+#define MAILBOX_ARM2DSP1_Flag          0x18
+#define MAILBOX_DSP2ARM1_Flag          0x1c
+#define MAILBOX_DSP2ARM2_Flag          0x20
+
+unsigned long mbox_base;
+
+struct omap_mbox1_fifo {
+       unsigned long cmd;
+       unsigned long data;
+       unsigned long flag;
+};
+
+struct omap_mbox1_priv {
+       struct omap_mbox1_fifo tx_fifo;
+       struct omap_mbox1_fifo rx_fifo;
+};
+
+static inline int mbox_read_reg(unsigned int reg)
+{
+       return __raw_readw(mbox_base + reg);
+}
+
+static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+{
+       __raw_writew(val, mbox_base + reg);
+}
+
+/* msg */
+static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
+{
+       struct omap_mbox1_fifo *fifo =
+               &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+       mbox_msg_t msg;
+
+       msg = mbox_read_reg(fifo->data);
+       msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
+
+       return msg;
+}
+
+static inline void
+omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+       struct omap_mbox1_fifo *fifo =
+               &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
+
+       mbox_write_reg(msg & 0xffff, fifo->data);
+       mbox_write_reg(msg >> 16, fifo->cmd);
+}
+
+static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
+{
+       return 0;
+}
+
+static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox)
+{
+       struct omap_mbox1_fifo *fifo =
+               &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+
+       return (mbox_read_reg(fifo->flag));
+}
+
+/* irq */
+static inline void
+omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+       if (irq == IRQ_RX)
+               enable_irq(mbox->irq);
+}
+
+static inline void
+omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+       if (irq == IRQ_RX)
+               disable_irq(mbox->irq);
+}
+
+static inline int
+omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+       if (irq == IRQ_TX)
+               return 0;
+       return 1;
+}
+
+static struct omap_mbox_ops omap1_mbox_ops = {
+       .type           = OMAP_MBOX_TYPE1,
+       .fifo_read      = omap1_mbox_fifo_read,
+       .fifo_write     = omap1_mbox_fifo_write,
+       .fifo_empty     = omap1_mbox_fifo_empty,
+       .fifo_full      = omap1_mbox_fifo_full,
+       .enable_irq     = omap1_mbox_enable_irq,
+       .disable_irq    = omap1_mbox_disable_irq,
+       .is_irq         = omap1_mbox_is_irq,
+};
+
+/* FIXME: the following struct should be created automatically by the user id */
+
+/* DSP */
+static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
+       .tx_fifo = {
+               .cmd    = MAILBOX_ARM2DSP1b,
+               .data   = MAILBOX_ARM2DSP1,
+               .flag   = MAILBOX_ARM2DSP1_Flag,
+       },
+       .rx_fifo = {
+               .cmd    = MAILBOX_DSP2ARM1b,
+               .data   = MAILBOX_DSP2ARM1,
+               .flag   = MAILBOX_DSP2ARM1_Flag,
+       },
+};
+
+struct omap_mbox mbox_dsp_info = {
+       .name   = "dsp",
+       .ops    = &omap1_mbox_ops,
+       .priv   = &omap1_mbox_dsp_priv,
+};
+EXPORT_SYMBOL(mbox_dsp_info);
+
+static int __init omap1_mbox_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int ret = 0;
+
+       if (pdev->num_resources != 2) {
+               dev_err(&pdev->dev, "invalid number of resources: %d\n",
+                       pdev->num_resources);
+               return -ENODEV;
+       }
+
+       /* MBOX base */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "invalid mem resource\n");
+               return -ENODEV;
+       }
+       mbox_base = res->start;
+
+       /* DSP IRQ */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "invalid irq resource\n");
+               return -ENODEV;
+       }
+       mbox_dsp_info.irq = res->start;
+
+       ret = omap_mbox_register(&mbox_dsp_info);
+
+       return ret;
+}
+
+static int omap1_mbox_remove(struct platform_device *pdev)
+{
+       omap_mbox_unregister(&mbox_dsp_info);
+
+       return 0;
+}
+
+static struct platform_driver omap1_mbox_driver = {
+       .probe  = omap1_mbox_probe,
+       .remove = omap1_mbox_remove,
+       .driver = {
+               .name   = "mailbox",
+       },
+};
+
+static int __init omap1_mbox_init(void)
+{
+       return platform_driver_register(&omap1_mbox_driver);
+}
+
+static void __exit omap1_mbox_exit(void)
+{
+       platform_driver_unregister(&omap1_mbox_driver);
+}
+
+module_init(omap1_mbox_init);
+module_exit(omap1_mbox_exit);
+
+MODULE_LICENSE("GPL");
index 85e048b259f57d92b6f2cb1fc9f77c6d95693ca6..3705d20c4e5c9b69a8c9c4d01dc2ee7b1c72e1c7 100644 (file)
@@ -179,7 +179,7 @@ static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
 
 static struct irqaction omap_mpu_timer1_irq = {
        .name           = "mpu_timer1",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = omap_mpu_timer1_interrupt,
 };
 
index aab97ccf1e63648889ddb515abd9c35ff85fd826..7393109f5c3027f4a9973294954d5bfb53d65f34 100644 (file)
@@ -9,6 +9,7 @@ config ARCH_OMAP2420
        bool "OMAP2420 support"
        depends on ARCH_OMAP24XX
        select OMAP_DM_TIMER
+       select ARCH_OMAP_OTG
 
 comment "OMAP Board Type"
        depends on ARCH_OMAP2
@@ -20,6 +21,7 @@ config MACH_OMAP_GENERIC
 config MACH_OMAP_H4
        bool "OMAP 2420 H4 board"
        depends on ARCH_OMAP2 && ARCH_OMAP24XX
+       select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG
 
 config MACH_OMAP_APOLLON
        bool "OMAP 2420 Apollon board"
index 1e7ed6d22ca98efc6614ff56071d91ac4679af6f..452193f0153182f5407ce36f99fba726cc4ca037 100644 (file)
@@ -266,12 +266,26 @@ static struct platform_device h4_lcd_device = {
        .id             = -1,
 };
 
+static struct resource h4_led_resources[] = {
+       [0] = {
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device h4_led_device = {
+       .name           = "omap_dbg_led",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(h4_led_resources),
+       .resource       = h4_led_resources,
+};
+
 static struct platform_device *h4_devices[] __initdata = {
        &h4_smc91x_device,
        &h4_flash_device,
        &h4_irda_device,
        &h4_kp_device,
        &h4_lcd_device,
+       &h4_led_device,
 };
 
 static inline void __init h4_init_smc91x(void)
index aa4322451e8b5dbe10cfd76cf58fff09b9384abf..52ec2f2d636022300709012b263f623b7dfc2ab5 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
 
-#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 
 #define OMAP2_I2C_BASE2                0x48072000
 #define OMAP2_I2C_INT2         57
@@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = {
 };
 
 static struct platform_device omap_i2c_device2 = {
-        .name           = "i2c_omap",
-        .id             = 2,
+       .name           = "i2c_omap",
+       .id             = 2,
        .num_resources  = ARRAY_SIZE(i2c_resources2),
        .resource       = i2c_resources2,
 };
@@ -66,6 +66,40 @@ static void omap_init_i2c(void) {}
 
 #endif
 
+#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+#define OMAP2_MBOX_BASE                IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
+
+static struct resource mbox_resources[] = {
+       {
+               .start          = OMAP2_MBOX_BASE,
+               .end            = OMAP2_MBOX_BASE + 0x11f,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = INT_24XX_MAIL_U0_MPU,
+               .flags          = IORESOURCE_IRQ,
+       },
+       {
+               .start          = INT_24XX_MAIL_U3_MPU,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mbox_device = {
+       .name           = "mailbox",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(mbox_resources),
+       .resource       = mbox_resources,
+};
+
+static inline void omap_init_mbox(void)
+{
+       platform_device_register(&mbox_device);
+}
+#else
+static inline void omap_init_mbox(void) { }
+#endif
+
 #if defined(CONFIG_OMAP_STI)
 
 #define OMAP2_STI_BASE         IO_ADDRESS(0x48068000)
@@ -111,29 +145,45 @@ static inline void omap_init_sti(void) {}
 #define OMAP2_MCSPI1_BASE              0x48098000
 #define OMAP2_MCSPI2_BASE              0x4809a000
 
-/* FIXME: use resources instead */
-
 static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
-       .base           = io_p2v(OMAP2_MCSPI1_BASE),
        .num_cs         = 4,
 };
 
+static struct resource omap2_mcspi1_resources[] = {
+       {
+               .start          = OMAP2_MCSPI1_BASE,
+               .end            = OMAP2_MCSPI1_BASE + 0xff,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
 struct platform_device omap2_mcspi1 = {
        .name           = "omap2_mcspi",
        .id             = 1,
+       .num_resources  = ARRAY_SIZE(omap2_mcspi1_resources),
+       .resource       = omap2_mcspi1_resources,
        .dev            = {
                .platform_data = &omap2_mcspi1_config,
        },
 };
 
 static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
-       .base           = io_p2v(OMAP2_MCSPI2_BASE),
        .num_cs         = 2,
 };
 
+static struct resource omap2_mcspi2_resources[] = {
+       {
+               .start          = OMAP2_MCSPI2_BASE,
+               .end            = OMAP2_MCSPI2_BASE + 0xff,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
 struct platform_device omap2_mcspi2 = {
        .name           = "omap2_mcspi",
        .id             = 2,
+       .num_resources  = ARRAY_SIZE(omap2_mcspi2_resources),
+       .resource       = omap2_mcspi2_resources,
        .dev            = {
                .platform_data = &omap2_mcspi2_config,
        },
@@ -157,10 +207,10 @@ static int __init omap2_init_devices(void)
         * in alphabetical order so they're easier to sort through.
         */
        omap_init_i2c();
+       omap_init_mbox();
        omap_init_mcspi();
        omap_init_sti();
 
        return 0;
 }
 arch_initcall(omap2_init_devices);
-
index d8f57824423f63708ca42a5b6a118c5470fb6406..54c836a984565daa81115a2d2ae2ab4a0b8ce3d4 100644 (file)
@@ -246,14 +246,22 @@ static int gpmc_cs_mem_enabled(int cs)
        return l & (1 << 6);
 }
 
-static void gpmc_cs_set_reserved(int cs, int reserved)
+int gpmc_cs_set_reserved(int cs, int reserved)
 {
+       if (cs > GPMC_CS_NUM)
+               return -ENODEV;
+
        gpmc_cs_map &= ~(1 << cs);
        gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+
+       return 0;
 }
 
-static int gpmc_cs_reserved(int cs)
+int gpmc_cs_reserved(int cs)
 {
+       if (cs > GPMC_CS_NUM)
+               return -ENODEV;
+
        return gpmc_cs_map & (1 << cs);
 }
 
index a0728c33e5d9e60de43b6f867b1efcfd61c1561f..82dc70f6b7795652829a01fa5a1c360ca1fc9cae 100644 (file)
@@ -27,6 +27,7 @@ extern void omap_sram_init(void);
 extern int omap2_clk_init(void);
 extern void omap2_check_revision(void);
 extern void gpmc_init(void);
+extern void omapfb_reserve_sdram(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -40,9 +41,21 @@ static struct map_desc omap2_io_desc[] __initdata = {
                .type           = MT_DEVICE
        },
        {
-               .virtual        = L4_24XX_VIRT,
-               .pfn            = __phys_to_pfn(L4_24XX_PHYS),
-               .length         = L4_24XX_SIZE,
+               .virtual        = DSP_MEM_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MEM_24XX_PHYS),
+               .length         = DSP_MEM_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_IPI_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_IPI_24XX_PHYS),
+               .length         = DSP_IPI_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_MMU_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MMU_24XX_PHYS),
+               .length         = DSP_MMU_24XX_SIZE,
                .type           = MT_DEVICE
        }
 };
@@ -60,7 +73,7 @@ void __init omap2_map_common_io(void)
 
        omap2_check_revision();
        omap_sram_init();
-       omapfb_reserve_mem();
+       omapfb_reserve_sdram();
 }
 
 void __init omap2_init_common_hw(void)
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
new file mode 100644 (file)
index 0000000..b03cd06
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Mailbox reservation modules for OMAP2
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *        and  Paul Mundt <paul.mundt@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/irqs.h>
+#include <asm/io.h>
+
+#define MAILBOX_REVISION               0x00
+#define MAILBOX_SYSCONFIG              0x10
+#define MAILBOX_SYSSTATUS              0x14
+#define MAILBOX_MESSAGE_0              0x40
+#define MAILBOX_MESSAGE_1              0x44
+#define MAILBOX_MESSAGE_2              0x48
+#define MAILBOX_MESSAGE_3              0x4c
+#define MAILBOX_MESSAGE_4              0x50
+#define MAILBOX_MESSAGE_5              0x54
+#define MAILBOX_FIFOSTATUS_0           0x80
+#define MAILBOX_FIFOSTATUS_1           0x84
+#define MAILBOX_FIFOSTATUS_2           0x88
+#define MAILBOX_FIFOSTATUS_3           0x8c
+#define MAILBOX_FIFOSTATUS_4           0x90
+#define MAILBOX_FIFOSTATUS_5           0x94
+#define MAILBOX_MSGSTATUS_0            0xc0
+#define MAILBOX_MSGSTATUS_1            0xc4
+#define MAILBOX_MSGSTATUS_2            0xc8
+#define MAILBOX_MSGSTATUS_3            0xcc
+#define MAILBOX_MSGSTATUS_4            0xd0
+#define MAILBOX_MSGSTATUS_5            0xd4
+#define MAILBOX_IRQSTATUS_0            0x100
+#define MAILBOX_IRQENABLE_0            0x104
+#define MAILBOX_IRQSTATUS_1            0x108
+#define MAILBOX_IRQENABLE_1            0x10c
+#define MAILBOX_IRQSTATUS_2            0x110
+#define MAILBOX_IRQENABLE_2            0x114
+#define MAILBOX_IRQSTATUS_3            0x118
+#define MAILBOX_IRQENABLE_3            0x11c
+
+static unsigned long mbox_base;
+
+#define MAILBOX_IRQ_NOTFULL(n)         (1 << (2 * (n) + 1))
+#define MAILBOX_IRQ_NEWMSG(n)          (1 << (2 * (n)))
+
+struct omap_mbox2_fifo {
+       unsigned long msg;
+       unsigned long fifo_stat;
+       unsigned long msg_stat;
+};
+
+struct omap_mbox2_priv {
+       struct omap_mbox2_fifo tx_fifo;
+       struct omap_mbox2_fifo rx_fifo;
+       unsigned long irqenable;
+       unsigned long irqstatus;
+       u32 newmsg_bit;
+       u32 notfull_bit;
+};
+
+static struct clk *mbox_ick_handle;
+
+static inline unsigned int mbox_read_reg(unsigned int reg)
+{
+       return __raw_readl(mbox_base + reg);
+}
+
+static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+{
+       __raw_writel(val, mbox_base + reg);
+}
+
+/* Mailbox H/W preparations */
+static inline int omap2_mbox_startup(struct omap_mbox *mbox)
+{
+       unsigned int l;
+
+       mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
+       if (IS_ERR(mbox_ick_handle)) {
+               printk("Could not get mailboxes_ick\n");
+               return -ENODEV;
+       }
+       clk_enable(mbox_ick_handle);
+
+       /* set smart-idle & autoidle */
+       l = mbox_read_reg(MAILBOX_SYSCONFIG);
+       l |= 0x00000011;
+       mbox_write_reg(l, MAILBOX_SYSCONFIG);
+
+       return 0;
+}
+
+static inline void omap2_mbox_shutdown(struct omap_mbox *mbox)
+{
+       clk_disable(mbox_ick_handle);
+       clk_put(mbox_ick_handle);
+}
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+       return (mbox_msg_t) mbox_read_reg(fifo->msg);
+}
+
+static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+       mbox_write_reg(msg, fifo->msg);
+}
+
+static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+       return (mbox_read_reg(fifo->msg_stat) == 0);
+}
+
+static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+       return (mbox_read_reg(fifo->fifo_stat));
+}
+
+/* Mailbox IRQ handle functions */
+static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox,
+               omap_mbox_type_t irq)
+{
+       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+       l = mbox_read_reg(p->irqenable);
+       l |= bit;
+       mbox_write_reg(l, p->irqenable);
+}
+
+static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox,
+               omap_mbox_type_t irq)
+{
+       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+       l = mbox_read_reg(p->irqenable);
+       l &= ~bit;
+       mbox_write_reg(l, p->irqenable);
+}
+
+static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox,
+               omap_mbox_type_t irq)
+{
+       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+       mbox_write_reg(bit, p->irqstatus);
+}
+
+static inline int omap2_mbox_is_irq(struct omap_mbox *mbox,
+               omap_mbox_type_t irq)
+{
+       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+       u32 enable = mbox_read_reg(p->irqenable);
+       u32 status = mbox_read_reg(p->irqstatus);
+
+       return (enable & status & bit);
+}
+
+static struct omap_mbox_ops omap2_mbox_ops = {
+       .type           = OMAP_MBOX_TYPE2,
+       .startup        = omap2_mbox_startup,
+       .shutdown       = omap2_mbox_shutdown,
+       .fifo_read      = omap2_mbox_fifo_read,
+       .fifo_write     = omap2_mbox_fifo_write,
+       .fifo_empty     = omap2_mbox_fifo_empty,
+       .fifo_full      = omap2_mbox_fifo_full,
+       .enable_irq     = omap2_mbox_enable_irq,
+       .disable_irq    = omap2_mbox_disable_irq,
+       .ack_irq        = omap2_mbox_ack_irq,
+       .is_irq         = omap2_mbox_is_irq,
+};
+
+/*
+ * MAILBOX 0: ARM -> DSP,
+ * MAILBOX 1: ARM <- DSP.
+ * MAILBOX 2: ARM -> IVA,
+ * MAILBOX 3: ARM <- IVA.
+ */
+
+/* FIXME: the following structs should be filled automatically by the user id */
+
+/* DSP */
+static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
+       .tx_fifo = {
+               .msg            = MAILBOX_MESSAGE_0,
+               .fifo_stat      = MAILBOX_FIFOSTATUS_0,
+       },
+       .rx_fifo = {
+               .msg            = MAILBOX_MESSAGE_1,
+               .msg_stat       = MAILBOX_MSGSTATUS_1,
+       },
+       .irqenable      = MAILBOX_IRQENABLE_0,
+       .irqstatus      = MAILBOX_IRQSTATUS_0,
+       .notfull_bit    = MAILBOX_IRQ_NOTFULL(0),
+       .newmsg_bit     = MAILBOX_IRQ_NEWMSG(1),
+};
+
+struct omap_mbox mbox_dsp_info = {
+       .name   = "dsp",
+       .ops    = &omap2_mbox_ops,
+       .priv   = &omap2_mbox_dsp_priv,
+};
+EXPORT_SYMBOL(mbox_dsp_info);
+
+/* IVA */
+static struct omap_mbox2_priv omap2_mbox_iva_priv = {
+       .tx_fifo = {
+               .msg            = MAILBOX_MESSAGE_2,
+               .fifo_stat      = MAILBOX_FIFOSTATUS_2,
+       },
+       .rx_fifo = {
+               .msg            = MAILBOX_MESSAGE_3,
+               .msg_stat       = MAILBOX_MSGSTATUS_3,
+       },
+       .irqenable      = MAILBOX_IRQENABLE_3,
+       .irqstatus      = MAILBOX_IRQSTATUS_3,
+       .notfull_bit    = MAILBOX_IRQ_NOTFULL(2),
+       .newmsg_bit     = MAILBOX_IRQ_NEWMSG(3),
+};
+
+static struct omap_mbox mbox_iva_info = {
+       .name   = "iva",
+       .ops    = &omap2_mbox_ops,
+       .priv   = &omap2_mbox_iva_priv,
+};
+
+static int __init omap2_mbox_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int ret = 0;
+
+       if (pdev->num_resources != 3) {
+               dev_err(&pdev->dev, "invalid number of resources: %d\n",
+                       pdev->num_resources);
+               return -ENODEV;
+       }
+
+       /* MBOX base */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "invalid mem resource\n");
+               return -ENODEV;
+       }
+       mbox_base = res->start;
+
+       /* DSP IRQ */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "invalid irq resource\n");
+               return -ENODEV;
+       }
+       mbox_dsp_info.irq = res->start;
+
+       ret = omap_mbox_register(&mbox_dsp_info);
+
+       /* IVA IRQ */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "invalid irq resource\n");
+               return -ENODEV;
+       }
+       mbox_iva_info.irq = res->start;
+
+       ret = omap_mbox_register(&mbox_iva_info);
+
+       return ret;
+}
+
+static int omap2_mbox_remove(struct platform_device *pdev)
+{
+       omap_mbox_unregister(&mbox_dsp_info);
+       return 0;
+}
+
+static struct platform_driver omap2_mbox_driver = {
+       .probe = omap2_mbox_probe,
+       .remove = omap2_mbox_remove,
+       .driver = {
+               .name = "mailbox",
+       },
+};
+
+static int __init omap2_mbox_init(void)
+{
+       return platform_driver_register(&omap2_mbox_driver);
+}
+
+static void __exit omap2_mbox_exit(void)
+{
+       platform_driver_unregister(&omap2_mbox_driver);
+}
+
+module_init(omap2_mbox_init);
+module_exit(omap2_mbox_exit);
+
+MODULE_LICENSE("GPL");
index 45d1aaa51b576d47a3610d6c04c1d8b90691cee3..62e801ef9ad9ef59ee91e920089b84dbefa8ba56 100644 (file)
@@ -52,7 +52,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction omap2_gp_timer_irq = {
        .name           = "gp timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = omap2_gp_timer_interrupt,
 };
 
index 8621c206ac846d5ca6e61b07eea3efab060108b0..67e05f005a6bcaa99a340c1969307052d15223db 100644 (file)
@@ -82,7 +82,7 @@ static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction pnx4008_timer_irq = {
        .name = "PNX4008 Tick Timer",
-       .flags = IRQF_DISABLED | IRQF_TIMER,
+       .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler = pnx4008_timer_interrupt
 };
 
index fc3b82a740a0b021f188d7801c3da29f93723b74..5248abe334d23f6966ea63f2c0a8462f69878261 100644 (file)
@@ -97,7 +97,7 @@ pxa_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction pxa_timer_irq = {
        .name           = "PXA Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = pxa_timer_interrupt,
 };
 
index 84d3fe76e94e1306916e66636094113e2609252c..c7f1b44da40d0849295d55d82f19e718778f5b0d 100644 (file)
@@ -549,7 +549,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction realview_timer_irq = {
        .name           = "RealView Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = realview_timer_interrupt,
 };
 
index 637aaba653901a23f640edfdfa7c2569c0a41c93..d1eeed2ad47c79f5ed1d94209233957001690f5f 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
+/* linux/arch/arm/mach-s3c2410/sleep.S
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
index b034ad69a3249e979fb61eb56f002d9113a8c3c7..b72fee0f2538ee6865a69389b7cb8eb253040c8b 100644 (file)
@@ -740,7 +740,7 @@ static void h3800_IRQ_demux(unsigned int irq, struct irq_desc *desc)
 static struct irqaction h3800_irq = {
        .name           = "h3800_asic",
        .handler        = h3800_IRQ_demux,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 };
 
 u32 kpio_int_shadow = 0;
index 29c89f9eb2ceed1e345fb193d6bf0a2bd0f6f9a9..416e277054c23958b286dfb674a24024b28a46b4 100644 (file)
@@ -111,7 +111,7 @@ sa1100_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction sa1100_timer_irq = {
        .name           = "SA11xx Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = sa1100_timer_interrupt,
 };
 
index 0e480fae8ec51e0c4ca07706373681ce8c90448e..a0545db2a34f5e0fedb1f98551751e303f34e7b8 100644 (file)
@@ -90,7 +90,7 @@ shark_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction shark_timer_irq = {
        .name           = "Shark Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = shark_timer_interrupt,
 };
 
index 1275aa7d2eb198249a6d4f61a74780dd82440118..a7dd09436cbcb6b484515e120101688adef64a49 100644 (file)
@@ -891,7 +891,7 @@ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction versatile_timer_irq = {
        .name           = "Versatile Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = versatile_timer_interrupt,
 };
 
index e684e9b38216dce35440d32025208f2041a41454..b81391a4e374a3ddc013bd677364ef40501d1aea 100644 (file)
@@ -366,6 +366,19 @@ config CPU_32v6K
          enabled will not boot on processors with do not support these
          instructions.
 
+# ARMv7
+config CPU_V7
+       bool "Support ARM V7 processor"
+       depends on ARCH_INTEGRATOR
+       select CPU_32v6K
+       select CPU_32v7
+       select CPU_ABRT_EV7
+       select CPU_CACHE_V7
+       select CPU_CACHE_VIPT
+       select CPU_CP15_MMU
+       select CPU_COPY_V6 if MMU
+       select CPU_TLB_V6 if MMU
+
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
 config CPU_32v3
@@ -391,6 +404,9 @@ config CPU_32v5
 config CPU_32v6
        bool
 
+config CPU_32v7
+       bool
+
 # The abort model
 config CPU_ABRT_NOMMU
        bool
@@ -413,6 +429,9 @@ config CPU_ABRT_EV5TJ
 config CPU_ABRT_EV6
        bool
 
+config CPU_ABRT_EV7
+       bool
+
 # The cache model
 config CPU_CACHE_V3
        bool
@@ -429,6 +448,9 @@ config CPU_CACHE_V4WB
 config CPU_CACHE_V6
        bool
 
+config CPU_CACHE_V7
+       bool
+
 config CPU_CACHE_VIVT
        bool
 
@@ -503,7 +525,7 @@ comment "Processor Features"
 
 config ARM_THUMB
        bool "Support Thumb user binaries"
-       depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
+       depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7
        default y
        help
          Say Y if you want to include kernel support for running user space
@@ -578,9 +600,15 @@ config CPU_CACHE_ROUND_ROBIN
          Say Y here to use the predictable round-robin cache replacement
          policy.  Unless you specifically require this or are unsure, say N.
 
+config CPU_L2CACHE_DISABLE
+       bool "Disable level 2 cache"
+       depends on CPU_V7
+       help
+         Say Y here to disable the level 2 cache.  If unsure, say N.
+
 config CPU_BPREDICT_DISABLE
        bool "Disable branch prediction"
-       depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3
+       depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7
        help
          Say Y here to disable branch prediction.  If unsure, say N.
 
index 2f8b95947774dc8d263ce753ba7cb64e2299d241..b5bd335ff14aad48f44331c0c17e5462f38d433d 100644 (file)
@@ -24,12 +24,14 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o
 obj-$(CONFIG_CPU_ABRT_EV5T)    += abort-ev5t.o
 obj-$(CONFIG_CPU_ABRT_EV5TJ)   += abort-ev5tj.o
 obj-$(CONFIG_CPU_ABRT_EV6)     += abort-ev6.o
+obj-$(CONFIG_CPU_ABRT_EV7)     += abort-ev7.o
 
 obj-$(CONFIG_CPU_CACHE_V3)     += cache-v3.o
 obj-$(CONFIG_CPU_CACHE_V4)     += cache-v4.o
 obj-$(CONFIG_CPU_CACHE_V4WT)   += cache-v4wt.o
 obj-$(CONFIG_CPU_CACHE_V4WB)   += cache-v4wb.o
 obj-$(CONFIG_CPU_CACHE_V6)     += cache-v6.o
+obj-$(CONFIG_CPU_CACHE_V7)     += cache-v7.o
 
 obj-$(CONFIG_CPU_COPY_V3)      += copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)    += copypage-v4wt.o
@@ -66,5 +68,6 @@ obj-$(CONFIG_CPU_SA1100)      += proc-sa1100.o
 obj-$(CONFIG_CPU_XSCALE)       += proc-xscale.o
 obj-$(CONFIG_CPU_XSC3)         += proc-xsc3.o
 obj-$(CONFIG_CPU_V6)           += proc-v6.o
+obj-$(CONFIG_CPU_V7)           += proc-v7.o
 
 obj-$(CONFIG_CACHE_L2X0)       += cache-l2x0.o
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
new file mode 100644 (file)
index 0000000..eb90bce
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: v7_early_abort
+ *
+ * Params  : r2 = address of aborted instruction
+ *         : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ *        : r1 = FSR, bit 11 = write
+ *        : r2-r8 = corrupted
+ *        : r9 = preserved
+ *        : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ */
+       .align  5
+ENTRY(v7_early_abort)
+       /*
+        * The effect of data aborts on on the exclusive access monitor are
+        * UNPREDICTABLE. Do a CLREX to clear the state
+        */
+       clrex
+
+       mrc     p15, 0, r1, c5, c0, 0           @ get FSR
+       mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+
+       /*
+        * V6 code adjusts the returned DFSR.
+        * New designs should not need to patch up faults.
+        */
+       mov     pc, lr
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
new file mode 100644 (file)
index 0000000..35ffc4d
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  linux/arch/arm/mm/cache-v7.S
+ *
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2005 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This is the "shell" of the ARMv7 processor support.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+#include "proc-macros.S"
+
+/*
+ *     v7_flush_dcache_all()
+ *
+ *     Flush the whole D-cache.
+ *
+ *     Corrupted registers: r0-r5, r7, r9-r11
+ *
+ *     - mm    - mm_struct describing address space
+ */
+ENTRY(v7_flush_dcache_all)
+       mrc     p15, 1, r0, c0, c0, 1           @ read clidr
+       ands    r3, r0, #0x7000000              @ extract loc from clidr
+       mov     r3, r3, lsr #23                 @ left align loc bit field
+       beq     finished                        @ if loc is 0, then no need to clean
+       mov     r10, #0                         @ start clean at cache level 0
+loop1:
+       add     r2, r10, r10, lsr #1            @ work out 3x current cache level
+       mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
+       and     r1, r1, #7                      @ mask of the bits for current cache only
+       cmp     r1, #2                          @ see what cache we have at this level
+       blt     skip                            @ skip if no cache, or just i-cache
+       mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
+       isb                                     @ isb to sych the new cssr&csidr
+       mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
+       and     r2, r1, #7                      @ extract the length of the cache lines
+       add     r2, r2, #4                      @ add 4 (line length offset)
+       ldr     r4, =0x3ff
+       ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
+       clz     r5, r4                          @ find bit position of way size increment
+       ldr     r7, =0x7fff
+       ands    r7, r7, r1, lsr #13             @ extract max number of the index size
+loop2:
+       mov     r9, r4                          @ create working copy of max way size
+loop3:
+       orr     r11, r10, r9, lsl r5            @ factor way and cache number into r11
+       orr     r11, r11, r7, lsl r2            @ factor index number into r11
+       mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
+       subs    r9, r9, #1                      @ decrement the way
+       bge     loop3
+       subs    r7, r7, #1                      @ decrement the index
+       bge     loop2
+skip:
+       add     r10, r10, #2                    @ increment cache number
+       cmp     r3, r10
+       bgt     loop1
+finished:
+       mov     r10, #0                         @ swith back to cache level 0
+       mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
+       isb
+       mov     pc, lr
+
+/*
+ *     v7_flush_cache_all()
+ *
+ *     Flush the entire cache system.
+ *  The data cache flush is now achieved using atomic clean / invalidates
+ *  working outwards from L1 cache. This is done using Set/Way based cache
+ *  maintainance instructions.
+ *  The instruction cache can still be invalidated back to the point of
+ *  unification in a single instruction.
+ *
+ */
+ENTRY(v7_flush_kern_cache_all)
+       stmfd   sp!, {r4-r5, r7, r9-r11, lr}
+       bl      v7_flush_dcache_all
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
+       ldmfd   sp!, {r4-r5, r7, r9-r11, lr}
+       mov     pc, lr
+
+/*
+ *     v7_flush_cache_all()
+ *
+ *     Flush all TLB entries in a particular address space
+ *
+ *     - mm    - mm_struct describing address space
+ */
+ENTRY(v7_flush_user_cache_all)
+       /*FALLTHROUGH*/
+
+/*
+ *     v7_flush_cache_range(start, end, flags)
+ *
+ *     Flush a range of TLB entries in the specified address space.
+ *
+ *     - start - start address (may not be aligned)
+ *     - end   - end address (exclusive, may not be aligned)
+ *     - flags - vm_area_struct flags describing address space
+ *
+ *     It is assumed that:
+ *     - we have a VIPT cache.
+ */
+ENTRY(v7_flush_user_cache_range)
+       mov     pc, lr
+
+/*
+ *     v7_coherent_kern_range(start,end)
+ *
+ *     Ensure that the I and D caches are coherent within specified
+ *     region.  This is typically used when code has been written to
+ *     a memory region, and will be executed.
+ *
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ *
+ *     It is assumed that:
+ *     - the Icache does not read data from the write buffer
+ */
+ENTRY(v7_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     v7_coherent_user_range(start,end)
+ *
+ *     Ensure that the I and D caches are coherent within specified
+ *     region.  This is typically used when code has been written to
+ *     a memory region, and will be executed.
+ *
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ *
+ *     It is assumed that:
+ *     - the Icache does not read data from the write buffer
+ */
+ENTRY(v7_coherent_user_range)
+       dcache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r0, r0, r3
+1:     mcr     p15, 0, r0, c7, c11, 1          @ clean D line to the point of unification
+       dsb
+       mcr     p15, 0, r0, c7, c5, 1           @ invalidate I line
+       add     r0, r0, r2
+       cmp     r0, r1
+       blo     1b
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
+       dsb
+       isb
+       mov     pc, lr
+
+/*
+ *     v7_flush_kern_dcache_page(kaddr)
+ *
+ *     Ensure that the data held in the page kaddr is written back
+ *     to the page in question.
+ *
+ *     - kaddr   - kernel address (guaranteed to be page aligned)
+ */
+ENTRY(v7_flush_kern_dcache_page)
+       dcache_line_size r2, r3
+       add     r1, r0, #PAGE_SZ
+1:
+       mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line / unified line
+       add     r0, r0, r2
+       cmp     r0, r1
+       blo     1b
+       dsb
+       mov     pc, lr
+
+/*
+ *     v7_dma_inv_range(start,end)
+ *
+ *     Invalidate the data cache within the specified region; we will
+ *     be performing a DMA operation in this region and we want to
+ *     purge old data in the cache.
+ *
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+ENTRY(v7_dma_inv_range)
+       dcache_line_size r2, r3
+       sub     r3, r2, #1
+       tst     r0, r3
+       bic     r0, r0, r3
+       mcrne   p15, 0, r0, c7, c14, 1          @ clean & invalidate D / U line
+
+       tst     r1, r3
+       bic     r1, r1, r3
+       mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D / U line
+1:
+       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line
+       add     r0, r0, r2
+       cmp     r0, r1
+       blo     1b
+       dsb
+       mov     pc, lr
+
+/*
+ *     v7_dma_clean_range(start,end)
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+ENTRY(v7_dma_clean_range)
+       dcache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r0, r0, r3
+1:
+       mcr     p15, 0, r0, c7, c10, 1          @ clean D / U line
+       add     r0, r0, r2
+       cmp     r0, r1
+       blo     1b
+       dsb
+       mov     pc, lr
+
+/*
+ *     v7_dma_flush_range(start,end)
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+ENTRY(v7_dma_flush_range)
+       dcache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r0, r0, r3
+1:
+       mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D / U line
+       add     r0, r0, r2
+       cmp     r0, r1
+       blo     1b
+       dsb
+       mov     pc, lr
+
+       __INITDATA
+
+       .type   v7_cache_fns, #object
+ENTRY(v7_cache_fns)
+       .long   v7_flush_kern_cache_all
+       .long   v7_flush_user_cache_all
+       .long   v7_flush_user_cache_range
+       .long   v7_coherent_kern_range
+       .long   v7_coherent_user_range
+       .long   v7_flush_kern_dcache_page
+       .long   v7_dma_inv_range
+       .long   v7_dma_clean_range
+       .long   v7_dma_flush_range
+       .size   v7_cache_fns, . - v7_cache_fns
index 9da43a0fdcdffc5ff09b4e8fd1bdf6d95ac0452b..fc84fcc743804d16241a99ee5cb1c86f650dd048 100644 (file)
@@ -14,7 +14,8 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-unsigned int cpu_last_asid = { 1 << ASID_BITS };
+static DEFINE_SPINLOCK(cpu_asid_lock);
+unsigned int cpu_last_asid = ASID_FIRST_VERSION;
 
 /*
  * We fork()ed a process, and we need a new context for the child
@@ -31,15 +32,16 @@ void __new_context(struct mm_struct *mm)
 {
        unsigned int asid;
 
+       spin_lock(&cpu_asid_lock);
        asid = ++cpu_last_asid;
        if (asid == 0)
-               asid = cpu_last_asid = 1 << ASID_BITS;
+               asid = cpu_last_asid = ASID_FIRST_VERSION;
 
        /*
         * If we've used up all our ASIDs, we need
         * to start a new version and flush the TLB.
         */
-       if ((asid & ~ASID_MASK) == 0) {
+       if (unlikely((asid & ~ASID_MASK) == 0)) {
                asid = ++cpu_last_asid;
                /* set the reserved ASID before flushing the TLB */
                asm("mcr        p15, 0, %0, c13, c0, 1  @ set reserved context ID\n"
@@ -47,7 +49,16 @@ void __new_context(struct mm_struct *mm)
                    : "r" (0));
                isb();
                flush_tlb_all();
+               if (icache_is_vivt_asid_tagged()) {
+                       asm("mcr        p15, 0, %0, c7, c5, 0   @ invalidate I-cache\n"
+                           "mcr        p15, 0, %0, c7, c5, 6   @ flush BTAC/BTB\n"
+                           :
+                           : "r" (0));
+                       dsb();
+               }
        }
+       spin_unlock(&cpu_asid_lock);
 
+       mm->cpu_vm_mask = cpumask_of_cpu(smp_processor_id());
        mm->context.id = asid;
 }
index 5d9ce7deb4a7bc6433f54aac7074e6749ee6c739..75d491448e45d86ee0c27ccab2915727221506d9 100644 (file)
@@ -453,7 +453,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        info.si_errno = 0;
        info.si_code  = inf->code;
        info.si_addr  = (void __user *)addr;
-       notify_die("", regs, &info, fsr, 0);
+       arm_notify_die("", regs, &info, fsr, 0);
 }
 
 asmlinkage void __exception
index 9e2c89eb2115bd644fc09d854d48ac7637fc3cad..b13150052a76bd6c5d6cc16b17a48d05978c16f8 100644 (file)
        .word   \ucset
 #endif
        .endm
+
+/*
+ * cache_line_size - get the cache line size from the CSIDR register
+ * (available on ARMv7+). It assumes that the CSSR register was configured
+ * to access the L1 data cache CSIDR.
+ */
+       .macro  dcache_line_size, reg, tmp
+       mrc     p15, 1, \tmp, c0, c0, 0         @ read CSIDR
+       and     \tmp, \tmp, #7                  @ cache line size encoding
+       mov     \reg, #16                       @ size offset
+       mov     \reg, \reg, lsl \tmp            @ actual cache line size
+       .endm
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
new file mode 100644 (file)
index 0000000..dd823dd
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ *  linux/arch/arm/mm/proc-v7.S
+ *
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This is the "shell" of the ARMv7 processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/elf.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+#define TTB_C          (1 << 0)
+#define TTB_S          (1 << 1)
+#define TTB_RGN_OC_WT  (2 << 3)
+#define TTB_RGN_OC_WB  (3 << 3)
+
+ENTRY(cpu_v7_proc_init)
+       mov     pc, lr
+
+ENTRY(cpu_v7_proc_fin)
+       mov     pc, lr
+
+/*
+ *     cpu_v7_reset(loc)
+ *
+ *     Perform a soft reset of the system.  Put the CPU into the
+ *     same state as it would be if it had been reset, and branch
+ *     to what would be the reset vector.
+ *
+ *     - loc   - location to jump to for soft reset
+ *
+ *     It is assumed that:
+ */
+       .align  5
+ENTRY(cpu_v7_reset)
+       mov     pc, r0
+
+/*
+ *     cpu_v7_do_idle()
+ *
+ *     Idle the processor (eg, wait for interrupt).
+ *
+ *     IRQs are already disabled.
+ */
+ENTRY(cpu_v7_do_idle)
+       .long   0xe320f003                      @ ARM V7 WFI instruction
+       mov     pc, lr
+
+ENTRY(cpu_v7_dcache_clean_area)
+#ifndef TLB_CAN_READ_FROM_L1_CACHE
+       dcache_line_size r2, r3
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+       add     r0, r0, r2
+       subs    r1, r1, r2
+       bhi     1b
+       dsb
+#endif
+       mov     pc, lr
+
+/*
+ *     cpu_v7_switch_mm(pgd_phys, tsk)
+ *
+ *     Set the translation table base pointer to be pgd_phys
+ *
+ *     - pgd_phys - physical address of new TTB
+ *
+ *     It is assumed that:
+ *     - we are not using split page tables
+ */
+ENTRY(cpu_v7_switch_mm)
+       mov     r2, #0
+       ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
+       orr     r0, r0, #TTB_RGN_OC_WB          @ mark PTWs outer cacheable, WB
+       mcr     p15, 0, r2, c13, c0, 1          @ set reserved context ID
+       isb
+1:     mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
+       isb
+       mcr     p15, 0, r1, c13, c0, 1          @ set context ID
+       isb
+       mov     pc, lr
+
+/*
+ *     cpu_v7_set_pte_ext(ptep, pte)
+ *
+ *     Set a level 2 translation table entry.
+ *
+ *     - ptep  - pointer to level 2 translation table entry
+ *               (hardware version is stored at -1024 bytes)
+ *     - pte   - PTE value to store
+ *     - ext   - value for extended PTE bits
+ *
+ *     Permissions:
+ *       YUWD  APX AP1 AP0     SVC     User
+ *       0xxx   0   0   0      no acc  no acc
+ *       100x   1   0   1      r/o     no acc
+ *       10x0   1   0   1      r/o     no acc
+ *       1011   0   0   1      r/w     no acc
+ *       110x   0   1   0      r/w     r/o
+ *       11x0   0   1   0      r/w     r/o
+ *       1111   0   1   1      r/w     r/w
+ */
+ENTRY(cpu_v7_set_pte_ext)
+       str     r1, [r0], #-2048                @ linux version
+
+       bic     r3, r1, #0x000003f0
+       bic     r3, r3, #0x00000003
+       orr     r3, r3, r2
+       orr     r3, r3, #PTE_EXT_AP0 | 2
+
+       tst     r1, #L_PTE_WRITE
+       tstne   r1, #L_PTE_DIRTY
+       orreq   r3, r3, #PTE_EXT_APX
+
+       tst     r1, #L_PTE_USER
+       orrne   r3, r3, #PTE_EXT_AP1
+       tstne   r3, #PTE_EXT_APX
+       bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+
+       tst     r1, #L_PTE_YOUNG
+       biceq   r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK
+
+       tst     r1, #L_PTE_EXEC
+       orreq   r3, r3, #PTE_EXT_XN
+
+       tst     r1, #L_PTE_PRESENT
+       moveq   r3, #0
+
+       str     r3, [r0]
+       mcr     p15, 0, r0, c7, c10, 1          @ flush_pte
+       mov     pc, lr
+
+cpu_v7_name:
+       .ascii  "ARMv7 Processor"
+       .align
+
+       .section ".text.init", #alloc, #execinstr
+
+/*
+ *     __v7_setup
+ *
+ *     Initialise TLB, Caches, and MMU state ready to switch the MMU
+ *     on.  Return in r0 the new CP15 C1 control register setting.
+ *
+ *     We automatically detect if we have a Harvard cache, and use the
+ *     Harvard cache control instructions insead of the unified cache
+ *     control instructions.
+ *
+ *     This should be able to cover all ARMv7 cores.
+ *
+ *     It is assumed that:
+ *     - cache type register is implemented
+ */
+__v7_setup:
+       adr     r12, __v7_setup_stack           @ the local stack
+       stmia   r12, {r0-r5, r7, r9, r11, lr}
+       bl      v7_flush_dcache_all
+       ldmia   r12, {r0-r5, r7, r9, r11, lr}
+       mov     r10, #0
+#ifdef HARVARD_CACHE
+       mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
+#endif
+       dsb
+       mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
+       mcr     p15, 0, r10, c2, c0, 2          @ TTB control register
+       orr     r4, r4, #TTB_RGN_OC_WB          @ mark PTWs outer cacheable, WB
+       mcr     p15, 0, r4, c2, c0, 0           @ load TTB0
+       mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
+       mov     r10, #0x1f                      @ domains 0, 1 = manager
+       mcr     p15, 0, r10, c3, c0, 0          @ load domain access register
+#ifndef CONFIG_CPU_L2CACHE_DISABLE
+       @ L2 cache configuration in the L2 aux control register
+       mrc     p15, 1, r10, c9, c0, 2
+       bic     r10, r10, #(1 << 16)            @ L2 outer cache
+       mcr     p15, 1, r10, c9, c0, 2
+       @ L2 cache is enabled in the aux control register
+       mrc     p15, 0, r10, c1, c0, 1
+       orr     r10, r10, #2
+       mcr     p15, 0, r10, c1, c0, 1
+#endif
+       mrc     p15, 0, r0, c1, c0, 0           @ read control register
+       ldr     r10, cr1_clear                  @ get mask for bits to clear
+       bic     r0, r0, r10                     @ clear bits them
+       ldr     r10, cr1_set                    @ get mask for bits to set
+       orr     r0, r0, r10                     @ set them
+       mov     pc, lr                          @ return to head.S:__ret
+
+       /*
+        *         V X F   I D LR
+        * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
+        * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
+        *         0 110       0011 1.00 .111 1101 < we want
+        */
+       .type   cr1_clear, #object
+       .type   cr1_set, #object
+cr1_clear:
+       .word   0x0120c302
+cr1_set:
+       .word   0x00c0387d
+
+__v7_setup_stack:
+       .space  4 * 11                          @ 11 registers
+
+       .type   v7_processor_functions, #object
+ENTRY(v7_processor_functions)
+       .word   v7_early_abort
+       .word   cpu_v7_proc_init
+       .word   cpu_v7_proc_fin
+       .word   cpu_v7_reset
+       .word   cpu_v7_do_idle
+       .word   cpu_v7_dcache_clean_area
+       .word   cpu_v7_switch_mm
+       .word   cpu_v7_set_pte_ext
+       .size   v7_processor_functions, . - v7_processor_functions
+
+       .type   cpu_arch_name, #object
+cpu_arch_name:
+       .asciz  "armv7"
+       .size   cpu_arch_name, . - cpu_arch_name
+
+       .type   cpu_elf_name, #object
+cpu_elf_name:
+       .asciz  "v7"
+       .size   cpu_elf_name, . - cpu_elf_name
+       .align
+
+       .section ".proc.info.init", #alloc, #execinstr
+
+       /*
+        * Match any ARMv7 processor core.
+        */
+       .type   __v7_proc_info, #object
+__v7_proc_info:
+       .long   0x000f0000              @ Required ID value
+       .long   0x000f0000              @ Mask for ID
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_BUFFERABLE | \
+               PMD_SECT_CACHEABLE | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_XN | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __v7_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_v7_name
+       .long   v7_processor_functions
+       .long   v6wbi_tlb_fns
+       .long   v6_user_fns
+       .long   v7_cache_fns
+       .size   __v7_proc_info, . - __v7_proc_info
index 0cc26da034a12458e515429f8ce75d71eba4bca5..100d57ad98ed82636c87282501e4adaaa73f70b1 100644 (file)
@@ -75,7 +75,7 @@ iop_timer_interrupt(int irq, void *dev_id)
 static struct irqaction iop_timer_irq = {
        .name           = "IOP Timer Tick",
        .handler        = iop_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 };
 
 void __init iop_init_time(unsigned long tick_rate)
index 9e8d21eca4ecbf676d23d0b4d600682c969d41f2..cfc69f3842fda4eb97cb3a1edcfddfc154b9bbee 100644 (file)
@@ -20,6 +20,11 @@ endchoice
 
 comment "OMAP Feature Selections"
 
+config OMAP_DEBUG_LEDS
+       bool
+       help
+         For debug card leds on TI reference boards.
+
 config OMAP_RESET_CLOCKS
        bool "Reset unused clocks during boot"
        depends on ARCH_OMAP
@@ -58,6 +63,14 @@ config OMAP_MUX_WARNINGS
          to change the pin multiplexing setup.  When there are no warnings
          printed, it's safe to deselect OMAP_MUX for your product.
 
+config OMAP_MCBSP
+       bool "McBSP support"
+       depends on ARCH_OMAP
+       default y
+       help
+         Say Y here if you want support for the OMAP Multichannel
+         Buffered Serial Port.
+
 choice
         prompt "System timer"
        default OMAP_MPU_TIMER
index 2896b4546411c3237bc7374435958276916f4a36..41a3c1cf3bd44bd23b66836dbc79b0fd39abfb0f 100644 (file)
@@ -3,7 +3,8 @@
 #
 
 # Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \
+        usb.o fb.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -16,4 +17,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
-
+obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
index f1179ad4be1bb0f63e3d95059c8e3188b5bcc1e4..0a603242f36712e1060542f6c14c97efd3100a76 100644 (file)
@@ -33,6 +33,41 @@ static DEFINE_SPINLOCK(clockfw_lock);
 
 static struct clk_functions *arch_clock;
 
+#ifdef CONFIG_PM_DEBUG
+
+static void print_parents(struct clk *clk)
+{
+       struct clk *p;
+       int printed = 0;
+
+       list_for_each_entry(p, &clocks, node) {
+               if (p->parent == clk && p->usecount) {
+                       if (!clk->usecount && !printed) {
+                               printk("MISMATCH: %s\n", clk->name);
+                               printed = 1;
+                       }
+                       printk("\t%-15s\n", p->name);
+               }
+       }
+}
+
+void clk_print_usecounts(void)
+{
+       unsigned long flags;
+       struct clk *p;
+
+       spin_lock_irqsave(&clockfw_lock, flags);
+       list_for_each_entry(p, &clocks, node) {
+               if (p->usecount)
+                       printk("%-15s: %d\n", p->name, p->usecount);
+               print_parents(p);
+
+       }
+       spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+
+#endif
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -249,6 +284,8 @@ void followparent_recalc(struct clk *clk)
                return;
 
        clk->rate = clk->parent->rate;
+       if (unlikely(clk->flags & RATE_PROPAGATES))
+               propagate_rate(clk);
 }
 
 /* Propagate rate to children */
index fecd3d6259950def5af1ad18fcff6bf16fcd5710..dd8708ad0a71833339c5e3abc23cf4711604275c 100644 (file)
@@ -93,8 +93,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
         * in the kernel. */
        for (i = 0; i < omap_board_config_size; i++) {
                if (omap_board_config[i].tag == tag) {
-                       kinfo = &omap_board_config[i];
-                       break;
+                       if (skip == 0) {
+                               kinfo = &omap_board_config[i];
+                               break;
+                       } else {
+                               skip--;
+                       }
                }
        }
        if (kinfo == NULL)
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
new file mode 100644 (file)
index 0000000..9128a80
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * linux/arch/arm/plat-omap/debug-leds.c
+ *
+ * Copyright 2003 by Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/gpio.h>
+
+
+/* Many OMAP development platforms reuse the same "debug board"; these
+ * platforms include H2, H3, H4, and Perseus2.  There are 16 LEDs on the
+ * debug board (all green), accessed through FPGA registers.
+ *
+ * The "surfer" expansion board and H2 sample board also have two-color
+ * green+red LEDs (in parallel), used here for timer and idle indicators
+ * in preference to the ones on the debug board, for a "Disco LED" effect.
+ *
+ * This driver exports either the original ARM LED API, the new generic
+ * one, or both.
+ */
+
+static spinlock_t                      lock;
+static struct h2p2_dbg_fpga __iomem    *fpga;
+static u16                             led_state, hw_led_state;
+
+
+#ifdef CONFIG_LEDS_OMAP_DEBUG
+#define new_led_api()  1
+#else
+#define new_led_api()  0
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/* original ARM debug LED API:
+ *  - timer and idle leds (some boards use non-FPGA leds here);
+ *  - up to 4 generic leds, easily accessed in-kernel (any context)
+ */
+
+#define GPIO_LED_RED           3
+#define GPIO_LED_GREEN         OMAP_MPUIO(4)
+
+#define LED_STATE_ENABLED      0x01
+#define LED_STATE_CLAIMED      0x02
+#define LED_TIMER_ON           0x04
+
+#define GPIO_IDLE              GPIO_LED_GREEN
+#define GPIO_TIMER             GPIO_LED_RED
+
+static void h2p2_dbg_leds_event(led_event_t evt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&lock, flags);
+
+       if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+               goto done;
+
+       switch (evt) {
+       case led_start:
+               if (fpga)
+                       led_state |= LED_STATE_ENABLED;
+               break;
+
+       case led_stop:
+       case led_halted:
+               /* all leds off during suspend or shutdown */
+
+               if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) {
+                       omap_set_gpio_dataout(GPIO_TIMER, 0);
+                       omap_set_gpio_dataout(GPIO_IDLE, 0);
+               }
+
+               __raw_writew(~0, &fpga->leds);
+               led_state &= ~LED_STATE_ENABLED;
+               goto done;
+
+       case led_claim:
+               led_state |= LED_STATE_CLAIMED;
+               hw_led_state = 0;
+               break;
+
+       case led_release:
+               led_state &= ~LED_STATE_CLAIMED;
+               break;
+
+#ifdef CONFIG_LEDS_TIMER
+       case led_timer:
+               led_state ^= LED_TIMER_ON;
+
+               if (machine_is_omap_perseus2() || machine_is_omap_h4())
+                       hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
+               else {
+                       omap_set_gpio_dataout(GPIO_TIMER,
+                                       led_state & LED_TIMER_ON);
+                       goto done;
+               }
+
+               break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+       /* LED lit iff busy */
+       case led_idle_start:
+               if (machine_is_omap_perseus2() || machine_is_omap_h4())
+                       hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
+               else {
+                       omap_set_gpio_dataout(GPIO_IDLE, 1);
+                       goto done;
+               }
+
+               break;
+
+       case led_idle_end:
+               if (machine_is_omap_perseus2() || machine_is_omap_h4())
+                       hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
+               else {
+                       omap_set_gpio_dataout(GPIO_IDLE, 0);
+                       goto done;
+               }
+
+               break;
+#endif
+
+       case led_green_on:
+               hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
+               break;
+       case led_green_off:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
+               break;
+
+       case led_amber_on:
+               hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
+               break;
+       case led_amber_off:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
+               break;
+
+       case led_red_on:
+               hw_led_state |= H2P2_DBG_FPGA_LED_RED;
+               break;
+       case led_red_off:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
+               break;
+
+       case led_blue_on:
+               hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
+               break;
+       case led_blue_off:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
+               break;
+
+       default:
+               break;
+       }
+
+
+       /*
+        *  Actually burn the LEDs
+        */
+       if (led_state & LED_STATE_ENABLED)
+               __raw_writew(~hw_led_state, &fpga->leds);
+
+done:
+       spin_unlock_irqrestore(&lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* "new" LED API
+ *  - with syfs access and generic triggering
+ *  - not readily accessible to in-kernel drivers
+ */
+
+struct dbg_led {
+       struct led_classdev     cdev;
+       u16                     mask;
+};
+
+static struct dbg_led dbg_leds[] = {
+       /* REVISIT at least H2 uses different timer & cpu leds... */
+#ifndef CONFIG_LEDS_TIMER
+       { .mask = 1 << 0,  .cdev.name =  "d4:green",
+               .cdev.default_trigger = "heartbeat", },
+#endif
+#ifndef CONFIG_LEDS_CPU
+       { .mask = 1 << 1,  .cdev.name =  "d5:green", },         /* !idle */
+#endif
+       { .mask = 1 << 2,  .cdev.name =  "d6:green", },
+       { .mask = 1 << 3,  .cdev.name =  "d7:green", },
+
+       { .mask = 1 << 4,  .cdev.name =  "d8:green", },
+       { .mask = 1 << 5,  .cdev.name =  "d9:green", },
+       { .mask = 1 << 6,  .cdev.name = "d10:green", },
+       { .mask = 1 << 7,  .cdev.name = "d11:green", },
+
+       { .mask = 1 << 8,  .cdev.name = "d12:green", },
+       { .mask = 1 << 9,  .cdev.name = "d13:green", },
+       { .mask = 1 << 10, .cdev.name = "d14:green", },
+       { .mask = 1 << 11, .cdev.name = "d15:green", },
+
+#ifndef        CONFIG_LEDS
+       { .mask = 1 << 12, .cdev.name = "d16:green", },
+       { .mask = 1 << 13, .cdev.name = "d17:green", },
+       { .mask = 1 << 14, .cdev.name = "d18:green", },
+       { .mask = 1 << 15, .cdev.name = "d19:green", },
+#endif
+};
+
+static void
+fpga_led_set(struct led_classdev *cdev, enum led_brightness value)
+{
+       struct dbg_led  *led = container_of(cdev, struct dbg_led, cdev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&lock, flags);
+       if (value == LED_OFF)
+               hw_led_state &= ~led->mask;
+       else
+               hw_led_state |= led->mask;
+       __raw_writew(~hw_led_state, &fpga->leds);
+       spin_unlock_irqrestore(&lock, flags);
+}
+
+static void __init newled_init(struct device *dev)
+{
+       unsigned        i;
+       struct dbg_led  *led;
+       int             status;
+
+       for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) {
+               led->cdev.brightness_set = fpga_led_set;
+               status = led_classdev_register(dev, &led->cdev);
+               if (status < 0)
+                       break;
+       }
+       return;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int /* __init */ fpga_probe(struct platform_device *pdev)
+{
+       struct resource *iomem;
+
+       spin_lock_init(&lock);
+
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iomem)
+               return -ENODEV;
+
+       fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE);
+       __raw_writew(~0, &fpga->leds);
+
+#ifdef CONFIG_LEDS
+       leds_event = h2p2_dbg_leds_event;
+       leds_event(led_start);
+#endif
+
+       if (new_led_api()) {
+               newled_init(&pdev->dev);
+       }
+
+       return 0;
+}
+
+static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+       __raw_writew(~0, &fpga->leds);
+       return 0;
+}
+
+static int fpga_resume_early(struct platform_device *pdev)
+{
+       __raw_writew(~hw_led_state, &fpga->leds);
+       return 0;
+}
+
+
+static struct platform_driver led_driver = {
+       .driver.name    = "omap_dbg_led",
+       .probe          = fpga_probe,
+       .suspend_late   = fpga_suspend_late,
+       .resume_early   = fpga_resume_early,
+};
+
+static int __init fpga_init(void)
+{
+       if (machine_is_omap_h4()
+                       || machine_is_omap_h3()
+                       || machine_is_omap_h2()
+                       || machine_is_omap_perseus2()
+                       )
+               return platform_driver_register(&led_driver);
+       return 0;
+}
+fs_initcall(fpga_init);
index eeb33fed6f7c1928bf20e098c7deb94897a8f862..c5dab1d6417e113aeae93658b45a5d5730cdebb1 100644 (file)
 #include <asm/arch/gpio.h>
 #include <asm/arch/menelaus.h>
 
-#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+#if    defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+
+#include "../plat-omap/dsp/dsp_common.h"
+
+static struct dsp_platform_data dsp_pdata = {
+       .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list),
+};
+
+static struct resource omap_dsp_resources[] = {
+       {
+               .name   = "dsp_mmu",
+               .start  = -1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device omap_dsp_device = {
+       .name           = "dsp",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(omap_dsp_resources),
+       .resource       = omap_dsp_resources,
+       .dev = {
+               .platform_data = &dsp_pdata,
+       },
+};
+
+static inline void omap_init_dsp(void)
+{
+       struct resource *res;
+       int irq;
+
+       if (cpu_is_omap15xx())
+               irq = INT_1510_DSP_MMU;
+       else if (cpu_is_omap16xx())
+               irq = INT_1610_DSP_MMU;
+       else if (cpu_is_omap24xx())
+               irq = INT_24XX_DSP_MMU;
+
+       res = platform_get_resource_byname(&omap_dsp_device,
+                                          IORESOURCE_IRQ, "dsp_mmu");
+       res->start = irq;
+
+       platform_device_register(&omap_dsp_device);
+}
+
+int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev)
+{
+       static DEFINE_MUTEX(dsp_pdata_lock);
+
+       mutex_init(&kdev->lock);
+
+       mutex_lock(&dsp_pdata_lock);
+       list_add_tail(&kdev->entry, &dsp_pdata.kdev_list);
+       mutex_unlock(&dsp_pdata_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(dsp_kfunc_device_register);
+
+#else
+static inline void omap_init_dsp(void) { }
+#endif /* CONFIG_OMAP_DSP */
+
+/*-------------------------------------------------------------------------*/
+#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 
 #define        OMAP1_I2C_BASE          0xfffb3800
 #define OMAP2_I2C_BASE1                0x48070000
@@ -48,8 +112,8 @@ static struct resource i2c_resources1[] = {
 /* DMA not used; works around erratum writing to non-empty i2c fifo */
 
 static struct platform_device omap_i2c_device1 = {
-        .name           = "i2c_omap",
-        .id             = 1,
+       .name           = "i2c_omap",
+       .id             = 1,
        .num_resources  = ARRAY_SIZE(i2c_resources1),
        .resource       = i2c_resources1,
 };
@@ -376,7 +440,7 @@ static inline void omap_init_wdt(void) {}
 
 /*-------------------------------------------------------------------------*/
 
-#if    defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE)
+#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE)
 
 #ifdef CONFIG_ARCH_OMAP24XX
 #define        OMAP_RNG_BASE           0x480A0000
@@ -436,6 +500,7 @@ static int __init omap_init_devices(void)
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
+       omap_init_dsp();
        omap_init_i2c();
        omap_init_kp();
        omap_init_mmc();
@@ -446,4 +511,3 @@ static int __init omap_init_devices(void)
        return 0;
 }
 arch_initcall(omap_init_devices);
-
index f3f84fbf8b875da63e8cf10bf178745a2eff2a7d..2d86b106ff3e06b0dbc9ffe3a8e84b0945fb96b0 100644 (file)
@@ -925,10 +925,17 @@ static int omap2_dma_handle_ch(int ch)
 {
        u32 status = OMAP_DMA_CSR_REG(ch);
 
-       if (!status)
+       if (!status) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch);
                return 0;
-       if (unlikely(dma_chan[ch].dev_id == -1))
+       }
+       if (unlikely(dma_chan[ch].dev_id == -1)) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
+                                       "channel %d\n", status, ch);
                return 0;
+       }
        if (unlikely(status & OMAP_DMA_DROP_IRQ))
                printk(KERN_INFO
                       "DMA synchronization event drop occurred with device "
@@ -959,11 +966,15 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
        int i;
 
        val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
-
-       for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) {
-               int active = val & (1 << (i - 1));
-               if (active)
-                       omap2_dma_handle_ch(i - 1);
+       if (val == 0) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "Spurious DMA IRQ\n");
+               return IRQ_HANDLED;
+       }
+       for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) {
+               if (val & 1)
+                       omap2_dma_handle_ch(i);
+               val >>= 1;
        }
 
        return IRQ_HANDLED;
index 659619f235ca325234c1bdea44cd3c05926fc17a..36073dfaa4db57810c96f1674c39f5889c13fc93 100644 (file)
@@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 
        /* When the functional clock disappears, too quick writes seem to
         * cause an abort. */
-       __delay(15000);
+       __delay(150000);
 }
 
 #endif
index 56acb8720f789ad7047daef09ba4ec6717e70d5b..4493bcff51729a2e4340d0d196ce67e10a1611ca 100644 (file)
@@ -1,3 +1,26 @@
+/*
+ * File: arch/arm/plat-omap/fb.c
+ *
+ * Framebuffer device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -16,6 +39,8 @@
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static struct omapfb_platform_data omapfb_config;
+static int config_invalid;
+static int configured_regions;
 
 static u64 omap_fb_dma_mask = ~(u32)0;
 
@@ -30,39 +55,270 @@ static struct platform_device omap_fb_device = {
        .num_resources = 0,
 };
 
-/* called from map_io */
-void omapfb_reserve_mem(void)
+static inline int ranges_overlap(unsigned long start1, unsigned long size1,
+                                unsigned long start2, unsigned long size2)
 {
-       const struct omap_fbmem_config *fbmem_conf;
+       return (start1 >= start2 && start1 < start2 + size2) ||
+              (start2 >= start1 && start2 < start1 + size1);
+}
 
-       omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
-       omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+static inline int range_included(unsigned long start1, unsigned long size1,
+                                unsigned long start2, unsigned long size2)
+{
+       return start1 >= start2 && start1 + size1 <= start2 + size2;
+}
 
-       fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
 
-       if (fbmem_conf != NULL) {
-               /* indicate that the bootloader already initialized the
-                * fb device, so we'll skip that part in the fb driver
-                */
-               omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
-               omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
-               if (fbmem_conf->fb_sdram_size) {
-                       pr_info("Reserving %u bytes SDRAM for frame buffer\n",
-                               fbmem_conf->fb_sdram_size);
-                       reserve_bootmem(fbmem_conf->fb_sdram_start,
-                                       fbmem_conf->fb_sdram_size);
+/* Check if there is an overlapping region. */
+static int fbmem_region_reserved(unsigned long start, size_t size)
+{
+       struct omapfb_mem_region *rg;
+       int i;
+
+       rg = &omapfb_config.mem_desc.region[0];
+       for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) {
+               if (!rg->paddr)
+                       /* Empty slot. */
+                       continue;
+               if (ranges_overlap(start, size, rg->paddr, rg->size))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Get the region_idx`th region from board config/ATAG and convert it to
+ * our internal format.
+ */
+static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
+{
+       const struct omap_fbmem_config  *conf;
+       u32                             paddr;
+
+       conf = omap_get_nr_config(OMAP_TAG_FBMEM,
+                                 struct omap_fbmem_config, region_idx);
+       if (conf == NULL)
+               return -ENOENT;
+
+       paddr = conf->start;
+       /*
+        * Low bits encode the page allocation mode, if high bits
+        * are zero. Otherwise we need a page aligned fixed
+        * address.
+        */
+       memset(rg, 0, sizeof(*rg));
+       rg->type = paddr & ~PAGE_MASK;
+       rg->paddr = paddr & PAGE_MASK;
+       rg->size = PAGE_ALIGN(conf->size);
+       return 0;
+}
+
+static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type,
+                                 unsigned long mem_start,
+                                 unsigned long mem_size)
+{
+       /*
+        * Check if the configuration specifies the type explicitly.
+        * type = 0 && paddr = 0, a default don't care case maps to
+        * the SDRAM type.
+        */
+       if (rg->type || (!rg->type && !rg->paddr))
+               return 0;
+       if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) {
+               rg->type = mem_type;
+               return 0;
+       }
+       /* Can't determine it. */
+       return -1;
+}
+
+static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
+                             unsigned long start_avail, unsigned size_avail)
+{
+       unsigned long   paddr = rg->paddr;
+       size_t          size = rg->size;
+
+       if (rg->type > OMAPFB_MEMTYPE_MAX) {
+               printk(KERN_ERR
+                       "Invalid start address for FB region %d\n", region_idx);
+               return -EINVAL;
+       }
+
+       if (!rg->size) {
+               printk(KERN_ERR "Zero size for FB region %d\n", region_idx);
+               return -EINVAL;
+       }
+
+       if (!paddr)
+               /* Allocate this dynamically, leave paddr 0 for now. */
+               return 0;
+
+       /*
+        * Fixed region for the given RAM range. Check if it's already
+        * reserved by the FB code or someone else.
+        */
+       if (fbmem_region_reserved(paddr, size) ||
+           !range_included(paddr, size, start_avail, size_avail)) {
+               printk(KERN_ERR "Trying to use reserved memory "
+                       "for FB region %d\n", region_idx);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Called from map_io. We need to call to this early enough so that we
+ * can reserve the fixed SDRAM regions before VM could get hold of them.
+ */
+void omapfb_reserve_sdram(void)
+{
+       struct bootmem_data     *bdata;
+       unsigned long           sdram_start, sdram_size;
+       unsigned long           reserved;
+       int                     i;
+
+       if (config_invalid)
+               return;
+
+       bdata = NODE_DATA(0)->bdata;
+       sdram_start = bdata->node_boot_start;
+       sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
+       reserved = 0;
+       for (i = 0; ; i++) {
+               struct omapfb_mem_region        rg;
+
+               if (get_fbmem_region(i, &rg) < 0)
+                       break;
+               if (i == OMAPFB_PLANE_NUM) {
+                       printk(KERN_ERR
+                               "Extraneous FB mem configuration entries\n");
+                       config_invalid = 1;
+                       return;
                }
+               /* Check if it's our memory type. */
+               if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM,
+                                         sdram_start, sdram_size) < 0 ||
+                   (rg.type != OMAPFB_MEMTYPE_SDRAM))
+                       continue;
+               BUG_ON(omapfb_config.mem_desc.region[i].size);
+               if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) {
+                       config_invalid = 1;
+                       return;
+               }
+               if (rg.paddr)
+                       reserve_bootmem(rg.paddr, rg.size);
+               reserved += rg.size;
+               omapfb_config.mem_desc.region[i] = rg;
+               configured_regions++;
        }
+       omapfb_config.mem_desc.region_cnt = i;
+       if (reserved)
+               pr_info("Reserving %lu bytes SDRAM for frame buffer\n",
+                        reserved);
+}
+
+/*
+ * Called at sram init time, before anything is pushed to the SRAM stack.
+ * Because of the stack scheme, we will allocate everything from the
+ * start of the lowest address region to the end of SRAM. This will also
+ * include padding for page alignment and possible holes between regions.
+ *
+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
+ * this point, since the driver built as a module would have problem with
+ * freeing / reallocating the regions.
+ */
+unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+                                 unsigned long sram_vstart,
+                                 unsigned long sram_size,
+                                 unsigned long pstart_avail,
+                                 unsigned long size_avail)
+{
+       struct omapfb_mem_region        rg;
+       unsigned long                   pend_avail;
+       unsigned long                   reserved;
+       int                             i;
+
+       if (config_invalid)
+               return 0;
+
+       reserved = 0;
+       pend_avail = pstart_avail + size_avail;
+       for (i = 0; ; i++) {
+               if (get_fbmem_region(i, &rg) < 0)
+                       break;
+               if (i == OMAPFB_PLANE_NUM) {
+                       printk(KERN_ERR
+                               "Extraneous FB mem configuration entries\n");
+                       config_invalid = 1;
+                       return 0;
+               }
+
+               /* Check if it's our memory type. */
+               if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM,
+                                         sram_pstart, sram_size) < 0 ||
+                   (rg.type != OMAPFB_MEMTYPE_SRAM))
+                       continue;
+               BUG_ON(omapfb_config.mem_desc.region[i].size);
+
+               if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) {
+                       config_invalid = 1;
+                       return 0;
+               }
+
+               if (!rg.paddr) {
+                       /* Dynamic allocation */
+                       if ((size_avail & PAGE_MASK) < rg.size) {
+                               printk("Not enough SRAM for FB region %d\n",
+                                       i);
+                               config_invalid = 1;
+                               return 0;
+                       }
+                       size_avail = (size_avail - rg.size) & PAGE_MASK;
+                       rg.paddr = pstart_avail + size_avail;
+               }
+               /* Reserve everything above the start of the region. */
+               if (pend_avail - rg.paddr > reserved)
+                       reserved = pend_avail - rg.paddr;
+               size_avail = pend_avail - reserved - pstart_avail;
+
+               /*
+                * We have a kernel mapping for this already, so the
+                * driver won't have to make one.
+                */
+               rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart);
+               omapfb_config.mem_desc.region[i] = rg;
+               configured_regions++;
+       }
+       omapfb_config.mem_desc.region_cnt = i;
+       if (reserved)
+               pr_info("Reserving %lu bytes SRAM for frame buffer\n",
+                        reserved);
+       return reserved;
+}
+
+void omapfb_set_ctrl_platform_data(void *data)
+{
+       omapfb_config.ctrl_platform_data = data;
 }
 
 static inline int omap_init_fb(void)
 {
        const struct omap_lcd_config *conf;
 
+       if (config_invalid)
+               return 0;
+       if (configured_regions != omapfb_config.mem_desc.region_cnt) {
+               printk(KERN_ERR "Invalid FB mem configuration entries\n");
+               return 0;
+       }
        conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
-       if (conf == NULL)
+       if (conf == NULL) {
+               if (configured_regions)
+                       /* FB mem config, but no LCD config? */
+                       printk(KERN_ERR "Missing LCD configuration\n");
                return 0;
-
+       }
        omapfb_config.lcd = *conf;
 
        return platform_device_register(&omap_fb_device);
@@ -72,7 +328,16 @@ arch_initcall(omap_init_fb);
 
 #else
 
-void omapfb_reserve_mem(void) {}
+void omapfb_reserve_sdram(void) {}
+unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+                                 unsigned long sram_vstart,
+                                 unsigned long sram_size,
+                                 unsigned long start_avail,
+                                 unsigned long size_avail)
+{
+       return 0;
+}
+
 
 #endif
 
index 9dc6d3617bdb8182f02b900522830331446f85fc..337455dfe64d493e64746d62caf38e7d169e71d2 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
 #include <linux/err.h>
@@ -1545,7 +1544,7 @@ void omap2_gpio_resume_after_retention(void)
  * This may get called early from board specific init
  * for boards that have interrupts routed via FPGA.
  */
-int omap_gpio_init(void)
+int __init omap_gpio_init(void)
 {
        if (!initialized)
                return _omap_gpio_init();
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
new file mode 100644 (file)
index 0000000..de7e6ef
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *             Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/blkdev.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/arch/mailbox.h>
+#include "mailbox.h"
+
+static struct omap_mbox *mboxes;
+static DEFINE_RWLOCK(mboxes_lock);
+
+/* Mailbox Sequence Bit function */
+void omap_mbox_init_seq(struct omap_mbox *mbox)
+{
+       mbox_seq_init(mbox);
+}
+EXPORT_SYMBOL(omap_mbox_init_seq);
+
+/*
+ * message sender
+ */
+static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
+{
+       int ret = 0, i = 1000;
+
+       while (mbox_fifo_full(mbox)) {
+               if (mbox->ops->type == OMAP_MBOX_TYPE2)
+                       return -1;
+               if (--i == 0)
+                       return -1;
+               udelay(1);
+       }
+
+       if (arg && mbox->txq->callback) {
+               ret = mbox->txq->callback(arg);
+               if (ret)
+                       goto out;
+       }
+
+       mbox_seq_toggle(mbox, &msg);
+       mbox_fifo_write(mbox, msg);
+ out:
+       return ret;
+}
+
+int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
+{
+       struct request *rq;
+       struct request_queue *q = mbox->txq->queue;
+       int ret = 0;
+
+       rq = blk_get_request(q, WRITE, GFP_ATOMIC);
+       if (unlikely(!rq)) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       rq->data = (void *)msg;
+       blk_insert_request(q, rq, 0, arg);
+
+       schedule_work(&mbox->txq->work);
+ fail:
+       return ret;
+}
+EXPORT_SYMBOL(omap_mbox_msg_send);
+
+static void mbox_tx_work(struct work_struct *work)
+{
+       int ret;
+       struct request *rq;
+       struct omap_mbox_queue *mq = container_of(work,
+                               struct omap_mbox_queue, work);
+       struct omap_mbox *mbox = mq->queue->queuedata;
+       struct request_queue *q = mbox->txq->queue;
+
+       while (1) {
+               spin_lock(q->queue_lock);
+               rq = elv_next_request(q);
+               spin_unlock(q->queue_lock);
+
+               if (!rq)
+                       break;
+
+               ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special);
+               if (ret) {
+                       enable_mbox_irq(mbox, IRQ_TX);
+                       return;
+               }
+
+               spin_lock(q->queue_lock);
+               blkdev_dequeue_request(rq);
+               end_that_request_last(rq, 0);
+               spin_unlock(q->queue_lock);
+       }
+}
+
+/*
+ * Message receiver(workqueue)
+ */
+static void mbox_rx_work(struct work_struct *work)
+{
+       struct omap_mbox_queue *mq =
+                       container_of(work, struct omap_mbox_queue, work);
+       struct omap_mbox *mbox = mq->queue->queuedata;
+       struct request_queue *q = mbox->rxq->queue;
+       struct request *rq;
+       mbox_msg_t msg;
+       unsigned long flags;
+
+       if (mbox->rxq->callback == NULL) {
+               sysfs_notify(&mbox->dev.kobj, NULL, "mbox");
+               return;
+       }
+
+       while (1) {
+               spin_lock_irqsave(q->queue_lock, flags);
+               rq = elv_next_request(q);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+               if (!rq)
+                       break;
+
+               msg = (mbox_msg_t) rq->data;
+
+               spin_lock_irqsave(q->queue_lock, flags);
+               blkdev_dequeue_request(rq);
+               end_that_request_last(rq, 0);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+
+               mbox->rxq->callback((void *)msg);
+       }
+}
+
+/*
+ * Mailbox interrupt handler
+ */
+static void mbox_txq_fn(request_queue_t * q)
+{
+}
+
+static void mbox_rxq_fn(request_queue_t * q)
+{
+}
+
+static void __mbox_tx_interrupt(struct omap_mbox *mbox)
+{
+       disable_mbox_irq(mbox, IRQ_TX);
+       ack_mbox_irq(mbox, IRQ_TX);
+       schedule_work(&mbox->txq->work);
+}
+
+static void __mbox_rx_interrupt(struct omap_mbox *mbox)
+{
+       struct request *rq;
+       mbox_msg_t msg;
+       request_queue_t *q = mbox->rxq->queue;
+
+       disable_mbox_irq(mbox, IRQ_RX);
+
+       while (!mbox_fifo_empty(mbox)) {
+               rq = blk_get_request(q, WRITE, GFP_ATOMIC);
+               if (unlikely(!rq))
+                       goto nomem;
+
+               msg = mbox_fifo_read(mbox);
+               rq->data = (void *)msg;
+
+               if (unlikely(mbox_seq_test(mbox, msg))) {
+                       pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
+                       if (mbox->err_notify)
+                               mbox->err_notify();
+               }
+
+               blk_insert_request(q, rq, 0, NULL);
+               if (mbox->ops->type == OMAP_MBOX_TYPE1)
+                       break;
+       }
+
+       /* no more messages in the fifo. clear IRQ source. */
+       ack_mbox_irq(mbox, IRQ_RX);
+       enable_mbox_irq(mbox, IRQ_RX);
+       nomem:
+       schedule_work(&mbox->rxq->work);
+}
+
+static irqreturn_t mbox_interrupt(int irq, void *p)
+{
+       struct omap_mbox *mbox = (struct omap_mbox *)p;
+
+       if (is_mbox_irq(mbox, IRQ_TX))
+               __mbox_tx_interrupt(mbox);
+
+       if (is_mbox_irq(mbox, IRQ_RX))
+               __mbox_rx_interrupt(mbox);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t
+omap_mbox_write(struct device *dev, struct device_attribute *attr,
+               const char * buf, size_t count)
+{
+       int ret;
+       mbox_msg_t *p = (mbox_msg_t *)buf;
+       struct omap_mbox *mbox = dev_get_drvdata(dev);
+
+       for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) {
+               ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL);
+               if (ret)
+                       return -EAGAIN;
+               p++;
+       }
+
+       return (size_t)((char *)p - buf);
+}
+
+static ssize_t
+omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       unsigned long flags;
+       struct request *rq;
+       mbox_msg_t *p = (mbox_msg_t *) buf;
+       struct omap_mbox *mbox = dev_get_drvdata(dev);
+       struct request_queue *q = mbox->rxq->queue;
+
+       while (1) {
+               spin_lock_irqsave(q->queue_lock, flags);
+               rq = elv_next_request(q);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+
+               if (!rq)
+                       break;
+
+               *p = (mbox_msg_t) rq->data;
+
+               spin_lock_irqsave(q->queue_lock, flags);
+               blkdev_dequeue_request(rq);
+               end_that_request_last(rq, 0);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+
+               if (unlikely(mbox_seq_test(mbox, *p))) {
+                       pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
+                       continue;
+               }
+               p++;
+       }
+
+       pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
+
+       return (size_t) ((char *)p - buf);
+}
+
+static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write);
+
+static ssize_t mbox_show(struct class *class, char *buf)
+{
+       return sprintf(buf, "mbox");
+}
+
+static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
+
+static struct class omap_mbox_class = {
+       .name = "omap_mbox",
+};
+
+static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
+                                       request_fn_proc * proc,
+                                       void (*work) (struct work_struct *))
+{
+       request_queue_t *q;
+       struct omap_mbox_queue *mq;
+
+       mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
+       if (!mq)
+               return NULL;
+
+       spin_lock_init(&mq->lock);
+
+       q = blk_init_queue(proc, &mq->lock);
+       if (!q)
+               goto error;
+       q->queuedata = mbox;
+       mq->queue = q;
+
+       INIT_WORK(&mq->work, work);
+
+       return mq;
+error:
+       kfree(mq);
+       return NULL;
+}
+
+static void mbox_queue_free(struct omap_mbox_queue *q)
+{
+       blk_cleanup_queue(q->queue);
+       kfree(q);
+}
+
+static int omap_mbox_init(struct omap_mbox *mbox)
+{
+       int ret;
+       struct omap_mbox_queue *mq;
+
+       if (likely(mbox->ops->startup)) {
+               ret = mbox->ops->startup(mbox);
+               if (unlikely(ret))
+                       return ret;
+       }
+
+       mbox->dev.class = &omap_mbox_class;
+       strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN);
+       dev_set_drvdata(&mbox->dev, mbox);
+
+       ret = device_register(&mbox->dev);
+       if (unlikely(ret))
+               goto fail_device_reg;
+
+       ret = device_create_file(&mbox->dev, &dev_attr_mbox);
+       if (unlikely(ret)) {
+               printk(KERN_ERR
+                       "device_create_file failed: %d\n", ret);
+               goto fail_create_mbox;
+       }
+
+       ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
+                               mbox->name, mbox);
+       if (unlikely(ret)) {
+               printk(KERN_ERR
+                       "failed to register mailbox interrupt:%d\n", ret);
+               goto fail_request_irq;
+       }
+       enable_mbox_irq(mbox, IRQ_RX);
+
+       mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work);
+       if (!mq) {
+               ret = -ENOMEM;
+               goto fail_alloc_txq;
+       }
+       mbox->txq = mq;
+
+       mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work);
+       if (!mq) {
+               ret = -ENOMEM;
+               goto fail_alloc_rxq;
+       }
+       mbox->rxq = mq;
+
+       return 0;
+
+ fail_alloc_rxq:
+       mbox_queue_free(mbox->txq);
+ fail_alloc_txq:
+       free_irq(mbox->irq, mbox);
+ fail_request_irq:
+       device_remove_file(&mbox->dev, &dev_attr_mbox);
+ fail_create_mbox:
+       device_unregister(&mbox->dev);
+ fail_device_reg:
+       if (unlikely(mbox->ops->shutdown))
+               mbox->ops->shutdown(mbox);
+
+       return ret;
+}
+
+static void omap_mbox_fini(struct omap_mbox *mbox)
+{
+       mbox_queue_free(mbox->txq);
+       mbox_queue_free(mbox->rxq);
+
+       free_irq(mbox->irq, mbox);
+       device_remove_file(&mbox->dev, &dev_attr_mbox);
+       class_unregister(&omap_mbox_class);
+
+       if (unlikely(mbox->ops->shutdown))
+               mbox->ops->shutdown(mbox);
+}
+
+static struct omap_mbox **find_mboxes(const char *name)
+{
+       struct omap_mbox **p;
+
+       for (p = &mboxes; *p; p = &(*p)->next) {
+               if (strcmp((*p)->name, name) == 0)
+                       break;
+       }
+
+       return p;
+}
+
+struct omap_mbox *omap_mbox_get(const char *name)
+{
+       struct omap_mbox *mbox;
+       int ret;
+
+       read_lock(&mboxes_lock);
+       mbox = *(find_mboxes(name));
+       if (mbox == NULL) {
+               read_unlock(&mboxes_lock);
+               return ERR_PTR(-ENOENT);
+       }
+
+       read_unlock(&mboxes_lock);
+
+       ret = omap_mbox_init(mbox);
+       if (ret)
+               return ERR_PTR(-ENODEV);
+
+       return mbox;
+}
+EXPORT_SYMBOL(omap_mbox_get);
+
+void omap_mbox_put(struct omap_mbox *mbox)
+{
+       omap_mbox_fini(mbox);
+}
+EXPORT_SYMBOL(omap_mbox_put);
+
+int omap_mbox_register(struct omap_mbox *mbox)
+{
+       int ret = 0;
+       struct omap_mbox **tmp;
+
+       if (!mbox)
+               return -EINVAL;
+       if (mbox->next)
+               return -EBUSY;
+
+       write_lock(&mboxes_lock);
+       tmp = find_mboxes(mbox->name);
+       if (*tmp)
+               ret = -EBUSY;
+       else
+               *tmp = mbox;
+       write_unlock(&mboxes_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(omap_mbox_register);
+
+int omap_mbox_unregister(struct omap_mbox *mbox)
+{
+       struct omap_mbox **tmp;
+
+       write_lock(&mboxes_lock);
+       tmp = &mboxes;
+       while (*tmp) {
+               if (mbox == *tmp) {
+                       *tmp = mbox->next;
+                       mbox->next = NULL;
+                       write_unlock(&mboxes_lock);
+                       return 0;
+               }
+               tmp = &(*tmp)->next;
+       }
+       write_unlock(&mboxes_lock);
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int __init omap_mbox_class_init(void)
+{
+       int ret = class_register(&omap_mbox_class);
+       if (!ret)
+               ret = class_create_file(&omap_mbox_class, &class_attr_mbox);
+
+       return ret;
+}
+
+static void __exit omap_mbox_class_exit(void)
+{
+       class_remove_file(&omap_mbox_class, &class_attr_mbox);
+       class_unregister(&omap_mbox_class);
+}
+
+subsys_initcall(omap_mbox_class_init);
+module_exit(omap_mbox_class_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h
new file mode 100644 (file)
index 0000000..67c6740
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Mailbox internal functions
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_PLAT_MAILBOX_H
+#define __ARCH_ARM_PLAT_MAILBOX_H
+
+/*
+ * Mailbox sequence bit API
+ */
+#if defined(CONFIG_ARCH_OMAP1)
+#  define MBOX_USE_SEQ_BIT
+#elif defined(CONFIG_ARCH_OMAP2)
+#  define MBOX_USE_SEQ_BIT
+#endif
+
+#ifdef MBOX_USE_SEQ_BIT
+/* seq_rcv should be initialized with any value other than
+ * 0 and 1 << 31, to allow either value for the first
+ * message.  */
+static inline void mbox_seq_init(struct omap_mbox *mbox)
+{
+       /* any value other than 0 and 1 << 31 */
+       mbox->seq_rcv = 0xffffffff;
+}
+
+static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
+{
+       /* add seq_snd to msg */
+       *msg = (*msg & 0x7fffffff) | mbox->seq_snd;
+       /* flip seq_snd */
+       mbox->seq_snd ^= 1 << 31;
+}
+
+static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+       mbox_msg_t seq = msg & (1 << 31);
+       if (seq == mbox->seq_rcv)
+               return -1;
+       mbox->seq_rcv = seq;
+       return 0;
+}
+#else
+static inline void mbox_seq_init(struct omap_mbox *mbox)
+{
+}
+static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
+{
+}
+static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+       return 0;
+}
+#endif
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+{
+       return mbox->ops->fifo_read(mbox);
+}
+static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+       mbox->ops->fifo_write(mbox, msg);
+}
+static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+{
+       return mbox->ops->fifo_empty(mbox);
+}
+static inline int mbox_fifo_full(struct omap_mbox *mbox)
+{
+       return mbox->ops->fifo_full(mbox);
+}
+
+/* Mailbox IRQ handle functions */
+static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+       mbox->ops->enable_irq(mbox, irq);
+}
+static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+       mbox->ops->disable_irq(mbox, irq);
+}
+static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+       if (mbox->ops->ack_irq)
+               mbox->ops->ack_irq(mbox, irq);
+}
+static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+       return mbox->ops->is_irq(mbox, irq);
+}
+
+#endif                         /* __ARCH_ARM_PLAT_MAILBOX_H */
index 19014b2ff4c6315a6e190c3c2c03e17c33eb184b..bc46f33aede3dc5bc9ebe9394bde2183faa126ed 100644 (file)
 
 #define ROUND_DOWN(value,boundary)     ((value) & (~((boundary)-1)))
 
+static unsigned long omap_sram_start;
 static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
-unsigned long omap_fb_sram_start;
-unsigned long omap_fb_sram_size;
+extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+                                        unsigned long sram_vstart,
+                                        unsigned long sram_size,
+                                        unsigned long pstart_avail,
+                                        unsigned long size_avail);
 
-/* Depending on the target RAMFS firewall setup, the public usable amount of
+/*
+ * Depending on the target RAMFS firewall setup, the public usable amount of
  * SRAM varies.  The default accessable size for all device types is 2k. A GP
  * device allows ARM11 but not other initators for full size. This
  * functionality seems ok until some nice security API happens.
@@ -77,32 +82,6 @@ static int is_sram_locked(void)
                return 1; /* assume locked with no PPA or security driver */
 }
 
-void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
-                     unsigned long *start, unsigned long *size)
-{
-       const struct omap_fbmem_config *fbmem_conf;
-
-       fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
-       if (fbmem_conf != NULL) {
-               *start = fbmem_conf->fb_sram_start;
-               *size = fbmem_conf->fb_sram_size;
-       } else {
-               *size = 0;
-               *start = 0;
-       }
-
-       if (*size && (
-           *start < start_avail ||
-           *start + *size > start_avail + size_avail)) {
-               printk(KERN_ERR "invalid FB SRAM configuration\n");
-               *start = start_avail;
-               *size = size_avail;
-       }
-
-       if (*size)
-               pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
-}
-
 /*
  * The amount of SRAM depends on the core type.
  * Note that we cannot try to test for SRAM here because writes
@@ -111,16 +90,16 @@ void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
  */
 void __init omap_detect_sram(void)
 {
-       unsigned long sram_start;
+       unsigned long reserved;
 
        if (cpu_is_omap24xx()) {
                if (is_sram_locked()) {
                        omap_sram_base = OMAP2_SRAM_PUB_VA;
-                       sram_start = OMAP2_SRAM_PUB_PA;
+                       omap_sram_start = OMAP2_SRAM_PUB_PA;
                        omap_sram_size = 0x800; /* 2K */
                } else {
                        omap_sram_base = OMAP2_SRAM_VA;
-                       sram_start = OMAP2_SRAM_PA;
+                       omap_sram_start = OMAP2_SRAM_PA;
                        if (cpu_is_omap242x())
                                omap_sram_size = 0xa0000; /* 640K */
                        else if (cpu_is_omap243x())
@@ -128,7 +107,7 @@ void __init omap_detect_sram(void)
                }
        } else {
                omap_sram_base = OMAP1_SRAM_VA;
-               sram_start = OMAP1_SRAM_PA;
+               omap_sram_start = OMAP1_SRAM_PA;
 
                if (cpu_is_omap730())
                        omap_sram_size = 0x32000;       /* 200K */
@@ -144,12 +123,11 @@ void __init omap_detect_sram(void)
                        omap_sram_size = 0x4000;
                }
        }
-       get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
-                        omap_sram_size - SRAM_BOOTLOADER_SZ,
-                        &omap_fb_sram_start, &omap_fb_sram_size);
-       if (omap_fb_sram_size)
-               omap_sram_size -= sram_start + omap_sram_size -
-                                 omap_fb_sram_start;
+       reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
+                                      omap_sram_size,
+                                      omap_sram_start + SRAM_BOOTLOADER_SZ,
+                                      omap_sram_size - SRAM_BOOTLOADER_SZ);
+       omap_sram_size -= reserved;
        omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
index 114f87151d601a303d9080dbff7d2617b86f87ff..2feceec8eccd0e639933c07b71bacf0a5e924ea4 100644 (file)
@@ -215,7 +215,7 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction omap_32k_timer_irq = {
        .name           = "32KHz timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = omap_32k_timer_interrupt,
 };
 
index 7e8096809be2bc227ef4e8acb310455a92d8cbfb..25489aafb11398f16849bb7cb225ee624d07c5e7 100644 (file)
 #include <asm/arch/usb.h>
 #include <asm/arch/board.h>
 
+#ifdef CONFIG_ARCH_OMAP1
+
+#define INT_USB_IRQ_GEN                IH2_BASE + 20
+#define INT_USB_IRQ_NISO       IH2_BASE + 30
+#define INT_USB_IRQ_ISO                IH2_BASE + 29
+#define INT_USB_IRQ_HGEN       INT_USB_HHC_1
+#define INT_USB_IRQ_OTG                IH2_BASE + 8
+
+#else
+
+#define INT_USB_IRQ_GEN                INT_24XX_USB_IRQ_GEN
+#define INT_USB_IRQ_NISO       INT_24XX_USB_IRQ_NISO
+#define INT_USB_IRQ_ISO                INT_24XX_USB_IRQ_ISO
+#define INT_USB_IRQ_HGEN       INT_24XX_USB_IRQ_HGEN
+#define INT_USB_IRQ_OTG                INT_24XX_USB_IRQ_OTG
+
+#endif
+
+
 /* 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.
@@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
 {
        u32     syscon1 = 0;
 
+       if (cpu_is_omap24xx())
+               CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL);
+
        if (nwires == 0) {
-               if (!cpu_is_omap15xx()) {
+               if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
                        /* pulldown D+/D- */
                        USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
                }
                return 0;
        }
 
-       if (is_device)
-               omap_cfg_reg(W4_USB_PUEN);
+       if (is_device) {
+               if (cpu_is_omap24xx())
+                       omap_cfg_reg(J20_24XX_USB0_PUEN);
+               else
+                       omap_cfg_reg(W4_USB_PUEN);
+       }
 
-       /* internal transceiver */
-       if (nwires == 2) {
+       /* internal transceiver (unavailable on 17xx, 24xx) */
+       if (!cpu_class_is_omap2() && nwires == 2) {
                // omap_cfg_reg(P9_USB_DP);
                // omap_cfg_reg(R8_USB_DM);
 
@@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
                return 0;
        }
 
-       omap_cfg_reg(V6_USB0_TXD);
-       omap_cfg_reg(W9_USB0_TXEN);
-       omap_cfg_reg(W5_USB0_SE0);
+       if (cpu_is_omap24xx()) {
+               omap_cfg_reg(K18_24XX_USB0_DAT);
+               omap_cfg_reg(K19_24XX_USB0_TXEN);
+               omap_cfg_reg(J14_24XX_USB0_SE0);
+               if (nwires != 3)
+                       omap_cfg_reg(J18_24XX_USB0_RCV);
+       } else {
+               omap_cfg_reg(V6_USB0_TXD);
+               omap_cfg_reg(W9_USB0_TXEN);
+               omap_cfg_reg(W5_USB0_SE0);
+               if (nwires != 3)
+                       omap_cfg_reg(Y5_USB0_RCV);
+       }
 
-       /* NOTE:  SPEED and SUSP aren't configured here */
+       /* NOTE:  SPEED and SUSP aren't configured here.  OTG hosts
+        * may be able to use I2C requests to set those bits along
+        * with VBUS switching and overcurrent detction.
+        */
 
-       if (nwires != 3)
-               omap_cfg_reg(Y5_USB0_RCV);
-       if (nwires != 6)
+       if (cpu_class_is_omap1() && nwires != 6)
                USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
 
        switch (nwires) {
        case 3:
                syscon1 = 2;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
                break;
        case 4:
                syscon1 = 1;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
                break;
        case 6:
                syscon1 = 3;
-               omap_cfg_reg(AA9_USB0_VP);
-               omap_cfg_reg(R9_USB0_VM);
-               USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               if (cpu_is_omap24xx()) {
+                       omap_cfg_reg(J19_24XX_USB0_VP);
+                       omap_cfg_reg(K20_24XX_USB0_VM);
+                       CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR);
+               } else {
+                       omap_cfg_reg(AA9_USB0_VP);
+                       omap_cfg_reg(R9_USB0_VM);
+                       USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               }
                break;
        default:
                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
@@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires)
 {
        u32     syscon1 = 0;
 
-       if (nwires != 6 && !cpu_is_omap15xx())
+       if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
                USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+       if (cpu_is_omap24xx())
+               CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL);
+
        if (nwires == 0)
                return 0;
 
        /* external transceiver */
-       omap_cfg_reg(USB1_TXD);
-       omap_cfg_reg(USB1_TXEN);
+       if (cpu_class_is_omap1()) {
+               omap_cfg_reg(USB1_TXD);
+               omap_cfg_reg(USB1_TXEN);
+               if (nwires != 3)
+                       omap_cfg_reg(USB1_RCV);
+       }
+
        if (cpu_is_omap15xx()) {
                omap_cfg_reg(USB1_SEO);
                omap_cfg_reg(USB1_SPEED);
@@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires)
        } else if (cpu_is_omap1710()) {
                omap_cfg_reg(R13_1710_USB1_SE0);
                // SUSP
+       } else if (cpu_is_omap24xx()) {
+               /* NOTE:  board-specific code must set up pin muxing for usb1,
+                * since each signal could come out on either of two balls.
+                */
        } else {
-               pr_debug("usb unrecognized\n");
+               pr_debug("usb%d cpu unrecognized\n", 1);
+               return 0;
        }
-       if (nwires != 3)
-               omap_cfg_reg(USB1_RCV);
 
        switch (nwires) {
+       case 2:
+               if (!cpu_is_omap24xx())
+                       goto bad;
+               /* NOTE: board-specific code must override this setting if
+                * this TLL link is not using DP/DM
+                */
+               syscon1 = 1;
+               CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL);
+               break;
        case 3:
                syscon1 = 2;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
                break;
        case 4:
                syscon1 = 1;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
                break;
        case 6:
+               if (cpu_is_omap24xx())
+                       goto bad;
                syscon1 = 3;
                omap_cfg_reg(USB1_VP);
                omap_cfg_reg(USB1_VM);
@@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
                        USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
                break;
        default:
+bad:
                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
                        1, nwires);
        }
@@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
 {
        u32     syscon1 = 0;
 
-       /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */
+       if (cpu_is_omap24xx()) {
+               CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL)
+                                       | USBT2TLL5PI);
+               alt_pingroup = 0;
+       }
+
+       /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
        if (alt_pingroup || nwires == 0)
                return 0;
-       if (nwires != 6 && !cpu_is_omap15xx())
+
+       if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
                USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
 
        /* external transceiver */
@@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
                if (nwires != 3)
                        omap_cfg_reg(Y5_USB2_RCV);
                // FIXME omap_cfg_reg(USB2_SPEED);
+       } else if (cpu_is_omap24xx()) {
+               omap_cfg_reg(Y11_24XX_USB2_DAT);
+               omap_cfg_reg(AA10_24XX_USB2_SE0);
+               if (nwires > 2)
+                       omap_cfg_reg(AA12_24XX_USB2_TXEN);
+               if (nwires > 3)
+                       omap_cfg_reg(AA6_24XX_USB2_RCV);
        } else {
-               pr_debug("usb unrecognized\n");
+               pr_debug("usb%d cpu unrecognized\n", 1);
+               return 0;
        }
-       // omap_cfg_reg(USB2_SUSP);
+       // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP);
 
        switch (nwires) {
+       case 2:
+               if (!cpu_is_omap24xx())
+                       goto bad;
+               /* NOTE: board-specific code must override this setting if
+                * this TLL link is not using DP/DM
+                */
+               syscon1 = 1;
+               CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL);
+               break;
        case 3:
                syscon1 = 2;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
                break;
        case 4:
                syscon1 = 1;
+               if (cpu_is_omap24xx())
+                       CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
+               break;
+       case 5:
+               if (!cpu_is_omap24xx())
+                       goto bad;
+               omap_cfg_reg(AA4_24XX_USB2_TLLSE0);
+               /* NOTE: board-specific code must override this setting if
+                * this TLL link is not using DP/DM.  Something must also
+                * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
+                */
+               syscon1 = 3;
+               CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL)
+                                       | USBT2TLL5PI;
                break;
        case 6:
+               if (cpu_is_omap24xx())
+                       goto bad;
                syscon1 = 3;
                if (cpu_is_omap15xx()) {
                        omap_cfg_reg(USB2_VP);
@@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
                }
                break;
        default:
+bad:
                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
                        2, nwires);
        }
@@ -294,13 +410,13 @@ static struct resource udc_resources[] = {
                .end            = UDC_BASE + 0xff,
                .flags          = IORESOURCE_MEM,
        }, {            /* general IRQ */
-               .start          = IH2_BASE + 20,
+               .start          = INT_USB_IRQ_GEN,
                .flags          = IORESOURCE_IRQ,
        }, {            /* PIO IRQ */
-               .start          = IH2_BASE + 30,
+               .start          = INT_USB_IRQ_NISO,
                .flags          = IORESOURCE_IRQ,
        }, {            /* SOF IRQ */
-               .start          = IH2_BASE + 29,
+               .start          = INT_USB_IRQ_ISO,
                .flags          = IORESOURCE_IRQ,
        },
 };
@@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0;
 static struct resource ohci_resources[] = {
        {
                .start  = OMAP_OHCI_BASE,
-               .end    = OMAP_OHCI_BASE + 4096 - 1,
+               .end    = OMAP_OHCI_BASE + 0xff,
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = INT_USB_HHC_1,
+               .start  = INT_USB_IRQ_HGEN,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -361,7 +477,7 @@ static struct resource otg_resources[] = {
                .end            = OTG_BASE + 0xff,
                .flags          = IORESOURCE_MEM,
        }, {
-               .start          = IH2_BASE + 8,
+               .start          = INT_USB_IRQ_OTG,
                .flags          = IORESOURCE_IRQ,
        },
 };
@@ -385,7 +501,7 @@ static struct platform_device otg_device = {
 
 
 // FIXME correct answer depends on hmc_mode,
-// as does any nonzero value for config->otg port number
+// as does (on omap1) any nonzero value for config->otg port number
 #ifdef CONFIG_USB_GADGET_OMAP
 #define        is_usb0_device(config)  1
 #else
@@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config)
        if (config->otg)
                syscon |= OTG_EN;
 #endif
-       pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
+       if (cpu_class_is_omap1())
+               pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
        pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
        OTG_SYSCON_2_REG = syscon;
 
        printk("USB: hmc %d", config->hmc_mode);
-       if (alt_pingroup)
+       if (!alt_pingroup)
                printk(", usb2 alt %d wires", config->pins[2]);
        else if (config->pins[0])
                printk(", usb0 %d wires%s", config->pins[0],
@@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config)
                printk(", Mini-AB on usb%d", config->otg - 1);
        printk("\n");
 
-       /* leave USB clocks/controllers off until needed */
-       ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
-       ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
-       ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+       if (cpu_class_is_omap1()) {
+               /* leave USB clocks/controllers off until needed */
+               ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
+               ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
+               ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+       }
        syscon = OTG_SYSCON_1_REG;
        syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
 
@@ -585,7 +704,7 @@ omap_usb_init(void)
        }
        platform_data = *config;
 
-       if (cpu_is_omap730() || cpu_is_omap16xx())
+       if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx())
                omap_otg_init(&platform_data);
        else if (cpu_is_omap15xx())
                omap_1510_usb_init(&platform_data);
index 435349dc3243fa352bd17d315f3921254f752d3c..7b7ae790b00da07ebfede651cd10d2bfa1706e89 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/plat-s3c24xx/sleep.S
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
index c523d1c9cce5e6e4c2ae0723aca5c3dc5871cd22..b7667375bcec891912682260cd62e855d968085c 100644 (file)
@@ -138,7 +138,7 @@ s3c2410_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction s3c2410_timer_irq = {
        .name           = "S3C2410 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = s3c2410_timer_interrupt,
 };
 
index 93293d04b3032c47f1181fb0576d34521e454e7b..f735d7e018e4161967114ab5ecff778a81f4d449 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/pm.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
index 9343889b27fe897cc647533287f9989f5ab65ce4..416927956721ac311f39a5400b9ddd832e792787 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
index 6a8ef8da6dab07000467c98fbd7ea95a2617dd10..379b82dc645fc6ca08353c53997647c311baed9e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
index f2901581d4dacd9aba26982c85918cd674f1dbcc..42505541a9b17836f8c30fbad66a19026b072a52 100644 (file)
@@ -176,13 +176,9 @@ void __init pgtable_cache_init(void)
 {
        pte_cache = kmem_cache_create("pte-cache",
                                sizeof(pte_t) * PTRS_PER_PTE,
-                               0, 0, pte_cache_ctor, NULL);
-       if (!pte_cache)
-               BUG();
+                               0, SLAB_PANIC, pte_cache_ctor, NULL);
 
        pgd_cache = kmem_cache_create("pgd-cache", MEMC_TABLE_SIZE +
                                sizeof(pgd_t) * PTRS_PER_PGD,
-                               0, 0, pgd_cache_ctor, NULL);
-       if (!pgd_cache)
-               BUG();
+                               0, SLAB_PANIC, pgd_cache_ctor, NULL);
 }
index 6115fc1f0cfab65c06277da9bfc46e8de89ade6c..dc6bc01f232cb3a1b2574ef40e8ff043070ddd7a 100644 (file)
@@ -16,7 +16,7 @@ AFLAGS                += -mrelax -mno-pic
 CFLAGS_MODULE  += -mno-relax
 LDFLAGS_vmlinux        += --relax
 
-cpuflags-$(CONFIG_CPU_AP7000)  += -mcpu=ap7000
+cpuflags-$(CONFIG_CPU_AT32AP7000)      += -mcpu=ap7000
 
 CFLAGS         += $(cpuflags-y)
 AFLAGS         += $(cpuflags-y)
index d0abbcaf1c1e3dac5a6d7eb34313ca0527003d04..004c94b6fc1d62ba9c8aa20bcfaa8591da9c5a0b 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/ptrace.h>
 
 #include <asm/cacheflush.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/ocd.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe);
index 4e4181ed1c6d52a70a5308a50aa4a2a7761099f0..13f988402613a038133f0e84289565210382600a 100644 (file)
@@ -330,13 +330,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 {
        struct pt_regs *childregs;
 
-       childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1;
+       childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
        *childregs = *regs;
 
        if (user_mode(regs))
                childregs->sp = usp;
        else
-               childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE;
+               childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
 
        childregs->r12 = 0; /* Set return value for child */
 
@@ -403,7 +403,7 @@ unsigned long get_wchan(struct task_struct *p)
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
 
-       stack_page = (unsigned long)p->thread_info;
+       stack_page = (unsigned long)task_stack_page(p);
        BUG_ON(!stack_page);
 
        /*
index 6f4388f7c20be5d57726dfcd01fe94fc962fda3b..3c36c2d1614827894a4bfff8d823ce9bf194d1ba 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/user.h>
 #include <asm/uaccess.h>
 #include <asm/ocd.h>
 #include <asm/mmu_context.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 
 static struct pt_regs *get_user_regs(struct task_struct *tsk)
 {
-       return (struct pt_regs *)((unsigned long) tsk->thread_info +
+       return (struct pt_regs *)((unsigned long)task_stack_page(tsk) +
                                  THREAD_SIZE - sizeof(struct pt_regs));
 }
 
@@ -300,7 +299,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs)
        else
                die_val = DIE_BREAKPOINT;
 
-       if (notify_die(die_val, regs, 0, SIGTRAP) == NOTIFY_STOP)
+       if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
                return;
 
        if (likely(ds & DS_SSS)) {
index 7c279586fbbac96b6445adc074ec56848c213e7f..07f6a6fa340de67e07eef9c0f57156008516c0b2 100644 (file)
@@ -291,4 +291,5 @@ sys_call_table:
        .long   sys_shmget              /* 275 */
        .long   sys_shmdt
        .long   sys_shmctl
+       .long   sys_utimensat
        .long   sys_ni_syscall          /* r8 is saturated at nr_syscalls */
index 4f0382d8483fe0bbc8133a5040cb6a8bf2634b49..86d107511dd4dc1290e765714a2b560432e85a17 100644 (file)
 #include <asm/sysreg.h>
 #include <asm/traps.h>
 
-ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&avr32_die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&avr32_die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 static DEFINE_SPINLOCK(die_lock);
 
 void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
@@ -137,7 +123,7 @@ asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
 
 /* This way of handling undefined instructions is stolen from ARM */
 static LIST_HEAD(undef_hook);
-static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(undef_lock);
 
 void register_undef_hook(struct undef_hook *hook)
 {
index 7ad20cfb48a821b117d5c25d55b002b978f5059c..e7f72c995a3251361a912521537455ca16de9f11 100644 (file)
@@ -35,7 +35,7 @@ SECTIONS
                        _einittext = .;
                . = ALIGN(4);
                __tagtable_begin = .;
-                       *(.taglist)
+                       *(.taglist.init)
                __tagtable_end = .;
                        *(.init.data)
                . = ALIGN(16);
index 00c435452d7e500e473b3cbbeb1b4f1d939d5659..0f8c89c9f83243532c57dded20c5fc1be0893b91 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "clock.h"
 
-static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clk_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
index b68d669f823de0a39f1f8bedebc3f5bd13429264..099212d4567c5d33d649c2c0988ec538dfb49803 100644 (file)
@@ -112,16 +112,21 @@ void dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
-#if 0
 void *dma_alloc_writecombine(struct device *dev, size_t size,
                             dma_addr_t *handle, gfp_t gfp)
 {
        struct page *page;
+       dma_addr_t phys;
 
        page = __dma_alloc(dev, size, handle, gfp);
+       if (!page)
+               return NULL;
+
+       phys = page_to_phys(page);
+       *handle = phys;
 
        /* Now, map the page into P3 with write-combining turned on */
-       return __ioremap(page_to_phys(page), size, _PAGE_BUFFER);
+       return __ioremap(phys, size, _PAGE_BUFFER);
 }
 EXPORT_SYMBOL(dma_alloc_writecombine);
 
@@ -132,8 +137,7 @@ void dma_free_writecombine(struct device *dev, size_t size,
 
        iounmap(cpu_addr);
 
-       page = bus_to_page(handle);
+       page = phys_to_page(handle);
        __dma_free(dev, size, page, handle);
 }
 EXPORT_SYMBOL(dma_free_writecombine);
-#endif
index 146ebdbdc3027b07e9893d7ce374ac6e46148164..88b00b15970f9091babb54d2479e261e80e8064e 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/mmu_context.h>
 #include <asm/sysreg.h>
 #include <asm/tlb.h>
index 41d9a9f897002f5536ecca2eeae0ad07b09d7cbd..e455f4504509518c9791163fd05d20d443434735 100644 (file)
@@ -46,7 +46,7 @@ int main(void)
        DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
        DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
        DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
index d7c8e514cb92185c406dd290a4b7164c3044cc12..e718bb4a1ef027fdc050f51d4303cbe11a8905d0 100644 (file)
@@ -73,7 +73,7 @@
 static inline struct pt_regs *get_user_regs(struct task_struct *task)
 {
        return (struct pt_regs *)
-           ((unsigned long)task->thread_info +
+           ((unsigned long)task_stack_page(task) +
             (THREAD_SIZE - sizeof(struct pt_regs)));
 }
 
@@ -99,7 +99,7 @@ static inline long get_reg(struct task_struct *task, int regno)
        unsigned char *reg_ptr;
 
        struct pt_regs *regs =
-           (struct pt_regs *)((unsigned long)task->thread_info +
+           (struct pt_regs *)((unsigned long)task_stack_page(task) +
                               (THREAD_SIZE - sizeof(struct pt_regs)));
        reg_ptr = (char *)regs;
 
@@ -125,7 +125,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data)
        char * reg_ptr;
 
        struct pt_regs *regs =
-           (struct pt_regs *)((unsigned long)task->thread_info +
+           (struct pt_regs *)((unsigned long)task_stack_page(task) +
                               (THREAD_SIZE - sizeof(struct pt_regs)));
        reg_ptr = (char *)regs;
 
index 961c0d58ded4a52ca5313e0ef94e62f8d0adf126..fd2129a04586551bc24ae0d2278ac43b1e48426a 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 19bcad05716f7880506983cec1f580d88bb689cb..41d4a5f93284abe34e1838c1e5379d1ab120956a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index f64624fc4504bef716e5971ae5290011c5fed9f0..1d859c16931e3628853b80bdefa4664bda69b863 100644 (file)
@@ -603,7 +603,7 @@ config ETRAX_CARDBUS
         select HOTPLUG
         select PCCARD_NONSTATIC
         help
-        Enabled the ETRAX Carbus driver.
+        Enabled the ETRAX Cardbus driver.
 
 config PCI
        bool
index 70d3bf0c92e8ebdda3c5d56bcb3663cfe6dc7ffc..832fc63504d4decd21c03eb4ba8fb7462a406851 100644 (file)
@@ -76,7 +76,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
 {
        void __iomem *mem_base;
        int pages = size >> PAGE_SHIFT;
-       int bitmap_size = (pages + 31)/32;
+       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 
        if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
                goto out;
index 82cf2e3624a41e93a1b748c671406f62043876bc..d4d57b74133436a607518e7471318c3c1def3b92 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 1f20c16ac2a48fd193eec7410b1c4fb4cad2681d..105bb5ed48f7d3d5ed1b3ac791b3fc1655479050 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/sched.h>
 #include <linux/in6.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/pm.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 2b6363cbe985d7b4529f46f8eef31bf381c9994e..1085d037027b2cd20b972b797c0a655d282911b3 100644 (file)
@@ -67,7 +67,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index eed694312a795a4e6cae4c6a6d4e579e781beaf3..114738a4558280b264eed8589d91618352320a87 100644 (file)
@@ -45,15 +45,15 @@ config TIME_LOW_RES
        bool
        default y
 
-config ARCH_HAS_ILOG2_U32
+config QUICKLIST
        bool
        default y
 
-config ARCH_HAS_ILOG2_U64
+config ARCH_HAS_ILOG2_U32
        bool
        default y
 
-config ARCH_USES_SLAB_PAGE_STRUCT
+config ARCH_HAS_ILOG2_U64
        bool
        default y
 
index 940ac306e9a0e5b13bf54ff610ec4fc1601a769e..43dc08ec7511eff6b3dba5b4a632ac9dc34d7ba2 100644 (file)
@@ -1482,6 +1482,16 @@ sys_call_table:
        .long sys_faccessat
        .long sys_pselect6
        .long sys_ppoll
+       .long sys_unshare               /* 310 */
+       .long sys_set_robust_list
+       .long sys_get_robust_list
+       .long sys_splice
+       .long sys_sync_file_range
+       .long sys_tee                   /* 315 */
+       .long sys_vmsplice
+       .long sys_move_pages
+       .long sys_getcpu
+       .long sys_epoll_pwait
 
 
 syscall_table_size = (. - sys_call_table)
index 87f360a4ea27165059971e76001a0e818a0178e9..c7e59dcadee47d58c7c44dac6d1cbce7a2134730 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/irq.h>
index 515a5cea5469e1c3bb5ab53315a441246baf7902..9583a338e9d6022b7529dcffa34201917502151d 100644 (file)
 #include <linux/elf.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
+#include <linux/pagemap.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
+#include <asm/tlb.h>
 #include <asm/gdb-stub.h>
 #include <asm/mb-regs.h>
 
@@ -88,6 +90,8 @@ void cpu_idle(void)
                while (!need_resched()) {
                        irq_stat[cpu].idle_timestamp = jiffies;
 
+                       check_pgt_cache();
+
                        if (!frv_dma_inprogress && idle)
                                idle();
                }
index fcff819b4340669003e1e0966f174a4677f004ed..ce88fb95ee59e5ce213d3c4a660e27e3fe9b4cbf 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index f278cdf3a72fa76e9ade9150dbca8d2b08775f73..8e182ced1a0f028d1020e5f44df4da8e5512722c 100644 (file)
@@ -19,7 +19,7 @@ struct sem_waiter {
        struct task_struct      *task;
 };
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
 void semtrace(struct semaphore *sem, const char *str)
 {
        if (sem->debug)
index 8ea3ca2aba621f9390e304e6bf97a1dc140a1e3e..aa3c795d5354aa97084c0f82c23ab3abe3e25359 100644 (file)
@@ -191,7 +191,7 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = {
 static const struct clock_cmode __pminitdata *clock_cmodes;
 static int __pminitdata clock_doubled;
 
-static struct uart_port __initdata __frv_uart0 = {
+static struct uart_port __pminitdata __frv_uart0 = {
        .uartclk                = 0,
        .membase                = (char *) UART0_BASE,
        .irq                    = IRQ_CPU_UART0,
@@ -200,7 +200,7 @@ static struct uart_port __initdata __frv_uart0 = {
        .flags                  = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 };
 
-static struct uart_port __initdata __frv_uart1 = {
+static struct uart_port __pminitdata __frv_uart1 = {
        .uartclk                = 0,
        .membase                = (char *) UART1_BASE,
        .irq                    = IRQ_CPU_UART1,
index 85baeae9666aeae35f0a1e66277500c99c42a697..d64bcaff54cd441ebd76c735c9ad878109c76223 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index c4d4348c9e8ec326b0c169cdd2ae3bc07627b938..26b3df32b9a7476a89dd2ee238f642a4bc2e73fa 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index cac2c01a3a561d3545bdd58a52768e4445e75497..385fd30b142f5cf28951373df0acd80cd45245c8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/elf-fdpic.h>
+#include <asm/mman.h>
 
 /*****************************************************************************/
 /*
index 19b13be114a2695a9876b21f897f44b837feee06..7787c3cc52c6923d58e305b4ae10c4e3ab6b87e1 100644 (file)
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/quicklist.h>
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
-struct kmem_cache *pgd_cache;
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
@@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd)
                set_page_private(next, (unsigned long) pprev);
 }
 
-void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+void pgd_ctor(void *pgd)
 {
        unsigned long flags;
 
@@ -120,7 +120,7 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 }
 
 /* never called when PTRS_PER_PMD > 1 */
-void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+void pgd_dtor(void *pgd)
 {
        unsigned long flags; /* can be called from interrupt context */
 
@@ -133,7 +133,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        pgd_t *pgd;
 
-       pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+       pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
        if (!pgd)
                return pgd;
 
@@ -143,17 +143,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 void pgd_free(pgd_t *pgd)
 {
        /* in the non-PAE case, clear_page_tables() clears user pgd entries */
-       kmem_cache_free(pgd_cache, pgd);
+       quicklist_free(0, pgd_dtor, pgd);
 }
 
 void __init pgtable_cache_init(void)
 {
-       pgd_cache = kmem_cache_create("pgd",
-                                     PTRS_PER_PGD * sizeof(pgd_t),
-                                     PTRS_PER_PGD * sizeof(pgd_t),
-                                     0,
-                                     pgd_ctor,
-                                     pgd_dtor);
-       if (!pgd_cache)
-               panic("pgtable_cache_init(): Cannot create pgd cache");
 }
+
+void check_pgt_cache(void)
+{
+       quicklist_trim(0, pgd_dtor, 25, 16);
+}
+
index e0e9bcb015a905f9bb4be1ff1174b55772ddbb6b..554efe604a085ae31046423e60b227a5ceb7dbc8 100644 (file)
@@ -21,12 +21,12 @@ config GDB_MAGICPRINT
        bool "Message Output for GDB MagicPrint service"
        depends on (H8300H_SIM || H8S_SIM)
        help
-         kernel messages output useing MagicPrint service from GDB
+         kernel messages output using MagicPrint service from GDB
 
 config SYSCALL_PRINT
        bool "SystemCall trace print"
        help
-         outout history of systemcall
+         output history of systemcall
 
 config GDB_DEBUG
        bool "Use gdb stub"
index b78b82ad28a3868466b7b5a5c974fc83eea90884..fc30b4fd0914fcb607d4449b48cea1ff86772f36 100644 (file)
@@ -30,7 +30,7 @@ int main(void)
        DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
        DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 
index f6031373dc21f894b8653804c0fd94e8edb46669..8f2411db7eaf3473d5433e5bf31cda3582208a04 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 302a2dfe634aa8df11b3bfe47669003116cd8a86..11ba75a05220bc7cfefe8febcbfd19b7c29b9315 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 64ad10f984a1027d5037f679524841d1829f1530..30944ee2e61a04ea401277cee8cd8f7af9f4b75b 100644 (file)
@@ -858,9 +858,9 @@ config RELOCATABLE
        bool "Build a relocatable kernel(EXPERIMENTAL)"
        depends on EXPERIMENTAL
        help
-         This build a kernel image that retains relocation information
+         This builds a kernel image that retains relocation information
           so it can be loaded someplace besides the default 1MB.
-         The relocations tend to the kernel binary about 10% larger,
+         The relocations tend to make the kernel binary about 10% larger,
           but are discarded at runtime.
 
          One use is for the kexec on panic case where the recovery kernel
index dce6124cb842a8307625ef673b8d97c4c99007cd..d7f6fb0b30f234895c90554e34303d6f76990115 100644 (file)
@@ -108,7 +108,7 @@ config MCORE2
        bool "Core 2/newer Xeon"
        help
          Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
-         CPUs. You can distingush newer from older Xeons by the CPU family
+         CPUs. You can distinguish newer from older Xeons by the CPU family
          in /proc/cpuinfo. Newer ones have 6.
 
 config MPENTIUM4
@@ -172,7 +172,7 @@ config MWINCHIP3D
        help
          Select this for an IDT Winchip-2A or 3.  Linux and GCC
          treat this chip as a 586TSC with some extended instructions
-         and alignment reqirements.  Also enable out of order memory
+         and alignment requirements.  Also enable out of order memory
          stores for this CPU, which can increase performance of some
          operations.
 
index 4f98516b9f945f208d40600dc3016b82362a8d56..91cff8dc9e1afa4018234d5aed33f122a5cd4193 100644 (file)
@@ -34,6 +34,7 @@ obj-y                         += sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT)        += srat.o
 obj-$(CONFIG_EFI)              += efi.o efi_stub.o
 obj-$(CONFIG_DOUBLEFAULT)      += doublefault.o
+obj-$(CONFIG_SERIAL_8250)      += legacy_serial.o
 obj-$(CONFIG_VM86)             += vm86.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
index aca054cc0552b61aa0ad3662a0b5dc9220dbf7e5..67824f3bb974113aab84b73c79239b1ba0283f30 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
index 367ff1d930cbac620ac30c2c11033f74a25a2787..4112afe712b9af2522cdea3728dc0b3acc5de9ca 100644 (file)
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
@@ -1173,7 +1172,7 @@ static void reinit_timer(void)
        unsigned long flags;
 
        spin_lock_irqsave(&i8253_lock, flags);
-       /* set the clock to 100 Hz */
+       /* set the clock to HZ */
        outb_p(0x34, PIT_MODE);         /* binary, mode 2, LSB/MSB, ch 0 */
        udelay(10);
        outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
index 80b4c5d421b1366915028b2002af39cdae851c95..e5be819492ef1daf5bed9ff653dfeaee6f117e24 100644 (file)
@@ -733,9 +733,11 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
        sys_dev = get_cpu_sysdev(cpu);
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cache_add_dev(sys_dev);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                cache_remove_dev(sys_dev);
                break;
        }
index 065005c3f16879c40fe82e59a53ebc8d95f240c8..7ba7c3abd3a4a74866899b7d6d6cae38f3113b93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c
+ * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c
  *
  * Thermal throttle event support code (such as syslog messaging and rate
  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
@@ -137,10 +137,12 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
        mutex_lock(&therm_cpu_lock);
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                err = thermal_throttle_add_dev(sys_dev);
                WARN_ON(err);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                thermal_throttle_remove_dev(sys_dev);
                break;
        }
index 6471a5a13202db49b8f0fbd79d355047ac008a89..200fb3f9ebfbda2ec232deec234ded94128f4cfb 100644 (file)
@@ -77,8 +77,10 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
        set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
        
        /* If we can run i686 user-space code, call us an i686 */
-#define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
-        if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 )
+#define USER686 ((1 << X86_FEATURE_TSC)|\
+                (1 << X86_FEATURE_CX8)|\
+                (1 << X86_FEATURE_CMOV))
+        if (c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686)
                c->x86 = 6;
 
 #ifdef CONFIG_SYSCTL
index eeae0d992337dd3e7c543e683adcc45233abb697..5c2faa10e9fac42f604d0af086af0618835c289d 100644 (file)
@@ -169,9 +169,11 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cpuid_device_create(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
                break;
        }
index a5e0e990ea9539eaff5c80105af16ad8335add62..53589d1b1a05ba882ef7b69bd43557970a69e742 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/smp.h>
 
 #include <mach_ipi.h>
index dd9e7faafa7c787c8a006093228b3acd118f65f2..a1808022ea19bf6a5fab059c6cff765bdde3acfb 100644 (file)
@@ -347,14 +347,12 @@ void __init efi_init(void)
                printk(KERN_ERR PFX "Woah! Couldn't map the EFI system table.\n");
        if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
                printk(KERN_ERR PFX "Woah! EFI system table signature incorrect\n");
-       if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
-               printk(KERN_ERR PFX
-                      "Warning: EFI system table major version mismatch: "
-                      "got %d.%02d, expected %d.%02d\n",
+       if ((efi.systab->hdr.revision >> 16) == 0)
+               printk(KERN_ERR PFX "Warning: EFI system table version "
+                      "%d.%02d, expected 1.00 or greater\n",
                       efi.systab->hdr.revision >> 16,
-                      efi.systab->hdr.revision & 0xffff,
-                      EFI_SYSTEM_TABLE_REVISION >> 16,
-                      EFI_SYSTEM_TABLE_REVISION & 0xffff);
+                      efi.systab->hdr.revision & 0xffff);
+
        /*
         * Grab some details from the system table
         */
index 03abfdb1a6e4c5cb8e4c7e407f0a19e3763de2df..0499cbe9871a4bb410c762f89bec6756685280fe 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
index 1b623cda3a64f97d1858842c8a888b645ee82012..7f8b7af2b95fc89f8f638c264754fc4974566cf7 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/mc146818rtc.h>
 #include <linux/compiler.h>
 #include <linux/acpi.h>
index d1e42e0dbe67da0f0984abbfcef792d771292213..3d310a946d7610479ad86cb06f740fa974b4772a 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
index b545bc746fceb2a9f6f192778c6dbca784395553..dde828a333c3e8355e49d0a3ed8d562b3071d4f9 100644 (file)
@@ -31,8 +31,8 @@
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
 #include <linux/preempt.h>
+#include <linux/kdebug.h>
 #include <asm/cacheflush.h>
-#include <asm/kdebug.h>
 #include <asm/desc.h>
 #include <asm/uaccess.h>
 
@@ -226,24 +226,15 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 }
 
 /* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
        unsigned long *sara = (unsigned long *)&regs->esp;
 
-       struct kretprobe_instance *ri;
+       ri->ret_addr = (kprobe_opcode_t *) *sara;
 
-       if ((ri = get_free_rp_inst(rp)) != NULL) {
-               ri->rp = rp;
-               ri->task = current;
-               ri->ret_addr = (kprobe_opcode_t *) *sara;
-
-               /* Replace the return addr with trampoline addr */
-               *sara = (unsigned long) &kretprobe_trampoline;
-               add_rp_inst(ri);
-       } else {
-               rp->nmissed++;
-       }
+       /* Replace the return addr with trampoline addr */
+       *sara = (unsigned long) &kretprobe_trampoline;
 }
 
 /*
@@ -449,8 +440,7 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
                        break;
        }
 
-       BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
-
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
        spin_unlock_irqrestore(&kretprobe_lock, flags);
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
@@ -753,6 +743,11 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       return 0;
+}
+
 int __init arch_init_kprobes(void)
 {
        return 0;
index b410e5fb034f285346ef41c4cc6929db3081790b..e0b2d17f4f10a879758419116a1cadae42f93a71 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 
diff --git a/arch/i386/kernel/legacy_serial.c b/arch/i386/kernel/legacy_serial.c
new file mode 100644 (file)
index 0000000..2151011
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Legacy COM port devices for x86 platforms without PNPBIOS or ACPI.
+ * Data taken from include/asm-i386/serial.h.
+ *
+ * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
+ *     Bjorn Helgaas <bjorn.helgaas@hp.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/module.h>
+#include <linux/init.h>
+#include <linux/pnp.h>
+#include <linux/serial_8250.h>
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ)
+#define COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ)
+#else
+#define COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
+#define COM4_FLAGS UPF_BOOT_AUTOCONF
+#endif
+
+#define PORT(_base,_irq,_flags)                                \
+       {                                               \
+               .iobase         = _base,                \
+               .irq            = _irq,                 \
+               .uartclk        = 1843200,              \
+               .iotype         = UPIO_PORT,            \
+               .flags          = _flags,               \
+       }
+
+static struct plat_serial8250_port x86_com_data[] = {
+       PORT(0x3F8, 4, COM_FLAGS),
+       PORT(0x2F8, 3, COM_FLAGS),
+       PORT(0x3E8, 4, COM_FLAGS),
+       PORT(0x2E8, 3, COM4_FLAGS),
+       { },
+};
+
+static struct platform_device x86_com_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = x86_com_data,
+       },
+};
+
+static int force_legacy_probe;
+module_param_named(force, force_legacy_probe, bool, 0);
+MODULE_PARM_DESC(force, "Force legacy serial port probe");
+
+static int __init serial8250_x86_com_init(void)
+{
+       if (pnp_platform_devices && !force_legacy_probe)
+               return -ENODEV;
+
+       return platform_device_register(&x86_com_device);
+}
+
+module_init(serial8250_x86_com_init);
+
+MODULE_AUTHOR("Bjorn Helgaas");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 legacy probe module");
index cbe7ec8dbb9f5311ac385ab29bd4cc9266835f5a..83f825f2e2d7db0ee5b5a002d78792219fb64b8f 100644 (file)
@@ -567,7 +567,7 @@ static int cpu_request_microcode(int cpu)
        return error;
 }
 
-static int apply_microcode_on_cpu(int cpu)
+static int apply_microcode_check_cpu(int cpu)
 {
        struct cpuinfo_x86 *c = cpu_data + cpu;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -575,8 +575,9 @@ static int apply_microcode_on_cpu(int cpu)
        unsigned int val[2];
        int err = 0;
 
+       /* Check if the microcode is available */
        if (!uci->mc)
-               return -EINVAL;
+               return 0;
 
        old = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
@@ -614,7 +615,7 @@ static int apply_microcode_on_cpu(int cpu)
        return err;
 }
 
-static void microcode_init_cpu(int cpu)
+static void microcode_init_cpu(int cpu, int resume)
 {
        cpumask_t old;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -624,8 +625,7 @@ static void microcode_init_cpu(int cpu)
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
        mutex_lock(&microcode_mutex);
        collect_cpu_info(cpu);
-       if (uci->valid && system_state == SYSTEM_RUNNING &&
-           !suspend_cpu_hotplug)
+       if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
                cpu_request_microcode(cpu);
        mutex_unlock(&microcode_mutex);
        set_cpus_allowed(current, old);
@@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = {
        .name = "microcode",
 };
 
-static int mc_sysdev_add(struct sys_device *sys_dev)
+static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
 {
        int err, cpu = sys_dev->id;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -711,39 +711,31 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
                return 0;
 
        pr_debug("Microcode:CPU %d added\n", cpu);
-       /* If suspend_cpu_hotplug is set, the system is resuming and we should
-        * use the data from before the suspend.
-        */
-       if (suspend_cpu_hotplug) {
-               err = apply_microcode_on_cpu(cpu);
-               if (err)
-                       microcode_fini_cpu(cpu);
-       }
-       if (!uci->valid)
-               memset(uci, 0, sizeof(*uci));
+       memset(uci, 0, sizeof(*uci));
 
        err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
        if (err)
                return err;
 
-       if (!uci->valid)
-               microcode_init_cpu(cpu);
+       microcode_init_cpu(cpu, resume);
 
        return 0;
 }
 
+static int mc_sysdev_add(struct sys_device *sys_dev)
+{
+       return __mc_sysdev_add(sys_dev, 0);
+}
+
 static int mc_sysdev_remove(struct sys_device *sys_dev)
 {
        int cpu = sys_dev->id;
 
        if (!cpu_online(cpu))
                return 0;
+
        pr_debug("Microcode:CPU %d removed\n", cpu);
-       /* If suspend_cpu_hotplug is set, the system is suspending and we should
-        * keep the microcode in memory for the resume.
-        */
-       if (!suspend_cpu_hotplug)
-               microcode_fini_cpu(cpu);
+       microcode_fini_cpu(cpu);
        sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
        return 0;
 }
@@ -774,13 +766,34 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 
        sys_dev = get_cpu_sysdev(cpu);
        switch (action) {
+       case CPU_UP_CANCELED_FROZEN:
+               /* The CPU refused to come up during a system resume */
+               microcode_fini_cpu(cpu);
+               break;
        case CPU_ONLINE:
        case CPU_DOWN_FAILED:
                mc_sysdev_add(sys_dev);
                break;
+       case CPU_ONLINE_FROZEN:
+               /* System-wide resume is in progress, try to apply microcode */
+               if (apply_microcode_check_cpu(cpu)) {
+                       /* The application of microcode failed */
+                       microcode_fini_cpu(cpu);
+                       __mc_sysdev_add(sys_dev, 1);
+                       break;
+               }
+       case CPU_DOWN_FAILED_FROZEN:
+               if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
+                       printk(KERN_ERR "Microcode: Failed to create the sysfs "
+                               "group for CPU%d\n", cpu);
+               break;
        case CPU_DOWN_PREPARE:
                mc_sysdev_remove(sys_dev);
                break;
+       case CPU_DOWN_PREPARE_FROZEN:
+               /* Suspend is in progress, only remove the interface */
+               sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+               break;
        }
        return NOTIFY_OK;
 }
index 0952eccd8f28feca563a8ce9eed1339f916cf245..13abb4ebfb79b3f831f8b7f5373c16d31844c2bd 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/acpi.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/bitops.h>
index bcaa6e9b6197a4466972153fb812f783f82c13a7..0c1069b8d638031571618701a6f2e09044fd4b59 100644 (file)
 
 static struct class *msr_class;
 
-static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
-{
-       int err;
-
-       err = wrmsr_safe(reg, eax, edx);
-       if (err)
-               err = -EIO;
-       return err;
-}
-
-static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
-{
-       int err;
-
-       err = rdmsr_safe(reg, eax, edx);
-       if (err)
-               err = -EIO;
-       return err;
-}
-
-#ifdef CONFIG_SMP
-
-struct msr_command {
-       int err;
-       u32 reg;
-       u32 data[2];
-};
-
-static void msr_smp_wrmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
-}
-
-static void msr_smp_rdmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
-}
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = wrmsr_eio(reg, eax, edx);
-       } else {
-               cmd.reg = reg;
-               cmd.data[0] = eax;
-               cmd.data[1] = edx;
-
-               smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1);
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = rdmsr_eio(reg, eax, edx);
-       } else {
-               cmd.reg = reg;
-
-               smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1);
-
-               *eax = cmd.data[0];
-               *edx = cmd.data[1];
-
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-#else                          /* ! CONFIG_SMP */
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       return wrmsr_eio(reg, eax, edx);
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
-{
-       return rdmsr_eio(reg, eax, edx);
-}
-
-#endif                         /* ! CONFIG_SMP */
-
 static loff_t msr_seek(struct file *file, loff_t offset, int orig)
 {
        loff_t ret = -EINVAL;
@@ -174,9 +76,9 @@ static ssize_t msr_read(struct file *file, char __user * buf,
                return -EINVAL; /* Invalid chunk size */
 
        for (; count; count -= 8) {
-               err = do_rdmsr(cpu, reg, &data[0], &data[1]);
+               err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]);
                if (err)
-                       return err;
+                       return -EIO;
                if (copy_to_user(tmp, &data, 8))
                        return -EFAULT;
                tmp += 2;
@@ -200,9 +102,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
        for (; count; count -= 8) {
                if (copy_from_user(&data, tmp, 8))
                        return -EFAULT;
-               err = do_wrmsr(cpu, reg, data[0], data[1]);
+               err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]);
                if (err)
-                       return err;
+                       return -EIO;
                tmp += 2;
        }
 
@@ -251,9 +153,11 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                msr_device_create(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
                break;
        }
index 33cf2f3c444f24aac4e321fa6cf3e4833d349b0f..fba121f7973f7583c4e5de5f7eb77439f51fc4fe 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/cpumask.h>
 #include <linux/kernel_stat.h>
+#include <linux/kdebug.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
-#include <asm/kdebug.h>
 
 #include "mach_traps.h"
 
index 3ebcea033623e357904d52195d4d52d526267636..30b754f7cbec2d827ac07b8475bb499d35257811 100644 (file)
@@ -77,7 +77,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
 {
        void __iomem *mem_base = NULL;
        int pages = size >> PAGE_SHIFT;
-       int bitmap_size = (pages + 31)/32;
+       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 
        if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
                goto out;
index 61999479b7a443734199d68d5b42b53455edd922..d76d9bc33b30c02d2aa02198270295e4cd57c681 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/elfcore.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
index 4a8f8a2597233d06316afa6463d9e1eabdd9592e..0c0ceec5de009e025c214b4c0f8af7f9d607510e 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 4f99e870c986f41b72168b3dd44fbfc1e075bbe6..d574e38f0f774e67896ad8cfbd8420faca9f9ec9 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 89a45a9ddcd4e3e7565b3275760da0806cae0c2d..93f202a855fa43e4ea3b831513015545b5287afc 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/cache.h>
index a4b7ad283f49ace7e351fbb45f4917a75157af7f..b92cc4e8b3bbd13e066757fec67a0666a298ac30 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
index 4048397f1740bdbdce7d613e244ad3e9b3094dc0..e5dcb9379018b6cda96460f8bd2856cf0365cfaf 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 2697e9210e92773a28d5b2e9ea7174433465acef..0772678ceecf376753f834753441821c83ca3d53 100644 (file)
@@ -319,3 +319,4 @@ ENTRY(sys_call_table)
        .long sys_move_pages
        .long sys_getcpu
        .long sys_epoll_pwait
+       .long sys_utimensat             /* 320 */
index f21b41e7770c6768c2118ac0449a3f5f8b15397c..c05e7e861b29404e9c226d05a33d2c712e5a13ee 100644 (file)
@@ -52,7 +52,7 @@
 #include <asm/unwind.h>
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/stacktrace.h>
 
 #include <linux/module.h>
@@ -95,20 +95,6 @@ asmlinkage void machine_check(void);
 
 int kstack_depth_to_print = 24;
 static unsigned int code_bytes = 64;
-ATOMIC_NOTIFIER_HEAD(i386die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       vmalloc_sync_all();
-       return atomic_notifier_chain_register(&i386die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&i386die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
 
 static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
 {
@@ -319,7 +305,7 @@ void show_registers(struct pt_regs *regs)
               regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
        printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
                TASK_COMM_LEN, current->comm, current->pid,
-               current_thread_info(), current, current->thread_info);
+               current_thread_info(), current, task_thread_info(current));
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
@@ -747,6 +733,11 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
                 */
                if (nmi_watchdog_tick(regs, reason))
                        return;
+#endif
+               if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0)
+                                                       == NOTIFY_STOP)
+                       return;
+#ifdef CONFIG_X86_LOCAL_APIC
                if (!do_nmi_callback(regs, smp_processor_id()))
 #endif
                        unknown_nmi_error(reason, regs);
index d1b8f2b7aea616c1902bfe616071f586c76f5bbd..f2dcd1d27c0a6341bc76925f0c0f703960f0543d 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/highmem.h>
 #include <linux/ptrace.h>
 #include <linux/audit.h>
index 1c46bda409ff1e20e7e3fd6ee569c274ec66e66b..7767962f25d34d90f35cb0b7aab64f61b1c454a6 100644 (file)
@@ -6,6 +6,7 @@
 struct msr_info {
        u32 msr_no;
        u32 l, h;
+       int err;
 };
 
 static void __rdmsr_on_cpu(void *info)
@@ -15,20 +16,38 @@ static void __rdmsr_on_cpu(void *info)
        rdmsr(rv->msr_no, rv->l, rv->h);
 }
 
-void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+static void __rdmsr_safe_on_cpu(void *info)
 {
+       struct msr_info *rv = info;
+
+       rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h);
+}
+
+static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe)
+{
+       int err = 0;
        preempt_disable();
        if (smp_processor_id() == cpu)
-               rdmsr(msr_no, *l, *h);
+               if (safe)
+                       err = rdmsr_safe(msr_no, l, h);
+               else
+                       rdmsr(msr_no, *l, *h);
        else {
                struct msr_info rv;
 
                rv.msr_no = msr_no;
-               smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1);
+               if (safe) {
+                       smp_call_function_single(cpu, __rdmsr_safe_on_cpu,
+                                                &rv, 0, 1);
+                       err = rv.err;
+               } else {
+                       smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1);
+               }
                *l = rv.l;
                *h = rv.h;
        }
        preempt_enable();
+       return err;
 }
 
 static void __wrmsr_on_cpu(void *info)
@@ -38,21 +57,63 @@ static void __wrmsr_on_cpu(void *info)
        wrmsr(rv->msr_no, rv->l, rv->h);
 }
 
-void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+static void __wrmsr_safe_on_cpu(void *info)
 {
+       struct msr_info *rv = info;
+
+       rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h);
+}
+
+static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe)
+{
+       int err = 0;
        preempt_disable();
        if (smp_processor_id() == cpu)
-               wrmsr(msr_no, l, h);
+               if (safe)
+                       err = wrmsr_safe(msr_no, l, h);
+               else
+                       wrmsr(msr_no, l, h);
        else {
                struct msr_info rv;
 
                rv.msr_no = msr_no;
                rv.l = l;
                rv.h = h;
-               smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1);
+               if (safe) {
+                       smp_call_function_single(cpu, __wrmsr_safe_on_cpu,
+                                                &rv, 0, 1);
+                       err = rv.err;
+               } else {
+                       smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1);
+               }
        }
        preempt_enable();
+       return err;
+}
+
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       _wrmsr_on_cpu(cpu, msr_no, l, h, 0);
+}
+
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       _rdmsr_on_cpu(cpu, msr_no, l, h, 0);
+}
+
+/* These "safe" variants are slower and should be used when the target MSR
+   may not actually exist. */
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       return _wrmsr_on_cpu(cpu, msr_no, l, h, 1);
+}
+
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       return _rdmsr_on_cpu(cpu, msr_no, l, h, 1);
 }
 
 EXPORT_SYMBOL(rdmsr_on_cpu);
 EXPORT_SYMBOL(wrmsr_on_cpu);
+EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+EXPORT_SYMBOL(wrmsr_safe_on_cpu);
index c7881621070630abd4b7c0c25ec28b1534c163c0..7f635c7a238160bf8aa27c389001942c27575520 100644 (file)
@@ -81,7 +81,7 @@ void __init trap_init_hook(void)
 
 static struct irqaction irq0  = {
        .handler = timer_interrupt,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
        .mask = CPU_MASK_NONE,
        .name = "timer"
 };
index a7b3999bb37a8e4ab63b8f189de86e2619ee89fb..74f3da634423e36dbcbea79f04e4d236a4802132 100644 (file)
@@ -119,9 +119,7 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 0;       
 }
 
-#ifdef CONFIG_SMP
 int hard_smp_processor_id(void)
 {
        return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
-#endif
index 233ee20907b9bdd17d86282afee90ad77716a2a6..1f81f10e03a0cd8eed4c8544d3439844eaf770e8 100644 (file)
@@ -116,7 +116,7 @@ void __init pre_setup_arch_hook()
 
 static struct irqaction irq0 = {
        .handler =      timer_interrupt,
-       .flags =        IRQF_DISABLED,
+       .flags =        IRQF_DISABLED | IRQF_IRQPOLL,
        .name =         "timer",
 };
 
index 38c2b13124d92c0861211866d40cdf7adda3146a..710faf71a650b11a991cdbc034cb21e31f0a98f1 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
index 447bb105cf58a01d2410d40a41866ae25fcb75fe..2b55694e6400c6af0896153e546d890a430e95df 100644 (file)
@@ -42,7 +42,7 @@ void __init trap_init_hook(void)
 
 static struct irqaction irq0  = {
        .handler = timer_interrupt,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
        .mask = CPU_MASK_NONE,
        .name = "timer"
 };
index 8fe7e4593d5fe7aca75b81d35bbb70863427bcb2..9b77b39b71a6dde7a2f4e17aa39af680a13e27ff 100644 (file)
@@ -292,8 +292,8 @@ machine_emergency_restart(void)
 void
 mca_nmi_hook(void)
 {
-       __u8 dumpval __attribute__((unused)) = inb(0xf823);
-       __u8 swnmi __attribute__((unused)) = inb(0xf813);
+       __u8 dumpval __maybe_unused = inb(0xf823);
+       __u8 swnmi __maybe_unused = inb(0xf813);
 
        /* FIXME: assume dump switch pressed */
        /* check to see if the dump switch was pressed */
index 1a5e448a29c76b13ab8d75e40ff08f04cc5bc93f..50d9c52070b19380eea187540de2d168661ff918 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mc146818rtc.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/bootmem.h>
index fdc1d926fb2a2dccf3ab0127b738db6997665470..b4b24e0e45e1548b12ad3be6c82cef3658723643 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/kmod.h>
index f534c29e80b265fcc03f23f0f220362b1d79979e..29d7d61543a1dec88f2e2a1c348e5a696c1e70d2 100644 (file)
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/highmem.h>
 #include <linux/bootmem.h>             /* for max_low_pfn */
+#include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/desc.h>
-#include <asm/kdebug.h>
 #include <asm/segment.h>
 
 extern void die(const char *,struct pt_regs *,long);
index 6272a4fd9e7c82777380b68956c6824c02d254e2..efdf95ac8031daf0a8c5d865575e1960890bd156 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/sysctl.h>
index 1a7197e89eb4ce5e39cbf4eb9fa8ac72dfd7697f..c50782efa5c376e9325a77ddf68603d86b29c2f5 100644 (file)
@@ -751,12 +751,9 @@ void __init pgtable_cache_init(void)
                pmd_cache = kmem_cache_create("pmd",
                                        PTRS_PER_PMD*sizeof(pmd_t),
                                        PTRS_PER_PMD*sizeof(pmd_t),
-                                       0,
+                                       SLAB_PANIC,
                                        pmd_ctor,
                                        NULL);
-               if (!pmd_cache)
-                       panic("pgtable_cache_init(): cannot create pmd cache");
-
                if (!SHARED_KERNEL_PMD) {
                        /* If we're in PAE mode and have a non-shared
                           kernel pmd, then the pgd size must be a
@@ -770,11 +767,9 @@ void __init pgtable_cache_init(void)
        pgd_cache = kmem_cache_create("pgd",
                                pgd_size,
                                pgd_size,
-                               0,
+                               SLAB_PANIC,
                                pgd_ctor,
                                (!SHARED_KERNEL_PMD) ? pgd_dtor : NULL);
-       if (!pgd_cache)
-               panic("pgtable_cache_init(): Cannot create pgd cache");
 }
 
 /*
index 695f737516aec15e9ee47d52c215bb8e24deef5e..8e185208dfd438d2a30b02fe601526689fa8f1cd 100644 (file)
 #include <linux/sysdev.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
+#include <linux/kdebug.h>
 #include <asm/nmi.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
-#include <asm/kdebug.h>
  
 #include "op_counter.h"
 #include "op_x86_model.h"
index abf0ba52a6359fd8dc12c2cae9b4137dcca8d6e7..1418e36ae7aba63e0274b45618370142ceb4b53d 100644 (file)
 #include <linux/errno.h>
 #include <linux/oprofile.h>
 #include <linux/rcupdate.h>
-
+#include <linux/kdebug.h>
 
 #include <asm/nmi.h>
 #include <asm/apic.h>
 #include <asm/ptrace.h>
-#include <asm/kdebug.h>
  
 static int profile_timer_exceptions_notify(struct notifier_block *self,
                                           unsigned long val, void *data)
index 1cf11af96de25341d919e59c83138525aa202380..3de9f9ba2da6aed8be73921f3f416ed8af444a49 100644 (file)
@@ -6,7 +6,7 @@
    in the right sequence from here. */
 static __init int pci_access_init(void)
 {
-       int type __attribute__((unused)) = 0;
+       int type __maybe_unused = 0;
 
 #ifdef CONFIG_PCI_DIRECT
        type = pci_direct_probe();
index e23af4b6ae8c173ee20b456805bd556ac86a83fb..6e41471449c034f0cd32265590608fcfe68b604c 100644 (file)
@@ -468,7 +468,7 @@ config KEXEC
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
-         but it is indepedent of the system firmware.   And like a reboot
+         but it is independent of the system firmware.   And like a reboot
          you can start any kernel with it, not just Linux.
 
          The name comes from the similiarity to the exec system call.
index 5a0a7afcfc3a0ad010ceb29ff18a8618fdc81b4d..300acd913d9c5df9d7fa8aa396a58a6b71c2e9fa 100644 (file)
@@ -287,7 +287,7 @@ sys_fw_init (const char *args, int arglen)
 
        memset(efi_systab, 0, sizeof(efi_systab));
        efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
-       efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
+       efi_systab->hdr.revision  = ((1 << 16) | 00);
        efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
        efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0");
        efi_systab->fw_revision = 1;
index a152738c7d0d33a9496b1a4bc89d14ca9ec9c78b..16d51c14684990ab32b0f0b01f282edda6e3be5f 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
index b2bb7f227920e3735df59961b5428527857b82f8..85e82f32e480c4707de98d4fcdb73e801f2ebc95 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/syscalls.h>
 #include <linux/unistd.h>
index 6af400a12ca1335ca324a0e6c388ad7ec50c8819..beea7a0b9dc6a090047fb3d550bfe79e90ed5995 100644 (file)
@@ -252,10 +252,8 @@ ia32_init (void)
                extern struct kmem_cache *partial_page_cachep;
 
                partial_page_cachep = kmem_cache_create("partial_page_cache",
-                                                       sizeof(struct partial_page), 0, 0,
-                                                       NULL, NULL);
-               if (!partial_page_cachep)
-                       panic("Cannot create partial page SLAB cache");
+                                               sizeof(struct partial_page),
+                                               0, SLAB_PANIC, NULL, NULL);
        }
 #endif
        return 0;
index 80a94e7078278dc1f244334f63a3a8368bfed789..aeb79fb28f0bbd56672ea1c4b1e33bf7f58f33ec 100644 (file)
@@ -16,8 +16,8 @@
 #include <linux/elfcore.h>
 #include <linux/sysctl.h>
 #include <linux/init.h>
+#include <linux/kdebug.h>
 
-#include <asm/kdebug.h>
 #include <asm/mca.h>
 
 int kdump_status[NR_CPUS];
@@ -74,7 +74,7 @@ crash_save_this_cpu(void)
        buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
        if (!buf)
                return;
-       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus,
+       buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, prstatus,
                        sizeof(*prstatus));
        final_note(buf);
 }
index 78d29b79947dc3223a1e9c47e7975b71a90b5862..75ec3478d8a2c3aaf593810391e1d54a992fed1d 100644 (file)
@@ -445,11 +445,11 @@ efi_init (void)
                panic("Woah! Can't find EFI system table.\n");
        if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
                panic("Woah! EFI system table signature incorrect\n");
-       if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
-               printk(KERN_WARNING "Warning: EFI system table major version mismatch: "
-                      "got %d.%02d, expected %d.%02d\n",
-                      efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff,
-                      EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff);
+       if ((efi.systab->hdr.revision >> 16) == 0)
+               printk(KERN_WARNING "Warning: EFI system table version "
+                      "%d.%02d, expected 1.00 or greater\n",
+                      efi.systab->hdr.revision >> 16,
+                      efi.systab->hdr.revision & 0xffff);
 
        config_tables = __va(efi.systab->tables);
 
index d3e9f33e8bddcc816d2a213fb7361e9b1fad7ce8..6a49600cf337f5e468e857ccce5088f12917bfe8 100644 (file)
@@ -236,9 +236,11 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb,
        sys_dev = get_cpu_sysdev(cpu);
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                err_inject_add_dev(sys_dev);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                err_inject_remove_dev(sys_dev);
                break;
        }
index e87dd93d4db71ebf3b054ba1d46a1bb8b26a46ad..37f46527d233eef451ead5c8b6adcc2b24e33ca9 100644 (file)
@@ -87,7 +87,6 @@
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/bootmem.h>
 
index 9a5f41be760ba11b933d1532d040c55cc85c740f..dce5341303dea25ecb12777058df025d4be6601b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/random.h>      /* for rand_initialize_irq() */
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/threads.h>
 #include <linux/bitops.h>
 #include <linux/irq.h>
index 6cb56dd4056d1306097714b6a825fcc01d176f25..4f5fd0960ba7c0c7e1c44e0c358edff198e947f0 100644 (file)
@@ -29,9 +29,9 @@
 #include <linux/slab.h>
 #include <linux/preempt.h>
 #include <linux/moduleloader.h>
+#include <linux/kdebug.h>
 
 #include <asm/pgtable.h>
-#include <asm/kdebug.h>
 #include <asm/sections.h>
 #include <asm/uaccess.h>
 
@@ -444,7 +444,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
                        break;
        }
 
-       BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
+
        regs->cr_iip = orig_ret_address;
 
        reset_current_kprobe();
@@ -464,23 +465,13 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 }
 
 /* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
-       struct kretprobe_instance *ri;
-
-       if ((ri = get_free_rp_inst(rp)) != NULL) {
-               ri->rp = rp;
-               ri->task = current;
-               ri->ret_addr = (kprobe_opcode_t *)regs->b0;
-
-               /* Replace the return addr with trampoline addr */
-               regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
+       ri->ret_addr = (kprobe_opcode_t *)regs->b0;
 
-               add_rp_inst(ri);
-       } else {
-               rp->nmissed++;
-       }
+       /* Replace the return addr with trampoline addr */
+       regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
 }
 
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
@@ -1021,3 +1012,12 @@ int __init arch_init_kprobes(void)
                (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip;
        return register_kprobe(&trampoline_p);
 }
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (p->addr ==
+               (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip)
+               return 1;
+
+       return 0;
+}
index 491687f84fb557d446bdfa39d9475b1ba2bcd19d..f8ae709de0b5341e48abaaf13ac1bd011dd98ee0 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
 #include <linux/timer.h>
@@ -72,9 +71,9 @@
 #include <linux/smp.h>
 #include <linux/workqueue.h>
 #include <linux/cpumask.h>
+#include <linux/kdebug.h>
 
 #include <asm/delay.h>
-#include <asm/kdebug.h>
 #include <asm/machvec.h>
 #include <asm/meminit.h>
 #include <asm/page.h>
@@ -1690,7 +1689,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
        ti->preempt_count = 1;
        ti->task = p;
        ti->cpu = cpu;
-       p->thread_info = ti;
+       p->stack = ti;
        p->state = TASK_UNINTERRUPTIBLE;
        cpu_set(cpu, p->cpus_allowed);
        INIT_LIST_HEAD(&p->tasks);
index 832cf1e647e821f8543b8682b8675c95accc9828..70b8bdbb7e6f8b49e46c4fb84f637b7cab9d2b26 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kallsyms.h>
-#include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
 #include <linux/timer.h>
index a71df9ae03976ccbba7eb5154a639e941938ca44..85829e27785c74912a04a153b163674f38549de0 100644 (file)
@@ -975,9 +975,11 @@ static int palinfo_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                create_palinfo_proc_entries(hotcpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                remove_palinfo_proc_entries(hotcpu);
                break;
        }
index abc7ad03588630ed9ade6a593a8a96cbda619918..e7191ca30b165806d1cf28a49c88ca89f99d2512 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
index d7b7d3da1ebbddd071f8ef9186be24206fda364a..d1c3ed9943e52d8ccad85553e1d1008ae7dc3629 100644 (file)
 #include <linux/personality.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/thread_info.h>
 #include <linux/unistd.h>
 #include <linux/efi.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/kdebug.h>
 
 #include <asm/cpu.h>
 #include <asm/delay.h>
 #include <asm/elf.h>
 #include <asm/ia32.h>
 #include <asm/irq.h>
-#include <asm/kdebug.h>
 #include <asm/kexec.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
index af9f8754d8474ac0b0660ca50eaa547fadeeadcc..89f6b138a62cc2c7f82f7c0fed22c7fbafcc065a 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/proc_fs.h>
 #include <linux/module.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
 
@@ -583,6 +582,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu
        struct salinfo_data *data;
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                spin_lock_irqsave(&data_saved_lock, flags);
                for (i = 0, data = salinfo_data;
                     i < ARRAY_SIZE(salinfo_data);
@@ -593,6 +593,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu
                spin_unlock_irqrestore(&data_saved_lock, flags);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                spin_lock_irqsave(&data_saved_lock, flags);
                for (i = 0, data = salinfo_data;
                     i < ARRAY_SIZE(salinfo_data);
index 034b81d62bb1eff23b559a4e9a98df5733260257..aeec8184e862535e6676b2cafae699f502fa56f0 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
index ff7df439da6da98a3ecd222600866aeade40ace5..a44792d0f3a97aadb215c60a841b21fb285aa22a 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/mm.h>
 #include <linux/notifier.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/efi.h>
 #include <linux/percpu.h>
index 2fcaa2051aa3855791899aaeceada807bb490ee3..1eda194b95595110497adb009e457f8fe5c9d116 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/shm.h>
 #include <linux/file.h>                /* doh, must come after sched.h... */
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/highuid.h>
 #include <linux/hugetlb.h>
index 39e0cd3a0884e84e1c60b279a8090e6bfb611cd0..a06667c7acc0272ba492ef7a11c99fd90046d602 100644 (file)
@@ -235,7 +235,7 @@ ia64_init_itm (void)
 
 static struct irqaction timer_irqaction = {
        .handler =      timer_interrupt,
-       .flags =        IRQF_DISABLED,
+       .flags =        IRQF_DISABLED | IRQF_IRQPOLL,
        .name =         "timer"
 };
 
index 687500ddb4b872a59676396dd04cbed4c7a214ef..94ae3c87d828c5d251d78eceff617d4dc08494e0 100644 (file)
@@ -412,9 +412,11 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
        sys_dev = get_cpu_sysdev(cpu);
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cache_add_dev(sys_dev);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                cache_remove_dev(sys_dev);
                break;
        }
index cd5189f996297bd20a80d6a7c5f82774b389bd9f..b8e0d70bf9893f21451d7baad5f6dfd033bac527 100644 (file)
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
 #include <linux/delay.h>               /* for ssleep() */
+#include <linux/kdebug.h>
 
 #include <asm/fpswa.h>
 #include <asm/ia32.h>
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
-#include <asm/kdebug.h>
 
 fpswa_interface_t *fpswa_interface;
 EXPORT_SYMBOL(fpswa_interface);
 
-ATOMIC_NOTIFIER_HEAD(ia64die_chain);
-
-int
-register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&ia64die_chain, nb);
-}
-EXPORT_SYMBOL_GPL(register_die_notifier);
-
-int
-unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&ia64die_chain, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_die_notifier);
-
 void __init
 trap_init (void)
 {
index 1e357550c776c20d7ffa7ac4a57e59baee6adfd7..fe6aa5a9f8fa94edc851c59b4d1cd9d28839cf32 100644 (file)
@@ -15,7 +15,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/tty.h>
 
 #include <asm/intrinsics.h>
index 872da7a2accddfbb22db669a7c7cc79db9b347fa..94844442812a98e31ddaf083dbb68fd74a9b0d55 100644 (file)
@@ -693,6 +693,7 @@ void __init paging_init(void)
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
 pg_data_t *arch_alloc_nodedata(int nid)
 {
        unsigned long size = compute_pernodesize(nid);
@@ -710,3 +711,4 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
        pgdat_list[update_node] = update_pgdat;
        scatter_node_data();
 }
+#endif
index 59f3ab937615fb0fbe40ae08061b3aa47a32a775..21658e02116c5a77f3694f64ba15e3856d5938c8 100644 (file)
@@ -7,15 +7,14 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/kdebug.h>
 
 extern void die (char *, struct pt_regs *, long);
 
index c7c90f4f42980d98835be1b2ed0d75bf5fd2d17d..1346b7f05397506f0384fb204d9d62f27d838d6e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <asm/mman.h>
index 9f635896d2527b86a1a84702dfa8030369511afc..3549f3b425929434fd334fd9630fc9e85ca25e68 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
 #include <asm/machvec.h>
index 68355ef6f84170096b52aee5938a390143841e10..e336e1692a734cb137734f555133a68887915e57 100644 (file)
@@ -55,9 +55,9 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/completion.h>
+#include <linux/kdebug.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
-#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 #include <asm/sn/xpc.h>
 
@@ -1332,7 +1332,7 @@ xpc_init(void)
                dev_warn(xpc_part, "can't register reboot notifier\n");
        }
 
-       /* add ourselves to the die_notifier list (i.e., ia64die_chain) */
+       /* add ourselves to the die_notifier list */
        ret = register_die_notifier(&xpc_die_notifier);
        if (ret != 0) {
                dev_warn(xpc_part, "can't register die notifier\n");
index 8cbbb0b11e0c9c66b1a8280ed95dd65b3c6fe9ee..41a4c95e06d6e75666d071b93b460d82922dcf6a 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/sched.h>
 #include <linux/in6.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 
 #include <asm/semaphore.h>
index 4b156054baa6306f0d1d5d774c3f972809951737..916faf6070af7d1a29b1c91f7a875166ccef88d1 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 48d376f47e1a471bbee2716149c4e79cda7676f2..3eb3059534972c07aeaa7935aa57d5814675e5c2 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/delay.h>
index b4e7bcb43540444d6db2f4a56855711cc56ffe02..bda85548de6c79c0dceb81279257112443b2becd 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 9880abac3f5488ffc7d5ccc1ea9f6bc2afd20604..88469178ea6bbfcd690a539c9a51e5ec02878f3f 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/vt_kern.h>              /* For unblank_screen() */
index 037d58e82fb5a06319396fbb23670f0e1e939489..f3935ba249460e56e70c43e0fde7bf805bd7d6ee 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/tty.h>
index 7fd2720c38416f422d70d695d8dc73c67ed0a7b5..cdba9fd6d82fa66013a247f0a7bfdfc126970d0e 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 272d47eac58d4f99ceced83b6de7d1258cced58c..e341387787ab8b048e14ad9575fa96e889acc611 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
-#include <linux/smp_lock.h>
 #include <linux/bcd.h>
 #include <asm/mvme16xhw.h>
 
index 763c9aa0b4fdb3c7ff4909f8f543f331cf775090..9ff47bd09aee0027362a2dbcd75194add548fab9 100644 (file)
@@ -5,7 +5,7 @@ source "lib/Kconfig.debug"
 config FULLDEBUG
        bool "Full Symbolic/Source Debugging support"
        help
-         Enable debuging symbols on kernel build.
+         Enable debugging symbols on kernel build.
 
 config HIGHPROFILE
        bool "Use fast second timer for profiling"
index b988c7bdc6e4d6fd78656b68b1e41fdea1131da0..7cd183d346ef6b06264f8f2b95a5ea154b001125 100644 (file)
@@ -31,7 +31,7 @@ int main(void)
        DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
        DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 
index 72d34962357519477ea234a93e928402a759fc82..f54b6a3dfecb1726a88e5978bd0e6d42fa1f4ddc 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 3265b2d734dbb8b9fc37659475d4863506b86015..48e6b33e8b44962d7ce6c6c5da044179c4199ec8 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 7441a2cf523ee929edbddb072a5764032422d934..16ecea3c08136540f0bb8cc685f39fd71c8d84a8 100644 (file)
@@ -784,7 +784,6 @@ config TOSHIBA_RBTX4927
        select HAS_TXX9_SERIAL
        select HW_HAS_PCI
        select I8259
-       select ISA
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_TX49XX
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -806,7 +805,6 @@ config TOSHIBA_RBTX4938
        select HAS_TXX9_SERIAL
        select HW_HAS_PCI
        select I8259
-       select ISA
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_TX49XX
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -958,7 +956,7 @@ choice
          byte order. These modes require different kernels and a different
          Linux distribution.  In general there is one preferred byteorder for a
          particular system but some systems are just as commonly used in the
-         one or the other endianess.
+         one or the other endianness.
 
 config CPU_BIG_ENDIAN
        bool "Big endian"
@@ -1752,7 +1750,7 @@ config ARCH_DISCONTIGMEM_ENABLE
        bool
        default y if SGI_IP27
        help
-         Say Y to upport efficient handling of discontiguous physical memory,
+         Say Y to support efficient handling of discontiguous physical memory,
          for architectures which are either NUMA (Non-Uniform Memory Access)
          or have huge holes in the physical address space for other reasons.
          See <file:Documentation/vm/numa> for more.
@@ -1940,7 +1938,7 @@ config KEXEC
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
-         but it is indepedent of the system firmware.   And like a reboot
+         but it is independent of the system firmware.   And like a reboot
          you can start any kernel with it, not just Linux.
 
          The name comes from the similiarity to the exec system call.
index f2f742df32c7375f887e747e8272b47d12613b2a..4892db88a86a5c84f7ecc8145c8f3b2d2b8309a5 100644 (file)
@@ -92,7 +92,7 @@ cflags-y += -ffreestanding
 # when fed the toolchain default!
 #
 # Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of
-# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL
+# 2006-10-10 don't properly change the predefined symbols if -EB / -EL
 # are used, so we kludge that here.  A bug has been filed at
 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413.
 #
index 29e0df9f4be08bd569afc4589e65454bd19ff649..7d0f2174614eb9749b5d964af7d328cf75440ae7 100644 (file)
@@ -245,7 +245,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_ISA=y
 CONFIG_MMU=y
 
 #
@@ -573,7 +572,6 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 # CONFIG_PNPACPI is not set
 
 #
@@ -658,7 +656,6 @@ CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
@@ -676,11 +673,6 @@ CONFIG_RAID_ATTRS=m
 #
 # CONFIG_ATA is not set
 
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
 #
 # Multi-device support (RAID and LVM)
 #
@@ -742,37 +734,20 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_DM9000 is not set
-# CONFIG_NET_VENDOR_RACAL is not set
 
 #
 # Tulip family network device support
 #
 # CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
-CONFIG_NET_ISA=y
-# CONFIG_E2100 is not set
-# CONFIG_EWRK3 is not set
-# CONFIG_EEXPRESS is not set
-# CONFIG_EEXPRESS_PRO is not set
-# CONFIG_HPLAN_PLUS is not set
-# CONFIG_HPLAN is not set
-# CONFIG_LP486E is not set
-# CONFIG_ETH16I is not set
 CONFIG_NE2000=y
-# CONFIG_SEEQ8005 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -833,8 +808,6 @@ CONFIG_NET_RADIO=y
 # Obsolete Wireless cards support (pre-802.11)
 #
 # CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_WAVELAN is not set
 
 #
 # Wireless 802.11b ISA/PCI cards support
@@ -920,9 +893,6 @@ CONFIG_KEYBOARD_ATKBD=y
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -1072,7 +1042,6 @@ CONFIG_FB_ATY_CT=y
 #
 CONFIG_VGA_CONSOLE=y
 # CONFIG_VGACON_SOFT_SCROLLBACK is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 
index 761a779d5c4f67a8620f6efe481f0c2829d002d1..3b27309d54b18542b51e601780c32fefa513901b 100644 (file)
@@ -82,7 +82,7 @@ void output_task_defines(void)
 {
        text("/* MIPS task_struct offsets. */");
        offset("#define TASK_STATE         ", struct task_struct, state);
-       offset("#define TASK_THREAD_INFO   ", struct task_struct, thread_info);
+       offset("#define TASK_THREAD_INFO   ", struct task_struct, stack);
        offset("#define TASK_FLAGS         ", struct task_struct, flags);
        offset("#define TASK_MM            ", struct task_struct, mm);
        offset("#define TASK_PID           ", struct task_struct, pid);
index 304efdc5682f9776578eaa1f2ba402f549a06ecc..4fa54b230c098ab39c75e07bec68cbf720d15f21 100644 (file)
@@ -33,8 +33,3 @@ void __init setup_early_printk(void)
 {
        register_console(&early_console);
 }
-
-void __init disable_early_printk(void)
-{
-       unregister_console(&early_console);
-}
index 3cc25c05d367b942a2f355cd295292b763b3a281..403d96f99e7705dc0ba9cba5d8acd51246469ea3 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
-#include <linux/smp_lock.h>
 
 #include <asm/mipsregs.h>
 #include <asm/namei.h>
index e2863821a3dd8472ba194e45367a53f076552155..30f9eb09db3ffe962b7aadb52df45db71eaacb1a 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sockios.h>
 #include <linux/syscalls.h>
 #include <linux/tty.h>
index 2132485caa744bbeddca7b4af11070b2e8c8591f..6980deb6dced2b5d165988048a06e2fcd4dd23ef 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/ptrace.h>
 #include <linux/resource.h>
index 201ae194d1b86a7b13c568a0e837d2b2cbcff8ea..b5a7b46bbc49e0f6adb676c08c9f09aee5925823 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ptrace.h>
 #include <linux/audit.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
index 07d67309451a62cc4bc4ac89c9ec520e30f45639..2a08ce41bf2bd250350f40bee2344c1f01796b7e 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/personality.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index b9a014411f83db184c8a094d88f97b8c8d64b336..003f8152b9ed7e6ea7383358872a7bab98c1b682 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/syscalls.h>
index a9202fa9598728d88852b0090d340e31fb8c284c..4cf9ff24d1f77ba4db1ed2b97bc0fa426ddf74b5 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 5dcfab6b288efbbca69046a3bc66970736d84cc8..b361edb83dc63e009e9a1a39281e9c132e946bfe 100644 (file)
@@ -560,7 +560,7 @@ void smtc_boot_secondary(int cpu, struct task_struct *idle)
        write_tc_gpr_sp(__KSTK_TOS(idle));
 
        /* global pointer */
-       write_tc_gpr_gp((unsigned long)idle->thread_info);
+       write_tc_gpr_gp((unsigned long)task_thread_info(idle));
 
        smtc_status |= SMTC_MTC_ACTIVE;
        write_tc_c0_tchalt(0);
index a586aba337a7afcbd0f93f50c36c59167face762..ebd9db8d1ecebfe7a065145df4d2c204a24ed313 100644 (file)
@@ -31,8 +31,7 @@ static void save_raw_context_stack(struct stack_trace *trace,
        }
 }
 
-static void save_context_stack(struct stack_trace *trace,
-       struct task_struct *task, struct pt_regs *regs)
+static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs)
 {
        unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
@@ -41,7 +40,7 @@ static void save_context_stack(struct stack_trace *trace,
 
        if (raw_show_trace || !__kernel_text_address(pc)) {
                unsigned long stack_page =
-                       (unsigned long)task_stack_page(task);
+                       (unsigned long)task_stack_page(current);
                if (stack_page && sp >= stack_page &&
                    sp <= stack_page + THREAD_SIZE - 32)
                        save_raw_context_stack(trace, sp);
@@ -54,7 +53,7 @@ static void save_context_stack(struct stack_trace *trace,
                        trace->entries[trace->nr_entries++] = pc;
                if (trace->nr_entries >= trace->max_entries)
                        break;
-               pc = unwind_stack(task, &sp, pc, &ra);
+               pc = unwind_stack(current, &sp, pc, &ra);
        } while (pc);
 #else
        save_raw_context_stack(trace, sp);
@@ -64,22 +63,13 @@ static void save_context_stack(struct stack_trace *trace,
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
        struct pt_regs dummyregs;
        struct pt_regs *regs = &dummyregs;
 
        WARN_ON(trace->nr_entries || !trace->max_entries);
 
-       if (task && task != current) {
-               regs->regs[29] = task->thread.reg29;
-               regs->regs[31] = 0;
-               regs->cp0_epc = task->thread.reg31;
-       } else {
-               if (!task)
-                       task = current;
-               prepare_frametrace(regs);
-       }
-
-       save_context_stack(trace, task, regs);
+       prepare_frametrace(regs);
+       save_context_stack(trace, regs);
 }
index 26e1a7e78d13dac0acac8277572c88c74c9a106a..9dd5a2df8eac344c7701b2b7dab734c30d25d770 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/linkage.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/mman.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
index 493cb29b8a4284ed13ecd8e22a8abe650cf468b4..ff45a4b8fbaaad11c28abc39a9c27c55446d9e6b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
 #include <linux/bootmem.h>
index 24b7b053cfe916fe6a073791b4e9ddbc1765c603..a7d49ae805b43636ca49311a14ab14d4c2434364 100644 (file)
@@ -76,7 +76,6 @@
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 
 #include <asm/asm.h>
 #include <asm/branch.h>
index 8079f3d1eca0be71edbc8e771fa3ec3542b742cb..ea6ba7248489598e7376768abeef38d7a0fce632 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
index f9c595dceba95fe49bc7c5e584a5346fee5e1b64..7ebea331edb805802daf6aef5679691e3a22e96e 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/module.h>
 
index 7a7444874e80341522eb1cadd0c3b2d078d7b8d2..0ad39e53f7b1a0122d185c952fa03b5c64a99c79 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pci.h>
 
 /*
- * Set the the BCM1250, etc. PCI host bridge's TRDY timeout
+ * Set the BCM1250, etc. PCI host bridge's TRDY timeout
  * to the finite max.
  */
 static void __init quirk_sb1250_pci(struct pci_dev *dev)
@@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
                        quirk_sb1250_ht);
 
 /*
- * Set the the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
+ * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
  */
 static void __init quirk_sp1011(struct pci_dev *dev)
 {
index 60ade7690e09861aafcfa0ca3f09da1eef8230a5..ba8e0794630cd2e6a35e3284f5811e270cf3ef69 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
index ad5fc471a0046b28f535f71a3b6c30cea87bf3a7..9ccffdfb82896e436e8eaf7a35be042959f5f63b 100644 (file)
@@ -42,7 +42,7 @@ static irqreturn_t sni_isa_irq_handler(int dummy, void *p)
 struct irqaction sni_isa_irq = {
        .handler = sni_isa_irq_handler,
        .name = "ISA",
-       .flags = SA_SHIRQ
+       .flags = IRQF_SHARED
 };
 
 /*
index 0f7576dfd1413ad46363b8eaa52e3c89bcf8ec62..a0c11efeaeeb9dd24658c114b5c46fa66bf26e70 100644 (file)
@@ -1049,3 +1049,22 @@ static int __init toshiba_rbtx4927_rtc_init(void)
        return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 device_initcall(toshiba_rbtx4927_rtc_init);
+
+static int __init rbtx4927_ne_init(void)
+{
+       static struct resource __initdata res[] = {
+               {
+                       .start  = RBTX4927_RTL_8019_BASE,
+                       .end    = RBTX4927_RTL_8019_BASE + 0x20 - 1,
+                       .flags  = IORESOURCE_IO,
+               }, {
+                       .start  = RBTX4927_RTL_8019_IRQ,
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+       struct platform_device *dev =
+               platform_device_register_simple("ne", -1,
+                                               res, ARRAY_SIZE(res));
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+device_initcall(rbtx4927_ne_init);
index 66163ba452c809b31a25338271a1bbed15cd4f30..f5d1ce739fcc48b6eb1442e1cf87f610a7655066 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
+#include <linux/platform_device.h>
 
 #include <asm/wbflush.h>
 #include <asm/reboot.h>
@@ -1037,3 +1038,22 @@ static int __init tx4938_spi_proc_setup(void)
 
 __initcall(tx4938_spi_proc_setup);
 #endif
+
+static int __init rbtx4938_ne_init(void)
+{
+       struct resource res[] = {
+               {
+                       .start  = RBTX4938_RTL_8019_BASE,
+                       .end    = RBTX4938_RTL_8019_BASE + 0x20 - 1,
+                       .flags  = IORESOURCE_IO,
+               }, {
+                       .start  = RBTX4938_RTL_8019_IRQ,
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+       struct platform_device *dev =
+               platform_device_register_simple("ne", -1,
+                                               res, ARRAY_SIZE(res));
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+device_initcall(rbtx4938_ne_init);
index c7a81a2c014c98657ccb52357c315a2cfa2103f0..d86e15776779e55b8110215f1fb58a1da7f860ee 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/ptrace.h>
 #include <asm/errno.h>
index b34b4f3c60ec6cf087f25b31b64e5bd448604067..dede4765852edb140c24acfc99d30d5e602554b9 100644 (file)
@@ -34,7 +34,6 @@
  */
 
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <asm/errno.h>
 #include <asm/ioctl.h>
index 54fdb959149c4236f1e0a95204c1debbb94ac305..d3b7917a87cb559e68893ad40327d0ea5346a7e9 100644 (file)
@@ -54,7 +54,7 @@
 
 int main(void)
 {
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_STATE, offsetof(struct task_struct, state));
        DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
        DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
index e9d09b020e865ca2a2c875bc76a0d81929679a72..c5c9125dacecff8d58f7f447bf83342993d7dee4 100644 (file)
@@ -388,7 +388,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
 static struct irqaction timer_action = {
        .handler = timer_interrupt,
        .name = "timer",
-       .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU,
+       .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU | IRQF_IRQPOLL,
 };
 
 #ifdef CONFIG_SMP
index 0d0d617b6f218363794a9683ae93a4dc062ff690..8a0db376e91e3e17f290b4db7ad3eddb0089789e 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 9784e405f849ba6d066383ee82e4d7718b85a1e2..fb35ebc0c4da241a5d6da6e7e3b00de10a581b81 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 1c1a37f7305332a8d069d51fd572a4de5bc971fa..db94affe5c713a4692a08c73a6ac07e0fde5f2bc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/unistd.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/syscalls.h>
index 6fed0803c59378ef038694ed2038805516899d0a..4f589216b39e2a47864ea83ca897a859e2a8f3cb 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/shm.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/utsname.h>
 #include <linux/personality.h>
index 55bc1471967d2221badf806b78aada441760f0c7..745ff741490ae122ea9be8de1f3fa91bc690457a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
index 5f75b3e65986d8b9f96a7830f92fd23bde79dffd..89c03707eccc82dcf7dcb9d2b332a275b7b74f4b 100644 (file)
@@ -216,11 +216,8 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
                /* Handle some frequent special cases.... */
                {
                        char symname[KSYM_NAME_LEN+1];
-                       char *modname;
-                       unsigned long symsize, offset;
 
-                       kallsyms_lookup(info->ip, &symsize, &offset,
-                                       &modname, symname);
+                       kallsyms_lookup(info->ip, NULL, NULL, NULL, symname);
 
                        dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
 
index 8de5f9ff4ade1e8b36793ddb2f464c6d0113dc06..ccc5410af996a5cf87a45d6e2eda9a7a97f31df6 100644 (file)
@@ -117,18 +117,8 @@ config GENERIC_BUG
        default y
        depends on BUG
 
-#
-# Powerpc uses the slab allocator to manage its ptes and the
-# page structs of ptes are used for splitting the page table
-# lock for configurations supporting more than SPLIT_PTLOCK_CPUS.
-#
-# In that special configuration the page structs of slabs are modified.
-# This setting disables the selection of SLUB as a slab allocator.
-#
-config ARCH_USES_SLAB_PAGE_STRUCT
+config SYS_SUPPORTS_APM_EMULATION
        bool
-       default y
-       depends on SPLIT_PTLOCK_CPUS <= NR_CPUS
 
 config DEFAULT_UIMAGE
        bool
@@ -136,6 +126,11 @@ config DEFAULT_UIMAGE
          Used to allow a board to specify it wants a uImage built by default
        default n
 
+config PPC64_SWSUSP
+       bool
+       depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
+       default y
+
 menu "Processor support"
 choice
        prompt "Processor Type"
@@ -206,6 +201,7 @@ config 40x
 config 44x
        bool "AMCC 44x"
        select PPC_DCR_NATIVE
+       select WANT_DEVICE_TREE
 
 config E200
        bool "Freescale e200"
@@ -270,9 +266,14 @@ config PPC_OF_PLATFORM_PCI
        depends on PPC64 # not supported on 32 bits yet
        default n
 
+config 4xx
+       bool
+       depends on 40x || 44x
+       default y
+
 config BOOKE
        bool
-       depends on E200 || E500
+       depends on E200 || E500 || 44x
        default y
 
 config FSL_BOOKE
@@ -338,6 +339,11 @@ config PPC_STD_MMU_32
        def_bool y
        depends on PPC_STD_MMU && PPC32
 
+config PPC_MM_SLICES
+       bool
+       default y if HUGETLB_PAGE
+       default n
+
 config VIRT_CPU_ACCOUNTING
        bool "Deterministic task and CPU time accounting"
        depends on PPC64
@@ -527,9 +533,15 @@ config NODES_SPAN_OTHER_NODES
        def_bool y
        depends on NEED_MULTIPLE_NODES
 
+config PPC_HAS_HASH_64K
+       bool
+       depends on PPC64
+       default n
+
 config PPC_64K_PAGES
        bool "64k page size"
        depends on PPC64
+       select PPC_HAS_HASH_64K
        help
          This option changes the kernel logical page size to 64k. On machines
          without processor support for 64k pages, the kernel will simulate
@@ -669,11 +681,12 @@ config MCA
 config PCI
        bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
                || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-               || MPC7448HPC2 || PPC_PS3
+               || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
        default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
                && !PPC_85xx && !PPC_86xx
        default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
        default PCI_QSPAN if !4xx && !CPM2 && 8xx
+       select ARCH_SUPPORTS_MSI
        help
          Find out whether your system includes a PCI bus. PCI is the name of
          a bus system, i.e. the way the CPU talks to the other stuff inside
index 86aa3745af7f65f1d1240bac863be9145eda91f2..346cd3befe1e2252bb0c132e20d3b9f33aefd8ad 100644 (file)
@@ -32,7 +32,7 @@ config HCALL_STATS
        depends on PPC_PSERIES && DEBUG_FS
        help
          Adds code to keep track of the number of hypervisor calls made and
-         the amount of time spent in hypervisor callsr.  Wall time spent in
+         the amount of time spent in hypervisor calls.  Wall time spent in
          each call is always calculated, and if available CPU cycles spent
          are also calculated.  A directory named hcall_inst is added at the
          root of the debugfs filesystem.  Within the hcall_inst directory
@@ -139,10 +139,6 @@ config BOOTX_TEXT
          Say Y here to see progress messages from the boot firmware in text
          mode. Requires either BootX or Open Firmware.
 
-config SERIAL_TEXT_DEBUG
-       bool "Support for early boot texts over serial port"
-       depends on 4xx
-
 config PPC_EARLY_DEBUG
        bool "Early debugging (dangerous)"
 
@@ -207,6 +203,24 @@ config PPC_EARLY_DEBUG_BEAT
        help
          Select this to enable early debugging for Celleb with Beat.
 
+config PPC_EARLY_DEBUG_44x
+       bool "Early serial debugging for IBM/AMCC 44x CPUs"
+       depends on 44x
+       select PPC_UDBG_16550
+       help
+         Select this to enable early debugging for IBM 44x chips via the
+         inbuilt serial port.
+
 endchoice
 
+config PPC_EARLY_DEBUG_44x_PHYSLOW
+       hex "Low 32 bits of early debug UART physical address"
+       depends PPC_EARLY_DEBUG_44x
+       default "0x40000200"
+
+config PPC_EARLY_DEBUG_44x_PHYSHIGH
+       hex "EPRN of early debug UART physical address"
+       depends PPC_EARLY_DEBUG_44x
+       default "0x1"
+
 endmenu
index 794992025d8de94222fe26e5c90592d8f2a6a42e..81a531d84ff9ab383bde8d654efbb9cc0287f368 100644 (file)
@@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
 
 CPPFLAGS_vmlinux.lds   := -Upowerpc
 
-BOOT_TARGETS = zImage zImage.initrd uImage cuImage
+BOOT_TARGETS = zImage zImage.initrd uImage
 
 PHONY += $(BOOT_TARGETS)
 
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c
new file mode 100644 (file)
index 0000000..d51377d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * Based on earlier code:
+ *   Matt Porter <mporter@kernel.crashing.org>
+ *   Copyright 2002-2005 MontaVista Software Inc.
+ *
+ *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *   Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+#include "reg.h"
+#include "dcr.h"
+
+/* Read the 44x memory controller to get size of system memory. */
+void ibm44x_fixup_memsize(void)
+{
+       int i;
+       unsigned long memsize, bank_config;
+
+       memsize = 0;
+       for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
+               mtdcr(DCRN_SDRAM0_CFGADDR, sdram_bxcr[i]);
+               bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
+
+               if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
+                       memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
+       }
+
+       dt_fixup_memory(0, memsize);
+}
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h
new file mode 100644 (file)
index 0000000..7b129ad
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * PowerPC 44x related functions
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * 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 _PPC_BOOT_44X_H_
+#define _PPC_BOOT_44X_H_
+
+void ibm44x_fixup_memsize(void);
+void ebony_init(void *mac0, void *mac1);
+
+#endif /* _PPC_BOOT_44X_H_ */
index 3716594ea33eaec75ea10b40ac1372dffbbc05e6..5c384aad1184319bdfd7eafe984972be050ad45d 100644 (file)
@@ -37,13 +37,15 @@ zlib       := inffast.c inflate.c inftrees.c
 zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
 zliblinuxheader := zlib.h zconf.h zutil.h
 
-$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
-               $(addprefix $(obj)/,$(zlibheader))
+$(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
+       $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
                ns16550.c serial.c simple_alloc.c div64.S util.S \
-               gunzip_util.c elf_util.c $(zlib) devtree.c
-src-plat := of.c cuboot-83xx.c cuboot-85xx.c
+               gunzip_util.c elf_util.c $(zlib) devtree.c \
+               44x.c ebony.c
+src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
+               cuboot-ebony.c treeboot-ebony.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -129,7 +131,14 @@ image-$(CONFIG_PPC_CELLEB)         += zImage.pseries
 image-$(CONFIG_PPC_CHRP)               += zImage.chrp
 image-$(CONFIG_PPC_EFIKA)              += zImage.chrp
 image-$(CONFIG_PPC_PMAC)               += zImage.pmac
-image-$(CONFIG_DEFAULT_UIMAGE)         += uImage cuImage
+image-$(CONFIG_PPC_HOLLY)              += zImage.holly-elf
+image-$(CONFIG_DEFAULT_UIMAGE)         += uImage
+
+ifneq ($(CONFIG_DEVICE_TREE),"")
+image-$(CONFIG_PPC_83xx)               += cuImage.83xx
+image-$(CONFIG_PPC_85xx)               += cuImage.85xx
+image-$(CONFIG_EBONY)                  += treeImage.ebony cuImage.ebony
+endif
 
 # For 32-bit powermacs, build the COFF and miboot images
 # as well as the ELF images.
@@ -138,7 +147,8 @@ image-$(CONFIG_PPC_PMAC)    += zImage.coff zImage.miboot
 endif
 
 initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
-initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y))
+initrd-y := $(patsubst zImage%, zImage.initrd%, \
+               $(patsubst treeImage%, treeImage.initrd%, $(image-y)))
 initrd-y := $(filter-out $(image-y), $(initrd-y))
 targets        += $(image-y) $(initrd-y)
 
@@ -159,18 +169,27 @@ $(obj)/zImage.ps3: vmlinux
 $(obj)/zImage.initrd.ps3: vmlinux
        @echo "  WARNING zImage.initrd.ps3 not supported (yet)"
 
+$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
+       $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
+
+$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
+       $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
+
 $(obj)/uImage: vmlinux $(wrapperbits)
        $(call if_changed,wrap,uboot)
 
-cuboot-plat-$(CONFIG_83xx) += 83xx
-cuboot-plat-$(CONFIG_85xx) += 85xx
-cuboot-plat-y += unknown-platform
-
+# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
 dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
-       ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE)
+       ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
+
+$(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
+       $(call if_changed,wrap,cuboot-$*,$(dts))
+
+$(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
+       $(call if_changed,wrap,treeboot-$*,$(dts))
 
-$(obj)/cuImage: vmlinux $(wrapperbits)
-       $(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts))
+$(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits)
+       $(call if_changed,wrap,treeboot-$*,$(dts),,$(obj)/ramdisk.image.gz)
 
 $(obj)/zImage:         $(addprefix $(obj)/, $(image-y))
        @rm -f $@; ln $< $@
@@ -181,8 +200,8 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
        sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
 
 # anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd \
-               cuImage.elf cuImage.bin.gz
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
+       treeImage.*
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c
new file mode 100644 (file)
index 0000000..4464c5f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Old U-boot compatibility for Ebony
+ *
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporatio.
+ *   Based on cuboot-83xx.c, which is:
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "44x.h"
+
+#define TARGET_44x
+#include "ppcboot.h"
+
+static bd_t bd;
+extern char _end[];
+
+BSS_STACK(4096);
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                   unsigned long r6, unsigned long r7)
+{
+       unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
+       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+       memcpy(&bd, (bd_t *)r3, sizeof(bd));
+       loader_info.initrd_addr = r4;
+       loader_info.initrd_size = r4 ? r5 : 0;
+       loader_info.cmdline = (char *)r6;
+       loader_info.cmdline_len = r7 - r6;
+
+       simple_alloc_init(_end, avail_ram, 32, 64);
+
+       ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
+}
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
new file mode 100644 (file)
index 0000000..877bc97
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _PPC_BOOT_DCR_H_
+#define _PPC_BOOT_DCR_H_
+
+#define mfdcr(rn) \
+       ({      \
+               unsigned long rval; \
+               asm volatile("mfdcr %0,%1" : "=r"(rval) : "i"(rn)); \
+               rval; \
+       })
+#define mtdcr(rn, val) \
+       asm volatile("mtdcr %0,%1" : : "i"(rn), "r"(val))
+
+/* 440GP/440GX SDRAM controller DCRs */
+#define DCRN_SDRAM0_CFGADDR                            0x010
+#define DCRN_SDRAM0_CFGDATA                            0x011
+
+#define        SDRAM0_B0CR                             0x40
+#define        SDRAM0_B1CR                             0x44
+#define        SDRAM0_B2CR                             0x48
+#define        SDRAM0_B3CR                             0x4c
+
+static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2CR, SDRAM0_B3CR };
+
+#define                        SDRAM_CONFIG_BANK_ENABLE        0x00000001
+#define                        SDRAM_CONFIG_SIZE_MASK          0x000e0000
+#define                        SDRAM_CONFIG_BANK_SIZE(reg)     \
+       (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
+
+/* 440GP Clock, PM, chip control */
+#define DCRN_CPC0_SR                                   0x0b0
+#define DCRN_CPC0_ER                                   0x0b1
+#define DCRN_CPC0_FR                                   0x0b2
+#define DCRN_CPC0_SYS0                                 0x0e0
+#define          CPC0_SYS0_TUNE                                  0xffc00000
+#define          CPC0_SYS0_FBDV_MASK                             0x003c0000
+#define          CPC0_SYS0_FWDVA_MASK                            0x00038000
+#define          CPC0_SYS0_FWDVB_MASK                            0x00007000
+#define          CPC0_SYS0_OPDV_MASK                             0x00000c00
+#define          CPC0_SYS0_EPDV_MASK                             0x00000300
+/* Helper macros to compute the actual clock divider values from the
+ * encodings in the CPC0 register */
+#define          CPC0_SYS0_FBDV(reg) \
+               ((((((reg) & CPC0_SYS0_FBDV_MASK) >> 18) - 1) & 0xf) + 1)
+#define          CPC0_SYS0_FWDVA(reg) \
+               (8 - (((reg) & CPC0_SYS0_FWDVA_MASK) >> 15))
+#define          CPC0_SYS0_FWDVB(reg) \
+               (8 - (((reg) & CPC0_SYS0_FWDVB_MASK) >> 12))
+#define          CPC0_SYS0_OPDV(reg) \
+               ((((reg) & CPC0_SYS0_OPDV_MASK) >> 10) + 1)
+#define          CPC0_SYS0_EPDV(reg) \
+               ((((reg) & CPC0_SYS0_EPDV_MASK) >> 8) + 1)
+#define          CPC0_SYS0_EXTSL                                 0x00000080
+#define          CPC0_SYS0_RW_MASK                               0x00000060
+#define          CPC0_SYS0_RL                                    0x00000010
+#define          CPC0_SYS0_ZMIISL_MASK                           0x0000000c
+#define          CPC0_SYS0_BYPASS                                0x00000002
+#define          CPC0_SYS0_NTO1                                  0x00000001
+#define DCRN_CPC0_SYS1                                 0x0e1
+#define DCRN_CPC0_CUST0                                        0x0e2
+#define DCRN_CPC0_CUST1                                        0x0e3
+#define DCRN_CPC0_STRP0                                        0x0e4
+#define DCRN_CPC0_STRP1                                        0x0e5
+#define DCRN_CPC0_STRP2                                        0x0e6
+#define DCRN_CPC0_STRP3                                        0x0e7
+#define DCRN_CPC0_GPIO                                 0x0e8
+#define DCRN_CPC0_PLB                                  0x0e9
+#define DCRN_CPC0_CR1                                  0x0ea
+#define DCRN_CPC0_CR0                                  0x0eb
+#define          CPC0_CR0_SWE                                    0x80000000
+#define          CPC0_CR0_CETE                                   0x40000000
+#define          CPC0_CR0_U1FCS                                  0x20000000
+#define          CPC0_CR0_U0DTE                                  0x10000000
+#define          CPC0_CR0_U0DRE                                  0x08000000
+#define          CPC0_CR0_U0DC                                   0x04000000
+#define          CPC0_CR0_U1DTE                                  0x02000000
+#define          CPC0_CR0_U1DRE                                  0x01000000
+#define          CPC0_CR0_U1DC                                   0x00800000
+#define          CPC0_CR0_U0EC                                   0x00400000
+#define          CPC0_CR0_U1EC                                   0x00200000
+#define          CPC0_CR0_UDIV_MASK                              0x001f0000
+#define          CPC0_CR0_UDIV(reg) \
+               ((((reg) & CPC0_CR0_UDIV_MASK) >> 16) + 1)
+#define DCRN_CPC0_MIRQ0                                        0x0ec
+#define DCRN_CPC0_MIRQ1                                        0x0ed
+#define DCRN_CPC0_JTAGID                               0x0ef
+
+#endif /* _PPC_BOOT_DCR_H_ */
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
new file mode 100644 (file)
index 0000000..b679186
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Device Tree Source for IBM Ebony
+ *
+ * Copyright (c) 2006, 2007 IBM Corp.
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>, David Gibson <dwg@au1.ibm.com>
+ *
+ * FIXME: Draft only!
+ *
+ * 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.
+ *
+ * To build:
+ *   dtc -I dts -O asm -o ebony.S -b 0 ebony.dts
+ *   dtc -I dts -O dtb -o ebony.dtb -b 0 ebony.dts
+ */
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       model = "ibm,ebony";
+       compatible = "ibm,ebony";
+       dcr-parent = <&/cpus/PowerPC,440GP@0>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,440GP@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       clock-frequency = <0>; // Filled in by zImage
+                       timebase-frequency = <0>; // Filled in by zImage
+                       i-cache-line-size = <32>;
+                       d-cache-line-size = <32>;
+                       i-cache-size = <0>;
+                       d-cache-size = <0>;
+                       dcr-controller;
+                       dcr-access-method = "native";
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0 0 0>; // Filled in by zImage
+       };
+
+       UIC0: interrupt-controller0 {
+               device_type = "ibm,uic";
+               compatible = "ibm,uic-440gp", "ibm,uic";
+               interrupt-controller;
+               cell-index = <0>;
+               dcr-reg = <0c0 009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+
+       };
+
+       UIC1: interrupt-controller1 {
+               device_type = "ibm,uic";
+               compatible = "ibm,uic-440gp", "ibm,uic";
+               interrupt-controller;
+               cell-index = <1>;
+               dcr-reg = <0d0 009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <1e 4 1f 4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       CPC0: cpc {
+               device_type = "ibm,cpc";
+               compatible = "ibm,cpc-440gp";
+               dcr-reg = <0b0 003 0e0 010>;
+               // FIXME: anything else?
+       };
+
+       plb {
+               device_type = "ibm,plb";
+               compatible = "ibm,plb-440gp", "ibm,plb4";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges;
+               clock-frequency = <0>; // Filled in by zImage
+
+               SDRAM0: sdram {
+                       device_type = "memory-controller";
+                       compatible = "ibm,sdram-440gp", "ibm,sdram";
+                       dcr-reg = <010 2>;
+                       // FIXME: anything else?
+               };
+
+               DMA0: dma {
+                       // FIXME: ???
+                       device_type = "ibm,dma-4xx";
+                       compatible = "ibm,dma-440gp", "ibm,dma-4xx";
+                       dcr-reg = <100 027>;
+               };
+
+               MAL0: mcmal {
+                       device_type = "mcmal-dma";
+                       compatible = "ibm,mcmal-440gp", "ibm,mcmal";
+                       dcr-reg = <180 62>;
+                       num-tx-chans = <4>;
+                       num-rx-chans = <4>;
+                       interrupt-parent = <&MAL0>;
+                       interrupts = <0 1 2 3 4>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
+                                        /*RXEOB*/ 1 &UIC0 b 4
+                                        /*SERR*/  2 &UIC1 0 4
+                                        /*TXDE*/  3 &UIC1 1 4
+                                        /*RXDE*/  4 &UIC1 2 4>;
+                       interrupt-map-mask = <ffffffff>;
+               };
+
+               POB0: opb {
+                       device_type = "ibm,opb";
+                       compatible = "ibm,opb-440gp", "ibm,opb";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       /* Wish there was a nicer way of specifying a full 32-bit
+                          range */
+                       ranges = <00000000 1 00000000 80000000
+                                 80000000 1 80000000 80000000>;
+                       dcr-reg = <090 00b>;
+                       interrupt-parent = <&UIC1>;
+                       interrupts = <7 4>;
+                       clock-frequency = <0>; // Filled in by zImage
+
+                       EBC0: ebc {
+                               device_type = "ibm,ebc";
+                               compatible = "ibm,ebc-440gp";
+                               dcr-reg = <012 2>;
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               clock-frequency = <0>; // Filled in by zImage
+                               ranges = <0 00000000 fff00000 100000
+                                         1 00000000 48000000 100000
+                                         2 00000000 ff800000 400000
+                                         3 00000000 48200000 100000
+                                         7 00000000 48300000 100000>;
+                               interrupts = <5 4>;
+                               interrupt-parent = <&UIC1>;
+
+                               small-flash@0,0 {
+                                       device_type = "rom";
+                                       compatible = "direct-mapped";
+                                       probe-type = "JEDEC";
+                                       bank-width = <1>;
+                                       partitions = <0 80000>;
+                                       partition-names = "OpenBIOS";
+                                       reg = <0 80000 80000>;
+                               };
+
+                               ds1743@1,0 {
+                                       /* NVRAM & RTC */
+                                       device_type = "nvram";
+                                       compatible = "ds1743";
+                                       reg = <1 0 2000>;
+                               };
+
+                               large-flash@2,0 {
+                                       device_type = "rom";
+                                       compatible = "direct-mapped";
+                                       probe-type = "JEDEC";
+                                       bank-width = <1>;
+                                       partitions = <0 380000
+                                                     280000 80000>;
+                                       partition-names = "fs", "firmware";
+                                       reg = <2 0 400000>;
+                               };
+
+                               ir@3,0 {
+                                       reg = <3 0 10>;
+                               };
+
+                               fpga@7,0 {
+                                       compatible = "Ebony-FPGA";
+                                       reg = <7 0 10>;
+                               };
+                       };
+
+                       UART0: serial@40000200 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <40000200 8>;
+                               virtual-reg = <e0000200>;
+                               clock-frequency = <A8C000>;
+                               current-speed = <2580>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0 4>;
+                       };
+
+                       UART1: serial@40000300 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <40000300 8>;
+                               virtual-reg = <e0000300>;
+                               clock-frequency = <A8C000>;
+                               current-speed = <2580>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <1 4>;
+                       };
+
+                       IIC0: i2c@40000400 {
+                               /* FIXME */
+                               device_type = "i2c";
+                               compatible = "ibm,iic-440gp", "ibm,iic";
+                               reg = <40000400 14>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <2 4>;
+                       };
+                       IIC1: i2c@40000500 {
+                               /* FIXME */
+                               device_type = "i2c";
+                               compatible = "ibm,iic-440gp", "ibm,iic";
+                               reg = <40000500 14>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <3 4>;
+                       };
+
+                       GPIO0: gpio@40000700 {
+                               /* FIXME */
+                               device_type = "gpio";
+                               compatible = "ibm,gpio-440gp";
+                               reg = <40000700 20>;
+                       };
+
+                       ZMII0: emac-zmii@40000780 {
+                               device_type = "emac-zmii";
+                               compatible = "ibm,zmii-440gp", "ibm,zmii";
+                               reg = <40000780 c>;
+                       };
+
+                       EMAC0: ethernet@40000800 {
+                               linux,network-index = <0>;
+                               device_type = "network";
+                               compatible = "ibm,emac-440gp", "ibm,emac";
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <1c 4 1d 4>;
+                               reg = <40000800 70>;
+                               local-mac-address = [000000000000]; // Filled in by zImage
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <0 1>;
+                               mal-rx-channel = <0>;
+                               cell-index = <0>;
+                               max-frame-size = <5dc>;
+                               rx-fifo-size = <1000>;
+                               tx-fifo-size = <800>;
+                               phy-mode = "rmii";
+                               phy-map = <00000001>;
+                               zmii-device = <&ZMII0>;
+                               zmii-channel = <0>;
+                       };
+                       EMAC1: ethernet@40000900 {
+                               linux,network-index = <1>;
+                               device_type = "network";
+                               compatible = "ibm,emac-440gp", "ibm,emac";
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <1e 4 1f 4>;
+                               reg = <40000900 70>;
+                               local-mac-address = [000000000000]; // Filled in by zImage
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <2 3>;
+                               mal-rx-channel = <1>;
+                               cell-index = <1>;
+                               max-frame-size = <5dc>;
+                               rx-fifo-size = <1000>;
+                               tx-fifo-size = <800>;
+                               phy-mode = "rmii";
+                               phy-map = <00000001>;
+                               zmii-device = <&ZMII0>;
+                               zmii-channel = <1>;
+                       };
+
+
+                       GPT0: gpt@40000a00 {
+                               /* FIXME */
+                               reg = <40000a00 d4>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <12 4 13 4 14 4 15 4 16 4>;
+                       };
+
+               };
+
+               PCIX0: pci@1234 {
+                       device_type = "pci";
+                       /* FIXME */
+                       reg = <2 0ec00000 8
+                              2 0ec80000 f0
+                              2 0ec80100 fc>;
+               };
+       };
+
+       chosen {
+               linux,stdout-path = "/plb/opb/serial@40000200";
+//             linux,initrd-start = <0>; /* FIXME */
+//             linux,initrd-end = <0>;
+//             bootargs = "";
+       };
+};
+
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts
new file mode 100644 (file)
index 0000000..254499b
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Device Tree Source for IBM Holly (PPC 750CL with TSI controller)
+ * Copyright 2007, IBM Corporation
+ *
+ * Stephen Winiecki <stevewin@us.ibm.com>
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ *
+ * To build:
+ *   dtc -I dts -O asm -o holly.S -b 0 holly.dts
+ *   dtc -I dts -O dtb -o holly.dtb -b 0 holly.dts
+ */
+
+/ {
+       model = "41K7339";
+       compatible = "ibm,holly";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells =<0>;
+               PowerPC,750CL@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;
+                       i-cache-line-size = <20>;
+                       d-cache-size = <8000>;
+                       i-cache-size = <8000>;
+                       d-cache-sets = <80>;
+                       i-cache-sets = <80>;
+                       timebase-frequency = <2faf080>;
+                       clock-frequency = <23c34600>;
+                       bus-frequency = <bebc200>;
+                       32-bit;
+               };
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <00000000 20000000>;
+       };
+
+       tsi109@c0000000 {
+               device_type = "tsi-bridge";
+               compatible = "tsi-bridge";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <00000000 c0000000 00010000>;
+               reg = <c0000000 00010000>;
+
+               i2c@7000 {
+                       device_type = "i2c";
+                       compatible  = "tsi-i2c";
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <e 2>;
+                       reg = <7000 400>;
+               };
+
+               mdio@6000 {
+                       device_type = "mdio";
+                       compatible = "tsi-ethernet";
+
+                       PHY1: ethernet-phy@6000 {
+                               device_type = "ethernet-phy";
+                               compatible = "bcm54xx";
+                               reg = <6000 50>;
+                               phy-id = <1>;
+                       };
+
+                       PHY2: ethernet-phy@6400 {
+                               device_type = "ethernet-phy";
+                               compatible = "bcm54xx";
+                               reg = <6000 50>;
+                               phy-id = <2>;
+                       };
+               };
+
+               ethernet@6200 {
+                       device_type = "network";
+                       compatible = "tsi-ethernet";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <6000 200>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <10 2>;
+                       phy-handle = <&PHY1>;
+               };
+
+               ethernet@6600 {
+                       device_type = "network";
+                       compatible = "tsi-ethernet";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <6400 200>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <11 2>;
+                       phy-handle = <&PHY2>;
+               };
+
+               serial@7808 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <7808 200>;
+                       virtual-reg = <c0007808>;
+                       clock-frequency = <3F9C6000>;
+                       current-speed = <1c200>;
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <c 2>;
+               };
+
+               serial@7c08 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <7c08 200>;
+                       virtual-reg = <c0007c08>;
+                       clock-frequency = <3F9C6000>;
+                       current-speed = <1c200>;
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <d 2>;
+               };
+
+               MPIC: pic@7400 {
+                       device_type = "open-pic";
+                       compatible = "chrp,open-pic";
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       reg = <7400 400>;
+                       big-endian;
+               };
+
+               pci@1000 {
+                       device_type = "pci";
+                       compatible = "tsi109";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <1000 1000>;
+                       bus-range = <0 0>;
+                       /*----------------------------------------------------+
+                       | PCI memory range.
+                       | 01 denotes I/O space
+                       | 02 denotes 32-bit memory space
+                       +----------------------------------------------------*/
+                       ranges = <02000000 0 40000000 40000000 0 10000000
+                                 01000000 0 00000000 7e000000 0 00010000>;
+                       clock-frequency = <7f28154>;
+                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <17 2>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       /*----------------------------------------------------+
+                       | The INTA, INTB, INTC, INTD are shared.
+                       +----------------------------------------------------*/
+                       interrupt-map = <
+                               0800 0 0 1 &RT0 24 0
+                               0800 0 0 2 &RT0 25 0
+                               0800 0 0 3 &RT0 26 0
+                               0800 0 0 4 &RT0 27 0
+
+                               1000 0 0 1 &RT0 25 0
+                               1000 0 0 2 &RT0 26 0
+                               1000 0 0 3 &RT0 27 0
+                               1000 0 0 4 &RT0 24 0
+
+                               1800 0 0 1 &RT0 26 0
+                               1800 0 0 2 &RT0 27 0
+                               1800 0 0 3 &RT0 24 0
+                               1800 0 0 4 &RT0 25 0
+
+                               2000 0 0 1 &RT0 27 0
+                               2000 0 0 2 &RT0 24 0
+                               2000 0 0 3 &RT0 25 0
+                               2000 0 0 4 &RT0 26 0
+                               >;
+
+                       RT0: router@1180 {
+                               device_type = "pic-router";
+                               interrupt-controller;
+                               big-endian;
+                               clock-frequency = <0>;
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               interrupts = <17 2>;
+                               interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       };
+               };
+       };
+
+       chosen {
+               linux,stdout-path = "/tsi109@c0000000/serial@7808";
+               bootargs = "console=ttyS0,115200";
+       };
+};
index ba54c6b40a09dfe613fee0be2333aa3b2b7501da..e13ac6ef05a93d7744d9e4c121dc90170793f284 100644 (file)
@@ -48,6 +48,7 @@
 
        soc5200@f0000000 {
                model = "fsl,mpc5200";
+               compatible = "mpc5200";
                revision = ""                   // from bootloader
                #interrupt-cells = <3>;
                device_type = "soc";
                        device_type = "mscan";
                        compatible = "mpc5200-mscan";
                        cell-index = <1>;
-                       interrupts = <1 12 0>;
+                       interrupts = <2 12 0>;
                        interrupt-parent = <500>;
                        reg = <980 80>;
                };
                        interrupt-parent = <500>;
                };
 
-               gpio-wkup@b00 {
+               gpio-wkup@c00 {
                        compatible = "mpc5200-gpio-wkup";
                        reg = <c00 40>;
                        interrupts = <1 8 0 0 3 0>;
 
                i2c@3d00 {
                        device_type = "i2c";
-                       compatible = "mpc5200-i2c";
+                       compatible = "mpc5200-i2c\0fsl-i2c";
                        cell-index = <0>;
                        reg = <3d00 40>;
                        interrupts = <2 f 0>;
                        interrupt-parent = <500>;
+                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        device_type = "i2c";
-                       compatible = "mpc5200-i2c";
+                       compatible = "mpc5200-i2c\0fsl-i2c";
                        cell-index = <1>;
                        reg = <3d40 40>;
                        interrupts = <2 10 0>;
                        interrupt-parent = <500>;
+                       fsl5200-clocking;
                };
                sram@8000 {
                        device_type = "sram";
index 2e003081b0d3be1c37469933ef22b627afb92e11..00211b39a342bd283557baaa336a7ea47966f531 100644 (file)
@@ -48,6 +48,7 @@
 
        soc5200@f0000000 {
                model = "fsl,mpc5200b";
+               compatible = "mpc5200";
                revision = "";                  // from bootloader
                #interrupt-cells = <3>;
                device_type = "soc";
                        device_type = "mscan";
                        compatible = "mpc5200b-mscan\0mpc5200-mscan";
                        cell-index = <1>;
-                       interrupts = <1 12 0>;
+                       interrupts = <2 12 0>;
                        interrupt-parent = <500>;
                        reg = <980 80>;
                };
                        interrupt-parent = <500>;
                };
 
-               gpio-wkup@b00 {
+               gpio-wkup@c00 {
                        compatible = "mpc5200b-gpio-wkup\0mpc5200-gpio-wkup";
                        reg = <c00 40>;
                        interrupts = <1 8 0 0 3 0>;
 
                i2c@3d00 {
                        device_type = "i2c";
-                       compatible = "mpc5200b-i2c\0mpc5200-i2c";
+                       compatible = "mpc5200b-i2c\0mpc5200-i2c\0fsl-i2c";
                        cell-index = <0>;
                        reg = <3d00 40>;
                        interrupts = <2 f 0>;
                        interrupt-parent = <500>;
+                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        device_type = "i2c";
-                       compatible = "mpc5200b-i2c\0mpc5200-i2c";
+                       compatible = "mpc5200b-i2c\0mpc5200-i2c\0fsl-i2c";
                        cell-index = <1>;
                        reg = <3d40 40>;
                        interrupts = <2 10 0>;
                        interrupt-parent = <500>;
+                       fsl5200-clocking;
                };
                sram@8000 {
                        device_type = "sram";
index c798491f4cd0396f10102b96a1bc62614f8411e3..93b76069601049e58319b1ce3e08234263f9c6d8 100644 (file)
                                interrupts = <11 8>;
                                reg = <3>;
                                device_type = "ethernet-phy";
-                               interface = <3>; //ENET_100_MII
                        };
                        phy4: ethernet-phy@04 {
                                interrupt-parent = < &ipic >;
                                interrupts = <12 8>;
                                reg = <4>;
                                device_type = "ethernet-phy";
-                               interface = <3>;
                        };
                };
 
index b55bced1593d845d62c238312f0cee0e8be16ecf..be4c35784e490c8830e85a8900a831e5b121f7fc 100644 (file)
                                interrupts = <0>;
                                reg = <0>;
                                device_type = "ethernet-phy";
-                               interface = <3>; //ENET_100_MII
                        };
                        phy04:ethernet-phy@04 {
                                interrupt-parent = <&pic>;
                                interrupts = <0>;
                                reg = <4>;
                                device_type = "ethernet-phy";
-                               interface = <3>;
                        };
                };
 
index 7f578eb5708280d0159ae62c9807861a530a61a7..38c8594df3a4fd372e5d20e89792859e766f7a44 100644 (file)
                        rx-clock = <0>;
                        tx-clock = <19>;
                        phy-handle = < &phy0 >;
+                       phy-connection-type = "rgmii-id";
                        pio-handle = < &pio1 >;
                };
 
                        rx-clock = <0>;
                        tx-clock = <14>;
                        phy-handle = < &phy1 >;
+                       phy-connection-type = "rgmii-id";
                        pio-handle = < &pio2 >;
                };
 
                                interrupts = <11 8>;
                                reg = <0>;
                                device_type = "ethernet-phy";
-                               interface = <6>; //ENET_1000_GMII
                        };
                        phy1: ethernet-phy@01 {
                                interrupt-parent = < &ipic >;
                                interrupts = <12 8>;
                                reg = <1>;
                                device_type = "ethernet-phy";
-                               interface = <6>;
                        };
                };
 
index 7361b36749cb3383666630c2877ddab86291172d..948a3b61bd4a2a234561424ddee93245c331b396 100644 (file)
                        rx-clock = <0>;
                        tx-clock = <19>;
                        phy-handle = <&qe_phy0>;
+                       phy-connection-type = "gmii";
                        pio-handle = <&pio1>;
                };
 
                        rx-clock = <0>;
                        tx-clock = <14>;
                        phy-handle = <&qe_phy1>;
+                       phy-connection-type = "gmii";
                        pio-handle = <&pio2>;
                };
 
                                interrupts = <31 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
-                               interface = <6>; //ENET_1000_GMII
                        };
                        qe_phy1: ethernet-phy@01 {
                                interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
-                               interface = <6>;
                        };
                        qe_phy2: ethernet-phy@02 {
                                interrupt-parent = <&mpic>;
                                interrupts = <31 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
-                               interface = <6>; //ENET_1000_GMII
                        };
                        qe_phy3: ethernet-phy@03 {
                                interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
-                               interface = <6>; //ENET_1000_GMII
                        };
                };
 
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
new file mode 100644 (file)
index 0000000..b1251ee
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * Based on earlier code:
+ *   Copyright (C) Paul Mackerras 1997.
+ *
+ *   Matt Porter <mporter@kernel.crashing.org>
+ *   Copyright 2002-2005 MontaVista Software Inc.
+ *
+ *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *   Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+#include "reg.h"
+#include "dcr.h"
+#include "44x.h"
+
+extern char _dtb_start[];
+extern char _dtb_end[];
+
+static u8 *ebony_mac0, *ebony_mac1;
+
+/* Calculate 440GP clocks */
+void ibm440gp_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
+{
+       u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
+       u32 cr0 = mfdcr(DCRN_CPC0_CR0);
+       u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
+       u32 opdv = CPC0_SYS0_OPDV(sys0);
+       u32 epdv = CPC0_SYS0_EPDV(sys0);
+
+       if (sys0 & CPC0_SYS0_BYPASS) {
+               /* Bypass system PLL */
+               cpu = plb = sysclk;
+       } else {
+               if (sys0 & CPC0_SYS0_EXTSL)
+                       /* PerClk */
+                       m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
+               else
+                       /* CPU clock */
+                       m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
+               cpu = sysclk * m / CPC0_SYS0_FWDVA(sys0);
+               plb = sysclk * m / CPC0_SYS0_FWDVB(sys0);
+       }
+
+       opb = plb / opdv;
+       ebc = opb / epdv;
+
+       /* FIXME: Check if this is for all 440GP, or just Ebony */
+       if ((mfpvr() & 0xf0000fff) == 0x40000440)
+               /* Rev. B 440GP, use external system clock */
+               tb = sysclk;
+       else
+               /* Rev. C 440GP, errata force us to use internal clock */
+               tb = cpu;
+
+       if (cr0 & CPC0_CR0_U0EC)
+               /* External UART clock */
+               uart0 = ser_clk;
+       else
+               /* Internal UART clock */
+               uart0 = plb / CPC0_CR0_UDIV(cr0);
+
+       if (cr0 & CPC0_CR0_U1EC)
+               /* External UART clock */
+               uart1 = ser_clk;
+       else
+               /* Internal UART clock */
+               uart1 = plb / CPC0_CR0_UDIV(cr0);
+
+       printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
+              (sysclk + 500000) / 1000000, sysclk);
+
+       dt_fixup_cpu_clocks(cpu, tb, 0);
+
+       dt_fixup_clock("/plb", plb);
+       dt_fixup_clock("/plb/opb", opb);
+       dt_fixup_clock("/plb/opb/ebc", ebc);
+       dt_fixup_clock("/plb/opb/serial@40000200", uart0);
+       dt_fixup_clock("/plb/opb/serial@40000300", uart1);
+}
+
+static void ebony_fixups(void)
+{
+       // FIXME: sysclk should be derived by reading the FPGA registers
+       unsigned long sysclk = 33000000;
+
+       ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
+       ibm44x_fixup_memsize();
+       dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
+}
+
+#define SPRN_DBCR0             0x134
+#define   DBCR0_RST_SYSTEM     0x30000000
+
+static void ebony_exit(void)
+{
+       unsigned long tmp;
+
+       asm volatile (
+               "mfspr  %0,%1\n"
+               "oris   %0,%0,%2@h\n"
+               "mtspr  %1,%0"
+               : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+               );
+
+}
+
+void ebony_init(void *mac0, void *mac1)
+{
+       platform_ops.fixups = ebony_fixups;
+       platform_ops.exit = ebony_exit;
+       ebony_mac0 = mac0;
+       ebony_mac1 = mac1;
+       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+       serial_console_init();
+}
diff --git a/arch/powerpc/boot/holly.c b/arch/powerpc/boot/holly.c
new file mode 100644 (file)
index 0000000..7d6539f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007 IBM Corporation
+ *
+ * Stephen Winiecki <stevewin@us.ibm.com>
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * Based on earlier code:
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+#include "io.h"
+
+extern char _start[];
+extern char _end[];
+extern char _dtb_start[];
+extern char _dtb_end[];
+
+BSS_STACK(4096);
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
+{
+       u32 heapsize = 0x8000000 - (u32)_end; /* 128M */
+
+       simple_alloc_init(_end, heapsize, 32, 64);
+       ft_init(_dtb_start, 0, 4);
+       serial_console_init();
+}
index 4cb89299365163df4e777610129aee67226dbc8f..45d06a8c7cd1aeb128bce26d04645243278b8cc6 100644 (file)
@@ -46,8 +46,8 @@ int main(int argc, char *argv[])
        struct  stat    st;
        boot_block_t    bt;
 
-       if (argc < 3) {
-               fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
+       if (argc < 5) {
+               fprintf(stderr, "usage: %s <zImage-file> <boot-image> <load address> <entry point>\n",argv[0]);
                exit(1);
        }
 
@@ -61,10 +61,8 @@ int main(int argc, char *argv[])
        bt.bb_magic = htonl(0x0052504F);
 
        /* If we have the optional entry point parameter, use it */
-       if (argc == 4)
-               bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
-       else
-               bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
+       bt.bb_dest = htonl(strtoul(argv[3], NULL, 0));
+       bt.bb_entry_point = htonl(strtoul(argv[4], NULL, 0));
 
        /* We know these from the linker command.
         * ...and then move it up into memory a little more so the
diff --git a/arch/powerpc/boot/treeboot-ebony.c b/arch/powerpc/boot/treeboot-ebony.c
new file mode 100644 (file)
index 0000000..8436a9c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Old U-boot compatibility for Ebony
+ *
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporatio.
+ *   Based on cuboot-83xx.c, which is:
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "44x.h"
+
+extern char _end[];
+
+BSS_STACK(4096);
+
+#define OPENBIOS_MAC_BASE      0xfffffe0c
+#define OPENBIOS_MAC_OFFSET    0xc
+
+void platform_init(void)
+{
+       unsigned long end_of_ram = 0x8000000;
+       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+       simple_alloc_init(_end, avail_ram, 32, 64);
+       ebony_init((u8 *)OPENBIOS_MAC_BASE,
+                  (u8 *)(OPENBIOS_MAC_BASE + OPENBIOS_MAC_OFFSET));
+}
index 5cedd901201f82552bcc27299be1ac4057069786..2ed8b8b3f0ec0f10c1764017969b622c71718ba3 100755 (executable)
@@ -163,20 +163,19 @@ fi
 
 vmz="$vmz$gzip"
 
-case "$platform" in
-uboot|cuboot*)
-    version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
-       cut -d' ' -f3`
-    if [ -n "$version" ]; then
-       version="-n Linux-$version"
-    fi
-esac
+# Extract kernel version information, some platforms want to include
+# it in the image header
+version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
+    cut -d' ' -f3`
+if [ -n "$version" ]; then
+    uboot_version="-n Linux-$version"
+fi
 
 case "$platform" in
 uboot)
     rm -f "$ofile"
     mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
-       $version -d "$vmz" "$ofile"
+       $uboot_version -d "$vmz" "$ofile"
     if [ -z "$cacheit" ]; then
        rm -f "$vmz"
     fi
@@ -212,25 +211,32 @@ if [ "$platform" != "miboot" ]; then
     rm $tmp
 fi
 
+# Some platforms need the zImage's entry point and base address
+base=0x`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
+entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | cut -d' ' -f3`
+
 # post-processing needed for some platforms
 case "$platform" in
 pseries|chrp)
     $object/addnote "$ofile"
     ;;
 pmaccoff)
-    entry=`objdump -f "$ofile" | grep '^start address ' | \
-       cut -d' ' -f3`
     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
     $object/hack-coff "$ofile"
     ;;
 cuboot*)
-    base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
-    entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \
-           cut -d' ' -f3`
     mv "$ofile" "$ofile".elf
     ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin
     gzip -f -9 "$ofile".bin
     mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
-            $version -d "$ofile".bin.gz "$ofile"
+            $uboot_version -d "$ofile".bin.gz "$ofile"
+    ;;
+treeboot*)
+    mv "$ofile" "$ofile.elf"
+    $object/mktree "$ofile.elf" "$ofile" "$base" "$entry"
+    if [ -z "$cacheit" ]; then
+       rm -f "$ofile.elf"
+    fi
+    exit 0
     ;;
 esac
diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
new file mode 100644 (file)
index 0000000..c3b96ef
--- /dev/null
@@ -0,0 +1,905 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21
+# Fri May  4 13:47:08 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_E200 is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_4xx=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_EBONY=y
+CONFIG_440GP=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="ebony.dts"
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Networking
+#
+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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=35000
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP 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
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+# CONFIG_UCC_FAST is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
new file mode 100644 (file)
index 0000000..be633b9
--- /dev/null
@@ -0,0 +1,1070 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21
+# Sat May  5 11:02:35 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_APUS is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_LINKSTATION is not set
+# CONFIG_MPC7448HPC2 is not set
+CONFIG_PPC_HOLLY=y
+CONFIG_TSI108_BRIDGE=y
+CONFIG_MPIC=y
+CONFIG_MPIC_WEIRD=y
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_CPM2 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_TSI108_ETH=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+# CONFIG_UCC_FAST is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
index e1b36de6b38c49f7cb7880ab51594b0ead71d6dc..83192c0dc5bb0d8cf4ecbf454538c96ca7c11094 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Tue Jan 30 14:27:25 2007
+# Linux kernel version: 2.6.21-rc5
+# Mon Apr  9 16:09:16 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_83xx=y
@@ -63,6 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -71,6 +72,7 @@ CONFIG_SYSVIPC=y
 # CONFIG_IKCONFIG is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -123,16 +125,17 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_QUICC_ENGINE=y
-CONFIG_PPC_GEN550=y
 # CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_MPC8313_RDB is not set
 CONFIG_MPC832x_MDS=y
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
 # CONFIG_MPC834x_ITX is not set
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_MPIC is not set
 
@@ -163,6 +166,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
@@ -172,6 +176,7 @@ CONFIG_ISA_DMA_API=y
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
 # CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
@@ -220,6 +225,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -324,6 +330,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -342,7 +349,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -482,7 +488,21 @@ CONFIG_NETDEVICES=y
 #
 # PHY device support
 #
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -524,11 +544,13 @@ CONFIG_UCC_GETH=y
 # CONFIG_UGETH_FILTERING is not set
 # CONFIG_UGETH_TX_ON_DEMOND is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -621,6 +643,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -691,6 +714,7 @@ CONFIG_I2C_MPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_I2C_SIS5595 is not set
@@ -738,6 +762,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -778,6 +803,11 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
 #
 # Multimedia devices
 #
@@ -791,10 +821,9 @@ CONFIG_HWMON=y
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -805,6 +834,7 @@ CONFIG_FIRMWARE_EDID=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -868,6 +898,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -995,11 +1029,7 @@ CONFIG_PARTITION_ADVANCED=y
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
-
-#
-# QE Options
-#
-CONFIG_UCC_SLOW=y
+# CONFIG_UCC_SLOW is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
 
@@ -1012,7 +1042,8 @@ CONFIG_BITREVERSE=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 
 #
 # Instrumentation Support
@@ -1032,7 +1063,6 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1061,8 +1091,10 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1076,6 +1108,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index 56fc0a8244586b5adb9b664b538696eceee74a58..4a4da875fa4ece7a6c2b23833f73a575462feec3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 12 17:32:19 2007
+# Linux kernel version: 2.6.21-rc5
+# Mon Apr  9 16:12:43 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -125,7 +125,6 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_QUICC_ENGINE=y
-CONFIG_PPC_GEN550=y
 # CONFIG_WANT_EARLY_SERIAL is not set
 
 #
@@ -490,7 +489,21 @@ CONFIG_NETDEVICES=y
 #
 # PHY device support
 #
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+CONFIG_ICPLUS_PHY=y
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -1200,11 +1213,7 @@ CONFIG_NLS_ISO8859_1=y
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
-
-#
-# QE Options
-#
-CONFIG_UCC_SLOW=y
+# CONFIG_UCC_SLOW is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
 
@@ -1238,7 +1247,6 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
index 8eb475cd0df0caf483bfad44d0f0f71c74550f29..921a151dc7781be66508636f68a0b5fb5e7b4d7d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Sat Feb 17 10:09:26 2007
+# Linux kernel version: 2.6.21-rc5
+# Mon Apr  9 16:14:05 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -72,6 +72,7 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_IKCONFIG is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -124,7 +125,6 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_QUICC_ENGINE=y
-CONFIG_PPC_GEN550=y
 # CONFIG_WANT_EARLY_SERIAL is not set
 
 #
@@ -132,6 +132,7 @@ CONFIG_PPC_GEN550=y
 #
 # CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
 # CONFIG_MPC834x_MDS is not set
 # CONFIG_MPC834x_ITX is not set
 CONFIG_MPC836x_MDS=y
@@ -328,6 +329,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -346,7 +348,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -486,7 +487,21 @@ CONFIG_NETDEVICES=y
 #
 # PHY device support
 #
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -528,6 +543,7 @@ CONFIG_UCC_GETH=y
 # CONFIG_UGETH_FILTERING is not set
 # CONFIG_UGETH_TX_ON_DEMOND is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -745,6 +761,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -785,6 +802,11 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
 #
 # Multimedia devices
 #
@@ -798,10 +820,9 @@ CONFIG_HWMON=y
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1007,11 +1028,7 @@ CONFIG_PARTITION_ADVANCED=y
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
-
-#
-# QE Options
-#
-CONFIG_UCC_SLOW=y
+# CONFIG_UCC_SLOW is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
 
@@ -1045,7 +1062,6 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
index 0345a2ceec5970f41bce2021df37d6242bc767e2..fd604968f9a2b8afa636c62771716fb1941e8c16 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc6
-# Thu Jan 25 13:35:34 2007
+# Linux kernel version: 2.6.21
+# Mon Apr 30 12:03:35 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -60,6 +60,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -69,6 +70,7 @@ CONFIG_SYSVIPC=y
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
@@ -131,13 +133,36 @@ CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+CONFIG_PPC_PS3=y
+
+#
+# PS3 Platform Options
+#
+# CONFIG_PS3_ADVANCED is not set
+CONFIG_PS3_HTAB_SIZE=20
+# CONFIG_PS3_DYNAMIC_DMA is not set
+CONFIG_PS3_USE_LPAR_ADDR=y
+CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
+CONFIG_PS3_SYS_MANAGER=y
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-CONFIG_PPC_PS3=y
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=y
+CONFIG_SPU_BASE=y
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_U3_DART is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -146,24 +171,7 @@ CONFIG_PPC_PS3=y
 # CONFIG_PPC_INDIRECT_IO is not set
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-# CONFIG_MPIC is not set
-
-#
-# Cell Broadband Engine options
-#
-CONFIG_SPU_FS=y
-CONFIG_SPU_BASE=y
-# CONFIG_CBE_RAS is not set
-
-#
-# PS3 Platform Options
-#
-CONFIG_PS3_HTAB_SIZE=20
-# CONFIG_PS3_DYNAMIC_DMA is not set
-CONFIG_PS3_USE_LPAR_ADDR=y
-CONFIG_PS3_VUART=y
-CONFIG_PS3_PS3AV=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -179,10 +187,10 @@ CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_BKL is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
-CONFIG_FORCE_MAX_ZONEORDER=9
+CONFIG_FORCE_MAX_ZONEORDER=13
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-# CONFIG_KEXEC is not set
+CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 # CONFIG_IRQ_ALL_CPUS is not set
 # CONFIG_NUMA is not set
@@ -203,22 +211,22 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTPLUG_SPARSE=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_MEMORY_PROBE=y
-CONFIG_PPC_64K_PAGES=y
+# CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="root=/dev/sda1 ip=dhcp"
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
 
@@ -240,10 +248,13 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -261,7 +272,7 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
@@ -270,9 +281,23 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
@@ -313,7 +338,31 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
-# CONFIG_BT is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+# CONFIG_BT_RFCOMM_TTY is not set
+# CONFIG_BT_BNEP is not set
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
 # CONFIG_IEEE80211 is not set
 
 #
@@ -327,16 +376,13 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -347,24 +393,27 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_UB is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65535
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -388,7 +437,7 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
 
 #
@@ -413,6 +462,7 @@ CONFIG_BLK_DEV_SR=y
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -460,7 +510,7 @@ CONFIG_NETDEVICES=y
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-CONFIG_MII=y
+CONFIG_MII=m
 
 #
 # Ethernet (1000 Mbit)
@@ -475,9 +525,10 @@ CONFIG_MII=y
 #
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
 # Wan interfaces
@@ -551,7 +602,8 @@ CONFIG_HW_CONSOLE=y
 # Non-8250 serial port support
 #
 CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
 
 #
 # IPMI
@@ -597,6 +649,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
 
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
 #
 # Multimedia devices
 #
@@ -611,15 +668,22 @@ CONFIG_GEN_RTC=y
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_OF is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -634,7 +698,7 @@ CONFIG_FB_PS3_DEFAULT_SIZE_M=18
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -646,17 +710,62 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA PowerMac devices
+#
+
+#
+# ALSA PowerMac requires I2C
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -665,13 +774,13 @@ CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
 
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -704,7 +813,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
@@ -720,10 +829,16 @@ CONFIG_USB_STORAGE=y
 #
 # USB Input Devices
 #
-CONFIG_USB_HID=y
+CONFIG_USB_HID=m
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -736,6 +851,7 @@ CONFIG_USB_HID=y
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -748,15 +864,16 @@ CONFIG_USB_HID=y
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_PEGASUS=m
 # CONFIG_USB_RTL8150 is not set
-CONFIG_USB_USBNET_MII=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+# CONFIG_USB_NET_CDCETHER is not set
+# CONFIG_USB_NET_DM9601 is not set
 # CONFIG_USB_NET_GL620A is not set
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_PLUSB is not set
-CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_MCS7830=m
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
@@ -781,6 +898,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -791,6 +909,8 @@ CONFIG_USB_MON=y
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
 
 #
 # USB DSL modem support
@@ -845,6 +965,10 @@ CONFIG_USB_MON=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -852,7 +976,9 @@ CONFIG_USB_MON=y
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -871,27 +997,30 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
+CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=y
+CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=y
+CONFIG_FAT_FS=m
 # CONFIG_MSDOS_FS is not set
-CONFIG_VFAT_FS=y
+CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
@@ -933,7 +1062,7 @@ CONFIG_RAMFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
+CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
@@ -941,10 +1070,16 @@ CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1004,6 +1139,8 @@ CONFIG_NLS_ISO8859_1=y
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1014,7 +1151,8 @@ CONFIG_BITREVERSE=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 
 #
 # Instrumentation Support
@@ -1032,16 +1170,16 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-CONFIG_DEBUG_SLAB=y
-# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_RWSEMS=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1051,8 +1189,10 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_LIST=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
@@ -1063,6 +1203,8 @@ CONFIG_PPC_EARLY_DEBUG=y
 # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
 # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
 # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
 
 #
 # Security options
@@ -1073,4 +1215,43 @@ CONFIG_PPC_EARLY_DEBUG=y
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
index aa693d0f151ad26f50a14d48f6cf240318d21e22..3e779f07f21b0819801b946f2e66231c7eaf605c 100644 (file)
@@ -36,8 +36,9 @@ obj-$(CONFIG_GENERIC_TBSYNC)  += smp-tbsync.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_6xx)              += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)              += tau_6xx.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o suspend.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj64-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_64.o swsusp_asm64.o
 obj32-$(CONFIG_MODULES)                += module_32.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
@@ -67,6 +68,7 @@ obj-$(CONFIG_MODULES)         += $(module-y)
 pci64-$(CONFIG_PPC64)          += pci_64.o pci_dn.o
 pci32-$(CONFIG_PPC32)          := pci_32.o
 obj-$(CONFIG_PCI)              += $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI_MSI)          += msi.o
 kexec-$(CONFIG_PPC64)          := machine_kexec_64.o
 kexec-$(CONFIG_PPC32)          := machine_kexec_32.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o crash.o $(kexec-y)
index 0c5150c69175c014f065214d4440ce0b58ff0b59..2cb1d948779614040ec6ae3f303a7627c8dbee66 100644 (file)
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/suspend.h>
 #ifdef CONFIG_PPC64
 #include <linux/time.h>
 #include <linux/hardirq.h>
 #else
 #include <linux/ptrace.h>
-#include <linux/suspend.h>
 #endif
 
 #include <asm/io.h>
@@ -58,7 +58,7 @@ int main(void)
 #ifdef CONFIG_PPC64
        DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
 #else
-       DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
 #endif /* CONFIG_PPC64 */
 
@@ -122,12 +122,18 @@ int main(void)
        DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
        DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
        DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-       DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
        DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
-#ifdef CONFIG_HUGETLB_PAGE
-       DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
-       DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
-#endif /* CONFIG_HUGETLB_PAGE */
+#ifdef CONFIG_PPC_MM_SLICES
+       DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
+                                           context.low_slices_psize));
+       DEFINE(PACAHIGHSLICEPSIZE, offsetof(struct paca_struct,
+                                           context.high_slices_psize));
+       DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
+       DEFINE(MMUPSIZESLLP, offsetof(struct mmu_psize_def, sllp));
+#else
+       DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
+
+#endif /* CONFIG_PPC_MM_SLICES */
        DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
        DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
        DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
@@ -257,11 +263,11 @@ int main(void)
        DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
        DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
 
-#ifndef CONFIG_PPC64
        DEFINE(pbe_address, offsetof(struct pbe, address));
        DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
        DEFINE(pbe_next, offsetof(struct pbe, next));
 
+#ifndef CONFIG_PPC64
        DEFINE(TASK_SIZE, TASK_SIZE);
        DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
 #endif /* ! CONFIG_PPC64 */
index a15d4b8cce48783e0c54f12bf9b112460532408f..88695963f5872ecc444efa6dc204d6f865b1cecb 100644 (file)
@@ -120,8 +120,8 @@ skpinv:     addi    r4,r4,1                         /* Increment */
  * Configure and load pinned entry into TLB slot 63.
  */
 
-       lis     r3,KERNELBASE@h         /* Load the kernel virtual address */
-       ori     r3,r3,KERNELBASE@l
+       lis     r3,PAGE_OFFSET@h
+       ori     r3,r3,PAGE_OFFSET@l
 
        /* Kernel is at the base of RAM */
        li r4, 0                        /* Load the kernel physical address */
@@ -172,36 +172,28 @@ skpinv:   addi    r4,r4,1                         /* Increment */
        isync
 
 4:
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /*
-        * Add temporary UART mapping for early debug.
-        * We can map UART registers wherever we want as long as they don't
-        * interfere with other system mappings (e.g. with pinned entries).
-        * For an example of how we handle this - see ocotea.h.       --ebs
-        */
+#ifdef CONFIG_PPC_EARLY_DEBUG_44x
+       /* Add UART mapping for early debug. */
+
        /* pageid fields */
-       lis     r3,UART0_IO_BASE@h
-       ori     r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K
+       lis     r3,PPC44x_EARLY_DEBUG_VIRTADDR@h
+       ori     r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K
 
        /* xlat fields */
-       lis     r4,UART0_PHYS_IO_BASE@h         /* RPN depends on SoC */
-#ifndef CONFIG_440EP
-       ori     r4,r4,0x0001            /* ERPN is 1 for second 4GB page */
-#endif
+       lis     r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h
+       ori     r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
 
        /* attrib fields */
-       li      r5,0
-       ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
+       li      r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)
+        li      r0,62                    /* TLB slot 0 */
 
-        li      r0,0                    /* TLB slot 0 */
-
-       tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
-       tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
-       tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
+       tlbwe   r3,r0,PPC44x_TLB_PAGEID
+       tlbwe   r4,r0,PPC44x_TLB_XLAT
+       tlbwe   r5,r0,PPC44x_TLB_ATTRIB
 
        /* Force context change */
        isync
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
 
        /* Establish the interrupt vector offsets */
        SET_IVOR(0,  CriticalInput);
@@ -709,16 +701,6 @@ _GLOBAL(giveup_fpu)
        blr
 #endif
 
-/*
- * extern void abort(void)
- *
- * At present, this routine just applies a system reset.
- */
-_GLOBAL(abort)
-        mfspr   r13,SPRN_DBCR0
-        oris    r13,r13,DBCR0_RST_SYSTEM@h
-        mtspr   SPRN_DBCR0,r13
-
 _GLOBAL(set_context)
 
 #ifdef CONFIG_BDI_SWITCH
index 6e7f50967bab10af659e61c227c7974117bbd945..a9e9cbd329752aa11411d7d3058f6903655a9840 100644 (file)
 #include <asm/smp.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
+/* this is used for software suspend, and that shuts down
+ * CPUs even while the system is still booting... */
 #define cpu_should_die()       (cpu_is_offline(smp_processor_id()) && \
-                                system_state == SYSTEM_RUNNING)
+                                  (system_state == SYSTEM_RUNNING     \
+                                || system_state == SYSTEM_BOOTING))
 #else
 #define cpu_should_die()       0
 #endif
index ba3195478600998a72bbdbabeaf7761963a435ed..5328709eeedcf952b3fa32445f8a6aea1c3e82cb 100644 (file)
@@ -53,3 +53,24 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        isync
        b       1b
 
+_GLOBAL(power4_cpu_offline_powersave)
+       /* Go to NAP now */
+       mfmsr   r7
+       rldicl  r0,r7,48,1
+       rotldi  r0,r0,16
+       mtmsrd  r0,1                    /* hard-disable interrupts */
+       li      r0,1
+       li      r6,0
+       stb     r0,PACAHARDIRQEN(r13)   /* we'll hard-enable shortly */
+       stb     r6,PACASOFTIRQEN(r13)   /* soft-disable irqs */
+BEGIN_FTR_SECTION
+       DSSALL
+       sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       ori     r7,r7,MSR_EE
+       oris    r7,r7,MSR_POW@h
+       sync
+       isync
+       mtmsrd  r7
+       isync
+       blr
index 6c83fe229e6089f6c5221d72f84f342968f7eeac..9ed4931af1641253cce9dfce6c52fd6deb91c230 100644 (file)
@@ -67,6 +67,7 @@
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/firmware.h>
+#include <asm/lv1call.h>
 #endif
 
 int __irq_offset_value;
@@ -162,6 +163,16 @@ void local_irq_restore(unsigned long en)
        local_paca->hard_enabled = en;
        if ((int)mfspr(SPRN_DEC) < 0)
                mtspr(SPRN_DEC, 1);
+
+       /*
+        * Force the delivery of pending soft-disabled interrupts on PS3.
+        * Any HV call will have this side effect.
+        */
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+               u64 tmp;
+               lv1_get_version_info(&tmp);
+       }
+
        hard_irq_enable();
 }
 #endif /* CONFIG_PPC64 */
@@ -947,33 +958,6 @@ arch_initcall(irq_late_init);
 
 #endif /* CONFIG_PPC_MERGE */
 
-#ifdef CONFIG_PCI_MSI
-int pci_enable_msi(struct pci_dev * pdev)
-{
-       if (ppc_md.enable_msi)
-               return ppc_md.enable_msi(pdev);
-       else
-               return -1;
-}
-EXPORT_SYMBOL(pci_enable_msi);
-
-void pci_disable_msi(struct pci_dev * pdev)
-{
-       if (ppc_md.disable_msi)
-               ppc_md.disable_msi(pdev);
-}
-EXPORT_SYMBOL(pci_disable_msi);
-
-void pci_scan_msi_device(struct pci_dev *dev) {}
-int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
-void pci_disable_msix(struct pci_dev *dev) {}
-void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
-void pci_no_msi(void) {}
-EXPORT_SYMBOL(pci_enable_msix);
-EXPORT_SYMBOL(pci_disable_msix);
-
-#endif
-
 #ifdef CONFIG_PPC64
 static int __init setup_noirqdistrib(char *str)
 {
index ef647e7a9dc3513cdedd057fe7e626e07dc16278..0c96611f02f4852600711f416c5d9d8b6f036b85 100644 (file)
@@ -30,8 +30,8 @@
 #include <linux/ptrace.h>
 #include <linux/preempt.h>
 #include <linux/module.h>
+#include <linux/kdebug.h>
 #include <asm/cacheflush.h>
-#include <asm/kdebug.h>
 #include <asm/sstep.h>
 #include <asm/uaccess.h>
 
@@ -126,22 +126,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 }
 
 /* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
-       struct kretprobe_instance *ri;
-
-       if ((ri = get_free_rp_inst(rp)) != NULL) {
-               ri->rp = rp;
-               ri->task = current;
-               ri->ret_addr = (kprobe_opcode_t *)regs->link;
-
-               /* Replace the return addr with trampoline addr */
-               regs->link = (unsigned long)kretprobe_trampoline;
-               add_rp_inst(ri);
-       } else {
-               rp->nmissed++;
-       }
+       ri->ret_addr = (kprobe_opcode_t *)regs->link;
+
+       /* Replace the return addr with trampoline addr */
+       regs->link = (unsigned long)kretprobe_trampoline;
 }
 
 static int __kprobes kprobe_handler(struct pt_regs *regs)
@@ -336,7 +327,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
                        break;
        }
 
-       BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
        regs->nip = orig_ret_address;
 
        reset_current_kprobe();
@@ -410,7 +401,7 @@ out:
        return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -495,14 +486,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
                if (post_kprobe_handler(args->regs))
                        ret = NOTIFY_STOP;
                break;
-       case DIE_PAGE_FAULT:
-               /* kprobe_running() needs smp_processor_id() */
-               preempt_disable();
-               if (kprobe_running() &&
-                   kprobe_fault_handler(args->regs, args->trapnr))
-                       ret = NOTIFY_STOP;
-               preempt_enable();
-               break;
        default:
                break;
        }
@@ -559,3 +542,11 @@ int __init arch_init_kprobes(void)
 {
        return register_kprobe(&trampoline_p);
 }
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)
+               return 1;
+
+       return 0;
+}
index ae4836ea7442711f0f36c80e2ab90e6ae42fbedb..cea8045ba40b33a3f56346c4460cfd88bde9eac5 100644 (file)
@@ -244,9 +244,9 @@ static int __init add_legacy_pci_port(struct device_node *np,
         * doesn't work for these settings, you'll have to add your own special
         * cases here
         */
-       if (device_is_compatible(pci_dev, "pci13a8,152") ||
-           device_is_compatible(pci_dev, "pci13a8,154") ||
-           device_is_compatible(pci_dev, "pci13a8,158")) {
+       if (of_device_is_compatible(pci_dev, "pci13a8,152") ||
+           of_device_is_compatible(pci_dev, "pci13a8,154") ||
+           of_device_is_compatible(pci_dev, "pci13a8,158")) {
                addr += 0x200 * lindex;
                base += 0x200 * lindex;
        } else {
@@ -365,11 +365,11 @@ void __init find_legacy_serial_ports(void)
                /* Check for known pciclass, and also check wether we have
                 * a device with child nodes for ports or not
                 */
-               if (device_is_compatible(np, "pciclass,0700") ||
-                   device_is_compatible(np, "pciclass,070002"))
+               if (of_device_is_compatible(np, "pciclass,0700") ||
+                   of_device_is_compatible(np, "pciclass,070002"))
                        pci = np;
-               else if (device_is_compatible(parent, "pciclass,0700") ||
-                        device_is_compatible(parent, "pciclass,070002"))
+               else if (of_device_is_compatible(parent, "pciclass,0700") ||
+                        of_device_is_compatible(parent, "pciclass,070002"))
                        pci = parent;
                else {
                        of_node_put(parent);
index 584d1e3c013d24cac3a2eb5d17a7eb66a52d8e85..af11285ffbd1d2b7f69acfbc8aacd5ddc6f1ddca 100644 (file)
@@ -10,7 +10,8 @@
 #include <asm/pgtable.h>
 #include <asm/iseries/lpar_map.h>
 
-const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
+/* The # is to stop gcc trying to make .text nonexecutable */
+const struct LparMap __attribute__((__section__(".text #"))) xLparMap = {
        .xNumberEsids = HvEsidsToMap,
        .xNumberRanges = HvRangesToMap,
        .xSegmentTableOffs = STAB0_PAGE,
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
new file mode 100644 (file)
index 0000000..c62d101
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/msi.h>
+
+#include <asm/machdep.h>
+
+int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
+{
+       if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
+               pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
+               return -ENOSYS;
+       }
+
+       if (ppc_md.msi_check_device) {
+               pr_debug("msi: Using platform check routine.\n");
+               return ppc_md.msi_check_device(dev, nvec, type);
+       }
+
+        return 0;
+}
+
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       return ppc_md.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+       return ppc_md.teardown_msi_irqs(dev);
+}
index 0c8ea7659d928701bc92fcfff78685d81dc99453..a464d67248dfd1c7f754095fa386aabf7cd33178 100644 (file)
@@ -27,7 +27,7 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
                        match &= node->type
                                && !strcmp(matches->type, node->type);
                if (matches->compatible[0])
-                       match &= device_is_compatible(node,
+                       match &= of_device_is_compatible(node,
                                                      matches->compatible);
                if (match)
                        return matches;
@@ -120,8 +120,8 @@ void of_device_unregister(struct of_device *ofdev)
 }
 
 
-static ssize_t of_device_get_modalias(struct of_device *ofdev,
-                                       char *str, ssize_t len)
+ssize_t of_device_get_modalias(struct of_device *ofdev,
+                               char *str, ssize_t len)
 {
        const char *compat;
        int cplen, i;
@@ -239,3 +239,4 @@ EXPORT_SYMBOL(of_dev_get);
 EXPORT_SYMBOL(of_dev_put);
 EXPORT_SYMBOL(of_release_dev);
 EXPORT_SYMBOL(of_device_uevent);
+EXPORT_SYMBOL(of_device_get_modalias);
index 908ed7926db4e60ee3e3a4c2d3459b165ebbbc3c..84c34d979a88073e3970ac33adc62c24692935a6 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/ppc-pci.h>
 #include <asm/atomic.h>
 
-
 /*
  * The list of OF IDs below is used for matching bus types in the
  * system whose devices are to be exposed as of_platform_devices.
index f022862de34458b90a402a6c20330819aec7ff09..e66064b5093a2496ad2e03e9ebd1212ba98ad72b 100644 (file)
@@ -1658,7 +1658,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
        int i;
 
        if (page_is_ram(pfn))
-               return prot;
+               return __pgprot(prot);
 
        prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
 
index 7138092826aa4ce99fcabcc21d52217dc3a21d5d..6d05a1f377b5e1a56fb3294a4ec22661442c34fc 100644 (file)
@@ -1006,8 +1006,9 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 
                switch ((pci_space >> 24) & 0x3) {
                case 1:         /* I/O space */
-                       hose->io_base_phys = cpu_phys_addr;
-                       hose->pci_io_size = size;
+                       hose->io_base_phys = cpu_phys_addr - pci_addr;
+                       /* handle from 0 to top of I/O window */
+                       hose->pci_io_size = pci_addr + size;
 
                        res = &hose->io_resource;
                        res->flags = IORESOURCE_IO;
@@ -1117,8 +1118,8 @@ static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
        } else {
                /* Root Bus */
                res = &hose->io_resource;
-               *start_phys = hose->io_base_phys;
-               *start_virt = (unsigned long) hose->io_base_virt;
+               *start_phys = hose->io_base_phys + res->start;
+               *start_virt = (unsigned long) hose->io_base_virt + res->start;
                if (res->end > res->start)
                        *size = res->end - res->start + 1;
                else {
index ff252aaead122edd17354a3b4716223eea2fecba..c96fa9bd35a4f0ecf056dff387ce824e8808fc8e 100644 (file)
@@ -66,7 +66,6 @@ EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
 EXPORT_SYMBOL(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
-EXPORT_SYMBOL(__div64_32);
 
 EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
index e509aae2feb37925a17b10bef5735dccd0b1be60..6e2f03566b0dd8973f15bc4fac732ce4ff654692 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
index e27d9d1b6e67232b75d9e99c50a70d051b282866..d6047c441034935d01e8ef351e87482f5fd0fb9d 100644 (file)
@@ -635,6 +635,12 @@ static void __init early_cmdline_parse(void)
 /* ibm,dynamic-reconfiguration-memory property supported */
 #define OV5_DRCONF_MEMORY      0x20
 #define OV5_LARGE_PAGES                0x10    /* large pages supported */
+/* PCIe/MSI support.  Without MSI full PCIe is not supported */
+#ifdef CONFIG_PCI_MSI
+#define OV5_MSI                        0x01    /* PCIe/MSI support */
+#else
+#define OV5_MSI                        0x00
+#endif /* CONFIG_PCI_MSI */
 
 /*
  * The architecture vector has an array of PVR mask/value pairs,
@@ -679,7 +685,7 @@ static unsigned char ibm_architecture_vec[] = {
        /* option vector 5: PAPR/OF options */
        3 - 2,                          /* length */
        0,                              /* don't ignore, don't halt */
-       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY,
+       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
@@ -967,7 +973,7 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp)
  * If problems seem to show up, it would be a good start to track
  * them down.
  */
-static void reserve_mem(u64 base, u64 size)
+static void __init reserve_mem(u64 base, u64 size)
 {
        u64 top = base + size;
        unsigned long cnt = RELOC(mem_reserve_cnt);
@@ -2153,7 +2159,7 @@ static void __init fixup_device_tree_efika(void)
                                     3,12,0, 3,13,0, 3,14,0, 3,15,0 };
        struct subst_entry efika_subst_table[] = {
                { "/",                  "device_type",  prop_cstr("efika") },
-               { "/builtin",           "compatible",   prop_cstr("soc") },
+               { "/builtin",           "device_type",  prop_cstr("soc") },
                { "/builtin/ata",       "compatible",   prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
                { "/builtin/bestcomm",  "compatible",   prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
                { "/builtin/bestcomm",  "interrupts",   prop_bcomm_irq, sizeof(prop_bcomm_irq) },
index aa40a5307294b2a8442a3f4de0990386065c6b3f..b5c96af955c639ce43ea1532423bebebf0a6b177 100644 (file)
@@ -1042,3 +1042,28 @@ const void *of_get_mac_address(struct device_node *np)
 }
 EXPORT_SYMBOL(of_get_mac_address);
 
+int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
+{
+       int irq = irq_of_parse_and_map(dev, index);
+
+       /* Only dereference the resource if both the
+        * resource and the irq are valid. */
+       if (r && irq != NO_IRQ) {
+               r->start = r->end = irq;
+               r->flags = IORESOURCE_IRQ;
+       }
+
+       return irq;
+}
+EXPORT_SYMBOL_GPL(of_irq_to_resource);
+
+void __iomem *of_iomap(struct device_node *np, int index)
+{
+       struct resource res;
+
+       if (of_address_to_resource(np, index, &res))
+               return NULL;
+
+       return ioremap(res.start, 1 + res.end - res.start);
+}
+EXPORT_SYMBOL(of_iomap);
index cc44c7b975aaee2e15a1b33ea7574041e90600b9..f4f391cdd8f5e8bb45c059cf2779fd97d7f1cd3f 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 6b405a3f43f943b67c5b3cd2cabaeed43847aa00..dd1dca5bfa81fbebfbce7bcf1e2b1a72842e3a9b 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index f72e8e823d7818458210a025538b606450e81f9e..1ce0ae3f6ffc2bdd7fc4536c297b305db7e80178 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index d8e503b2e1af8d6ed9ece6358b61f083eeb2e712..22f1ef1b3100ff8df55e8ab0f8256518b4c2987e 100644 (file)
@@ -176,10 +176,10 @@ static struct call_data_struct {
 #define SMP_CALL_TIMEOUT       8
 
 /*
- * This function sends a 'generic call function' IPI to all other CPUs
- * in the system.
+ * These functions send a 'generic call function' IPI to other online
+ * CPUS in the system.
  *
- * [SUMMARY] Run a function on all other CPUs.
+ * [SUMMARY] Run a function on other CPUs.
  * <func> The function to run. This must be fast and non-blocking.
  * <info> An arbitrary pointer to pass to the function.
  * <nonatomic> currently unused.
@@ -190,18 +190,26 @@ static struct call_data_struct {
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-                      int wait)
-{ 
+int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic,
+                       int wait, cpumask_t map)
+{
        struct call_data_struct data;
-       int ret = -1, cpus;
+       int ret = -1, num_cpus;
+       int cpu;
        u64 timeout;
 
        /* Can deadlock when called with interrupts disabled */
        WARN_ON(irqs_disabled());
 
+       /* remove 'self' from the map */
+       if (cpu_isset(smp_processor_id(), map))
+               cpu_clear(smp_processor_id(), map);
+
+       /* sanity check the map, remove any non-online processors. */
+       cpus_and(map, map, cpu_online_map);
+
        if (unlikely(smp_ops == NULL))
-               return -1;
+               return ret;
 
        data.func = func;
        data.info = info;
@@ -213,40 +221,42 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
        spin_lock(&call_lock);
        /* Must grab online cpu count with preempt disabled, otherwise
         * it can change. */
-       cpus = num_online_cpus() - 1;
-       if (!cpus) {
+       num_cpus = num_online_cpus() - 1;
+       if (!num_cpus || cpus_empty(map)) {
                ret = 0;
                goto out;
        }
 
        call_data = &data;
        smp_wmb();
-       /* Send a message to all other CPUs and wait for them to respond */
-       smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
+       /* Send a message to all CPUs in the map */
+       for_each_cpu_mask(cpu, map)
+               smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
 
        timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
 
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus) {
+       /* Wait for indication that they have received the message */
+       while (atomic_read(&data.started) != num_cpus) {
                HMT_low();
                if (get_tb() >= timeout) {
                        printk("smp_call_function on cpu %d: other cpus not "
-                              "responding (%d)\n", smp_processor_id(),
-                              atomic_read(&data.started));
+                               "responding (%d)\n", smp_processor_id(),
+                               atomic_read(&data.started));
                        debugger(NULL);
                        goto out;
                }
        }
 
+       /* optionally wait for the CPUs to complete */
        if (wait) {
-               while (atomic_read(&data.finished) != cpus) {
+               while (atomic_read(&data.finished) != num_cpus) {
                        HMT_low();
                        if (get_tb() >= timeout) {
                                printk("smp_call_function on cpu %d: other "
-                                      "cpus not finishing (%d/%d)\n",
-                                      smp_processor_id(),
-                                      atomic_read(&data.finished),
-                                      atomic_read(&data.started));
+                                       "cpus not finishing (%d/%d)\n",
+                                       smp_processor_id(),
+                                       atomic_read(&data.finished),
+                                       atomic_read(&data.started));
                                debugger(NULL);
                                goto out;
                        }
@@ -262,8 +272,29 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
        return ret;
 }
 
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+                       int wait)
+{
+       return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map);
+}
 EXPORT_SYMBOL(smp_call_function);
 
+int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic,
+                       int wait)
+{
+       cpumask_t map=CPU_MASK_NONE;
+
+       if (!cpu_online(cpu))
+               return -EINVAL;
+
+       if (cpu == smp_processor_id())
+               return -EBUSY;
+
+       cpu_set(cpu, map);
+       return smp_call_function_map(func,info,nonatomic,wait,map);
+}
+EXPORT_SYMBOL(smp_call_function_single);
+
 void smp_call_function_interrupt(void)
 {
        void (*func) (void *info);
diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c
new file mode 100644 (file)
index 0000000..064a7ba
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Common powerpc suspend code for 32 and 64 bits
+ *
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.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.
+ */
+
+#include <linux/sched.h>
+#include <asm/suspend.h>
+#include <asm/system.h>
+#include <asm/current.h>
+#include <asm/mmu_context.h>
+
+void save_processor_state(void)
+{
+       /*
+        * flush out all the special registers so we don't need
+        * to save them in the snapshot
+        */
+       flush_fp_to_thread(current);
+       flush_altivec_to_thread(current);
+       flush_spe_to_thread(current);
+
+#ifdef CONFIG_PPC64
+       hard_irq_disable();
+#endif
+
+}
+
+void restore_processor_state(void)
+{
+#ifdef CONFIG_PPC32
+       set_context(current->active_mm->context.id, current->active_mm->pgd);
+#endif
+
+#ifdef CONFIG_PPC64
+       hard_irq_enable();
+#endif
+}
diff --git a/arch/powerpc/kernel/swsusp_64.c b/arch/powerpc/kernel/swsusp_64.c
new file mode 100644 (file)
index 0000000..6f3f069
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <asm/system.h>
+#include <asm/iommu.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+void do_after_copyback(void)
+{
+       iommu_restore();
+       touch_softlockup_watchdog();
+       mb();
+}
+
+void _iommu_save(void)
+{
+       iommu_save();
+}
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S
new file mode 100644 (file)
index 0000000..e092c3c
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_r1          0x00    /* stack pointer */
+#define SL_PC          0x08
+#define SL_MSR         0x10
+#define SL_SDR1                0x18
+#define SL_XER         0x20
+#define SL_TB          0x40
+#define SL_r2          0x48
+#define SL_CR          0x50
+#define SL_LR          0x58
+#define SL_r12         0x60
+#define SL_r13         0x68
+#define SL_r14         0x70
+#define SL_r15         0x78
+#define SL_r16         0x80
+#define SL_r17         0x88
+#define SL_r18         0x90
+#define SL_r19         0x98
+#define SL_r20         0xa0
+#define SL_r21         0xa8
+#define SL_r22         0xb0
+#define SL_r23         0xb8
+#define SL_r24         0xc0
+#define SL_r25         0xc8
+#define SL_r26         0xd0
+#define SL_r27         0xd8
+#define SL_r28         0xe0
+#define SL_r29         0xe8
+#define SL_r30         0xf0
+#define SL_r31         0xf8
+#define SL_SIZE                SL_r31+8
+
+/* these macros rely on the save area being
+ * pointed to by r11 */
+#define SAVE_SPECIAL(special)          \
+       mf##special     r0              ;\
+       std     r0, SL_##special(r11)
+#define RESTORE_SPECIAL(special)       \
+       ld      r0, SL_##special(r11)   ;\
+       mt##special     r0
+#define SAVE_REGISTER(reg)             \
+       std     reg, SL_##reg(r11)
+#define RESTORE_REGISTER(reg)          \
+       ld      reg, SL_##reg(r11)
+
+/* space for storing cpu state */
+       .section .data
+       .align  5
+swsusp_save_area:
+       .space SL_SIZE
+
+       .section ".toc","aw"
+swsusp_save_area_ptr:
+       .tc     swsusp_save_area[TC],swsusp_save_area
+restore_pblist_ptr:
+       .tc     restore_pblist[TC],restore_pblist
+
+       .section .text
+       .align  5
+_GLOBAL(swsusp_arch_suspend)
+       ld      r11,swsusp_save_area_ptr@toc(r2)
+       SAVE_SPECIAL(LR)
+       SAVE_REGISTER(r1)
+       SAVE_SPECIAL(CR)
+       SAVE_SPECIAL(TB)
+       SAVE_REGISTER(r2)
+       SAVE_REGISTER(r12)
+       SAVE_REGISTER(r13)
+       SAVE_REGISTER(r14)
+       SAVE_REGISTER(r15)
+       SAVE_REGISTER(r16)
+       SAVE_REGISTER(r17)
+       SAVE_REGISTER(r18)
+       SAVE_REGISTER(r19)
+       SAVE_REGISTER(r20)
+       SAVE_REGISTER(r21)
+       SAVE_REGISTER(r22)
+       SAVE_REGISTER(r23)
+       SAVE_REGISTER(r24)
+       SAVE_REGISTER(r25)
+       SAVE_REGISTER(r26)
+       SAVE_REGISTER(r27)
+       SAVE_REGISTER(r28)
+       SAVE_REGISTER(r29)
+       SAVE_REGISTER(r30)
+       SAVE_REGISTER(r31)
+       SAVE_SPECIAL(MSR)
+       SAVE_SPECIAL(SDR1)
+       SAVE_SPECIAL(XER)
+
+       /* we push the stack up 128 bytes but don't store the
+        * stack pointer on the stack like a real stackframe */
+       addi    r1,r1,-128
+
+       bl _iommu_save
+       bl swsusp_save
+
+       /* restore LR */
+       ld      r11,swsusp_save_area_ptr@toc(r2)
+       RESTORE_SPECIAL(LR)
+       addi    r1,r1,128
+
+       blr
+
+/* Resume code */
+_GLOBAL(swsusp_arch_resume)
+       /* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+       DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       sync
+
+       ld      r12,restore_pblist_ptr@toc(r2)
+       ld      r12,0(r12)
+
+       cmpdi   r12,0
+       beq-    nothing_to_copy
+       li      r15,512
+copyloop:
+       ld      r13,pbe_address(r12)
+       ld      r14,pbe_orig_address(r12)
+
+       mtctr   r15
+       li      r10,0
+copy_page_loop:
+       ldx     r0,r10,r13
+       stdx    r0,r10,r14
+       addi    r10,r10,8
+       bdnz copy_page_loop
+
+       ld      r12,pbe_next(r12)
+       cmpdi   r12,0
+       bne+    copyloop
+nothing_to_copy:
+
+       /* flush caches */
+       lis     r3, 0x10
+       mtctr   r3
+       li      r3, 0
+       ori     r3, r3, CONFIG_KERNEL_START>>48
+       li      r0, 48
+       sld     r3, r3, r0
+       li      r0, 0
+1:
+       dcbf    r0,r3
+       addi    r3,r3,0x20
+       bdnz    1b
+
+       sync
+
+       tlbia
+
+       ld      r11,swsusp_save_area_ptr@toc(r2)
+
+       RESTORE_SPECIAL(CR)
+
+       /* restore timebase */
+       /* load saved tb */
+       ld      r1, SL_TB(r11)
+       /* get upper 32 bits of it */
+       srdi    r2, r1, 32
+       /* clear tb lower to avoid wrap */
+       li      r0, 0
+       mttbl   r0
+       /* set tb upper */
+       mttbu   r2
+       /* set tb lower */
+       mttbl   r1
+
+       /* restore registers */
+       RESTORE_REGISTER(r1)
+       RESTORE_REGISTER(r2)
+       RESTORE_REGISTER(r12)
+       RESTORE_REGISTER(r13)
+       RESTORE_REGISTER(r14)
+       RESTORE_REGISTER(r15)
+       RESTORE_REGISTER(r16)
+       RESTORE_REGISTER(r17)
+       RESTORE_REGISTER(r18)
+       RESTORE_REGISTER(r19)
+       RESTORE_REGISTER(r20)
+       RESTORE_REGISTER(r21)
+       RESTORE_REGISTER(r22)
+       RESTORE_REGISTER(r23)
+       RESTORE_REGISTER(r24)
+       RESTORE_REGISTER(r25)
+       RESTORE_REGISTER(r26)
+       RESTORE_REGISTER(r27)
+       RESTORE_REGISTER(r28)
+       RESTORE_REGISTER(r29)
+       RESTORE_REGISTER(r30)
+       RESTORE_REGISTER(r31)
+       /* can't use RESTORE_SPECIAL(MSR) */
+       ld      r0, SL_MSR(r11)
+       mtmsrd  r0, 0
+       RESTORE_SPECIAL(SDR1)
+       RESTORE_SPECIAL(XER)
+
+       sync
+
+       addi    r1,r1,-128
+       bl      slb_flush_and_rebolt
+       bl      do_after_copyback
+       addi    r1,r1,128
+
+       ld      r11,swsusp_save_area_ptr@toc(r2)
+       RESTORE_SPECIAL(LR)
+
+       li      r3, 0
+       blr
index d358866b880f25012aadf35a5e6340dd233ae801..fc6647d332cbf18160e4f62865bf06a61cd75d65 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 933e214c33e8a835ed1614afa399b37b9506ceda..68991c2d4a1b3a6fcb101728c2be0e9724dcf37d 100644 (file)
@@ -342,10 +342,12 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                register_cpu_online(cpu);
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                unregister_cpu_online(cpu);
                break;
 #endif
@@ -499,4 +501,4 @@ static int __init topology_init(void)
 
        return 0;
 }
-__initcall(topology_init);
+subsys_initcall(topology_init);
index f7862224fe85e92748a8f1e28a0b7ef71a57b330..bf6445ac9f1cb38494b5e843e186aaf633a6703d 100644 (file)
@@ -33,8 +33,8 @@
 #include <linux/kexec.h>
 #include <linux/backlight.h>
 #include <linux/bug.h>
+#include <linux/kdebug.h>
 
-#include <asm/kdebug.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -72,20 +72,6 @@ EXPORT_SYMBOL(__debugger_dabr_match);
 EXPORT_SYMBOL(__debugger_fault_handler);
 #endif
 
-ATOMIC_NOTIFIER_HEAD(powerpc_die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&powerpc_die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&powerpc_die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 /*
  * Trap & Exception support
  */
index 7e0971868fc25ec77377feb5ac7c34e195a1fd8f..87703df87509031c6b163065a7afd08cb56ca593 100644 (file)
@@ -51,6 +51,9 @@ void __init udbg_early_init(void)
        udbg_init_pas_realmode();
 #elif defined(CONFIG_BOOTX_TEXT)
        udbg_init_btext();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_44x)
+       /* PPC44x debug */
+       udbg_init_44x_as1();
 #endif
 }
 
@@ -142,29 +145,22 @@ static void udbg_console_write(struct console *con, const char *s,
 static struct console udbg_console = {
        .name   = "udbg",
        .write  = udbg_console_write,
-       .flags  = CON_PRINTBUFFER | CON_ENABLED,
+       .flags  = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT,
        .index  = -1,
 };
 
 static int early_console_initialized;
 
-void __init disable_early_printk(void)
-{
-       if (!early_console_initialized)
-               return;
-       if (strstr(boot_command_line, "udbg-immortal")) {
-               printk(KERN_INFO "early console immortal !\n");
-               return;
-       }
-       unregister_console(&udbg_console);
-       early_console_initialized = 0;
-}
-
 /* called by setup_system */
 void register_early_udbg_console(void)
 {
        if (early_console_initialized)
                return;
+
+       if (strstr(boot_command_line, "udbg-immortal")) {
+               printk(KERN_INFO "early console immortal !\n");
+               udbg_console.flags &= ~CON_BOOT;
+       }
        early_console_initialized = 1;
        register_console(&udbg_console);
 }
index a963f657222b3341eabdc7aa9272ca56cd4b84a0..7afab5bcd61abbba9c656ce012dd3b7b9b464375 100644 (file)
@@ -191,3 +191,26 @@ void udbg_init_pas_realmode(void)
        udbg_getc_poll = NULL;
 }
 #endif /* CONFIG_PPC_MAPLE */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_44x
+#include <platforms/44x/44x.h>
+
+static void udbg_44x_as1_putc(char c)
+{
+       if (udbg_comport) {
+               while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
+                       /* wait for idle */;
+               as1_writeb(c, &udbg_comport->thr); eieio();
+               if (c == '\n')
+                       udbg_44x_as1_putc('\r');
+       }
+}
+
+void __init udbg_init_44x_as1(void)
+{
+       udbg_comport =
+               (volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
+
+       udbg_putc = udbg_44x_as1_putc;
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
index e46c31b36641e7fb074e6ba3e45e17fbb7600f14..4245579edb4e8ff2de805ba638f4b3982ca80344 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
index b2c1b67a10a7bc537d94ab58977bd88867469a69..62c1bc12ea39431755d2001a2b93d300068179c9 100644 (file)
@@ -117,7 +117,7 @@ static const struct vio_device_id *vio_match_device(
 {
        while (ids->type[0] != '\0') {
                if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
-                   device_is_compatible(dev->dev.archdata.of_node,
+                   of_device_is_compatible(dev->dev.archdata.of_node,
                                         ids->compat))
                        return ids;
                ids++;
index 48f3d13a3de5abba9b35c5ea7e2fd2d95770c622..6656d47841d06e02ae07d794349075dd30794ecb 100644 (file)
@@ -306,13 +306,15 @@ EXPORT_SYMBOL(__dma_free_coherent);
 static int __init dma_alloc_init(void)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
        int ret = 0;
 
        do {
                pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
-               pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+               pud = pud_alloc(&init_mm, pgd, CONSISTENT_BASE);
+               pmd = pmd_alloc(&init_mm, pud, CONSISTENT_BASE);
                if (!pmd) {
                        printk(KERN_ERR "%s: no pmd tables\n", __func__);
                        ret = -ENOMEM;
index 0a0a0487b33435f350713fc730a8b370b5e43b17..ca4dcb07a9393fd47778ae9d1a6687710106e3ec 100644 (file)
  *
  */
 
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/stddef.h>
-#include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/highmem.h>
-
-#include <asm/pgalloc.h>
-#include <asm/prom.h>
-#include <asm/io.h>
-#include <asm/mmu_context.h>
-#include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/machdep.h>
-#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/page.h>
 
 #include "mmu_decl.h"
 
-extern char etext[], _stext[];
-
 /* Used by the 44x TLB replacement exception handler.
  * Just needed it declared someplace.
  */
-unsigned int tlb_44x_index = 0;
-unsigned int tlb_44x_hwater = 62;
+unsigned int tlb_44x_index; /* = 0 */
+unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
 
 /*
  * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
  */
-static void __init
-ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
+static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
 {
-       unsigned long attrib = 0;
-
-       __asm__ __volatile__("\
-       clrrwi  %2,%2,10\n\
-       ori     %2,%2,%4\n\
-       clrrwi  %1,%1,10\n\
-       li      %0,0\n\
-       ori     %0,%0,%5\n\
-       tlbwe   %2,%3,%6\n\
-       tlbwe   %1,%3,%7\n\
-       tlbwe   %0,%3,%8"
+       __asm__ __volatile__(
+               "tlbwe  %2,%3,%4\n"
+               "tlbwe  %1,%3,%5\n"
+               "tlbwe  %0,%3,%6\n"
        :
-       : "r" (attrib), "r" (phys), "r" (virt), "r" (slot),
-         "i" (PPC44x_TLB_VALID | PPC44x_TLB_256M),
-         "i" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
+       : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
+         "r" (phys),
+         "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
+         "r" (tlb_44x_hwater--), /* slot for this TLB entry */
          "i" (PPC44x_TLB_PAGEID),
          "i" (PPC44x_TLB_XLAT),
          "i" (PPC44x_TLB_ATTRIB));
 }
 
-/*
- * MMU_init_hw does the chip-specific initialization of the MMU hardware.
- */
 void __init MMU_init_hw(void)
 {
        flush_instruction_cache();
@@ -98,22 +63,13 @@ void __init MMU_init_hw(void)
 
 unsigned long __init mmu_mapin_ram(void)
 {
-       unsigned int pinned_tlbs = 1;
-       int i;
-
-       /* Determine number of entries necessary to cover lowmem */
-       pinned_tlbs = (unsigned int)
-               (_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT);
-
-       /* Write upper watermark to save location */
-       tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
+       unsigned long addr;
 
-       /* If necessary, set additional pinned TLBs */
-       if (pinned_tlbs > 1)
-               for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
-                       unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE;
-                       ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
-               }
+       /* Pin in enough TLBs to cover any lowmem not covered by the
+        * initial 256M mapping established in head_44x.S */
+       for (addr = PPC_PIN_SIZE; addr < total_lowmem;
+            addr += PPC_PIN_SIZE)
+               ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
 
        return total_lowmem;
 }
index 38a81967ca0702a1f0f04b4de7aa8712fe79627d..4f839c6a97682165fc9c7d18c91140fea0eddd31 100644 (file)
@@ -18,4 +18,5 @@ obj-$(CONFIG_40x)             += 4xx_mmu.o
 obj-$(CONFIG_44x)              += 44x_mmu.o
 obj-$(CONFIG_FSL_BOOKE)                += fsl_booke_mmu.o
 obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
+obj-$(CONFIG_PPC_MM_SLICES)    += slice.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
index 03aeb3a460772528b009e3f240e735ffd463047d..bfe901353142f9d835eafa01cbf37b58868d0e10 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/highmem.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
-#include <asm/kdebug.h>
 #include <asm/siginfo.h>
 
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
 
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
+#ifdef CONFIG_KPROBES
+static inline int notify_page_fault(struct pt_regs *regs)
 {
-       return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
+       int ret = 0;
+
+       /* kprobe_running() needs smp_processor_id() */
+       if (!user_mode(regs)) {
+               preempt_disable();
+               if (kprobe_running() && kprobe_fault_handler(regs, 11))
+                       ret = 1;
+               preempt_enable();
+       }
 
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .str = str,
-               .err = err,
-               .trapnr = trap,
-               .signr = sig
-       };
-       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+       return ret;
 }
 #else
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs)
 {
-       return NOTIFY_DONE;
+       return 0;
 }
 #endif
 
@@ -175,8 +164,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
        is_write = error_code & ESR_DST;
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
 
-       if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code,
-                               11, SIGSEGV) == NOTIFY_STOP)
+       if (notify_page_fault(regs))
                return 0;
 
        if (trap == 0x300) {
index e64ce3eec36ed3e025324cb68011bac3c6a1028c..4762ff7c14df22fd2c4c5bdcc6a1e234665c917a 100644 (file)
@@ -615,6 +615,9 @@ htab_pte_insert_failure:
        li      r3,-1
        b       htab_bail
 
+#endif /* CONFIG_PPC_64K_PAGES */
+
+#ifdef CONFIG_PPC_HAS_HASH_64K
 
 /*****************************************************************************
  *                                                                           *
@@ -870,7 +873,7 @@ ht64_pte_insert_failure:
        b       ht64_bail
 
 
-#endif /* CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC_HAS_HASH_64K */
 
 
 /*****************************************************************************
index 79aedaf36f2bd3cc91a893ce862bf8c00056a488..7b7fe2d7b9dc7c1e882984ab2b8ba17461b70617 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/tlb.h>
 #include <asm/cputable.h>
 #include <asm/udbg.h>
+#include <asm/kexec.h>
 
 #ifdef DEBUG_LOW
 #define DBG_LOW(fmt...) udbg_printf(fmt)
@@ -340,31 +341,70 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
        local_irq_restore(flags);
 }
 
-/*
- * XXX This need fixing based on page size. It's only used by
- * native_hpte_clear() for now which needs fixing too so they
- * make a good pair...
- */
-static unsigned long slot2va(unsigned long hpte_v, unsigned long slot)
-{
-       unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v);
-       unsigned long va;
+#define LP_SHIFT       12
+#define LP_BITS                8
+#define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
 
-       va = avpn << 23;
+static void hpte_decode(hpte_t *hpte, unsigned long slot,
+                       int *psize, unsigned long *va)
+{
+       unsigned long hpte_r = hpte->r;
+       unsigned long hpte_v = hpte->v;
+       unsigned long avpn;
+       int i, size, shift, penc, avpnm_bits;
+
+       if (!(hpte_v & HPTE_V_LARGE))
+               size = MMU_PAGE_4K;
+       else {
+               for (i = 0; i < LP_BITS; i++) {
+                       if ((hpte_r & LP_MASK(i+1)) == LP_MASK(i+1))
+                               break;
+               }
+               penc = LP_MASK(i+1) >> LP_SHIFT;
+               for (size = 0; size < MMU_PAGE_COUNT; size++) {
 
-       if (! (hpte_v & HPTE_V_LARGE)) {
-               unsigned long vpi, pteg;
+                       /* 4K pages are not represented by LP */
+                       if (size == MMU_PAGE_4K)
+                               continue;
 
-               pteg = slot / HPTES_PER_GROUP;
-               if (hpte_v & HPTE_V_SECONDARY)
-                       pteg = ~pteg;
+                       /* valid entries have a shift value */
+                       if (!mmu_psize_defs[size].shift)
+                               continue;
 
-               vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
+                       if (penc == mmu_psize_defs[size].penc)
+                               break;
+               }
+       }
 
-               va |= vpi << PAGE_SHIFT;
+       /*
+        * FIXME, the code below works for 16M, 64K, and 4K pages as these
+        * fall under the p<=23 rules for calculating the virtual address.
+        * In the case of 16M pages, an extra bit is stolen from the AVPN
+        * field to achieve the requisite 24 bits.
+        *
+        * Does not work for 16G pages or 1 TB segments.
+        */
+       shift = mmu_psize_defs[size].shift;
+       if (mmu_psize_defs[size].avpnm)
+               avpnm_bits = __ilog2_u64(mmu_psize_defs[size].avpnm) + 1;
+       else
+               avpnm_bits = 0;
+       if (shift - avpnm_bits <= 23) {
+               avpn = HPTE_V_AVPN_VAL(hpte_v) << 23;
+
+               if (shift < 23) {
+                       unsigned long vpi, pteg;
+
+                       pteg = slot / HPTES_PER_GROUP;
+                       if (hpte_v & HPTE_V_SECONDARY)
+                               pteg = ~pteg;
+                       vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
+                       avpn |= (vpi << mmu_psize_defs[size].shift);
+               }
        }
 
-       return va;
+       *va = avpn;
+       *psize = size;
 }
 
 /*
@@ -374,15 +414,14 @@ static unsigned long slot2va(unsigned long hpte_v, unsigned long slot)
  *
  * TODO: add batching support when enabled.  remember, no dynamic memory here,
  * athough there is the control page available...
- *
- * XXX FIXME: 4k only for now !
  */
 static void native_hpte_clear(void)
 {
        unsigned long slot, slots, flags;
        hpte_t *hptep = htab_address;
-       unsigned long hpte_v;
+       unsigned long hpte_v, va;
        unsigned long pteg_count;
+       int psize;
 
        pteg_count = htab_hash_mask + 1;
 
@@ -408,8 +447,9 @@ static void native_hpte_clear(void)
                 * already hold the native_tlbie_lock.
                 */
                if (hpte_v & HPTE_V_VALID) {
+                       hpte_decode(hptep, slot, &psize, &va);
                        hptep->v = 0;
-                       __tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K);
+                       __tlbie(va, psize);
                }
        }
 
index 49618461defbda9a4e2017477c1326530281272e..028ba4ed03d2c88f5c413b96c83fe60e00161f58 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/cputable.h>
 #include <asm/abs_addr.h>
 #include <asm/sections.h>
+#include <asm/spu.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -103,7 +104,7 @@ int mmu_ci_restrictions;
 #ifdef CONFIG_DEBUG_PAGEALLOC
 static u8 *linear_map_hash_slots;
 static unsigned long linear_map_hash_count;
-static spinlock_t linear_map_hash_lock;
+static DEFINE_SPINLOCK(linear_map_hash_lock);
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
 /* There are definitions of page sizes arrays to be used when none
@@ -419,7 +420,7 @@ static void __init htab_finish_init(void)
        extern unsigned int *htab_call_hpte_remove;
        extern unsigned int *htab_call_hpte_updatepp;
 
-#ifdef CONFIG_PPC_64K_PAGES
+#ifdef CONFIG_PPC_HAS_HASH_64K
        extern unsigned int *ht64_call_hpte_insert1;
        extern unsigned int *ht64_call_hpte_insert2;
        extern unsigned int *ht64_call_hpte_remove;
@@ -596,22 +597,23 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
  * Demote a segment to using 4k pages.
  * For now this makes the whole process use 4k pages.
  */
-void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
-{
 #ifdef CONFIG_PPC_64K_PAGES
+static void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
+{
        if (mm->context.user_psize == MMU_PAGE_4K)
                return;
+#ifdef CONFIG_PPC_MM_SLICES
+       slice_set_user_psize(mm, MMU_PAGE_4K);
+#else /* CONFIG_PPC_MM_SLICES */
        mm->context.user_psize = MMU_PAGE_4K;
        mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp;
-       get_paca()->context = mm->context;
-       slb_flush_and_rebolt();
+#endif /* CONFIG_PPC_MM_SLICES */
+
 #ifdef CONFIG_SPE_BASE
        spu_flush_all_slbs(mm);
 #endif
-#endif
 }
-
-EXPORT_SYMBOL_GPL(demote_segment_4k);
+#endif /* CONFIG_PPC_64K_PAGES */
 
 /* Result code is:
  *  0 - handled
@@ -646,7 +648,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
                        return 1;
                }
                vsid = get_vsid(mm->context.id, ea);
+#ifdef CONFIG_PPC_MM_SLICES
+               psize = get_slice_psize(mm, ea);
+#else
                psize = mm->context.user_psize;
+#endif
                break;
        case VMALLOC_REGION_ID:
                mm = &init_mm;
@@ -674,11 +680,22 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
                local = 1;
 
+#ifdef CONFIG_HUGETLB_PAGE
        /* Handle hugepage regions */
-       if (unlikely(in_hugepage_area(mm->context, ea))) {
+       if (HPAGE_SHIFT && psize == mmu_huge_psize) {
                DBG_LOW(" -> huge page !\n");
                return hash_huge_page(mm, access, ea, vsid, local, trap);
        }
+#endif /* CONFIG_HUGETLB_PAGE */
+
+#ifndef CONFIG_PPC_64K_PAGES
+       /* If we use 4K pages and our psize is not 4K, then we are hitting
+        * a special driver mapping, we need to align the address before
+        * we fetch the PTE
+        */
+       if (psize != MMU_PAGE_4K)
+               ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
+#endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get PTE and page size from page tables */
        ptep = find_linux_pte(pgdir, ea);
@@ -702,54 +719,56 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        }
 
        /* Do actual hashing */
-#ifndef CONFIG_PPC_64K_PAGES
-       rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
-#else
+#ifdef CONFIG_PPC_64K_PAGES
        /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
        if (pte_val(*ptep) & _PAGE_4K_PFN) {
                demote_segment_4k(mm, ea);
                psize = MMU_PAGE_4K;
        }
 
-       if (mmu_ci_restrictions) {
-               /* If this PTE is non-cacheable, switch to 4k */
-               if (psize == MMU_PAGE_64K &&
-                   (pte_val(*ptep) & _PAGE_NO_CACHE)) {
-                       if (user_region) {
-                               demote_segment_4k(mm, ea);
-                               psize = MMU_PAGE_4K;
-                       } else if (ea < VMALLOC_END) {
-                               /*
-                                * some driver did a non-cacheable mapping
-                                * in vmalloc space, so switch vmalloc
-                                * to 4k pages
-                                */
-                               printk(KERN_ALERT "Reducing vmalloc segment "
-                                      "to 4kB pages because of "
-                                      "non-cacheable mapping\n");
-                               psize = mmu_vmalloc_psize = MMU_PAGE_4K;
-                       }
+       /* If this PTE is non-cacheable and we have restrictions on
+        * using non cacheable large pages, then we switch to 4k
+        */
+       if (mmu_ci_restrictions && psize == MMU_PAGE_64K &&
+           (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+               if (user_region) {
+                       demote_segment_4k(mm, ea);
+                       psize = MMU_PAGE_4K;
+               } else if (ea < VMALLOC_END) {
+                       /*
+                        * some driver did a non-cacheable mapping
+                        * in vmalloc space, so switch vmalloc
+                        * to 4k pages
+                        */
+                       printk(KERN_ALERT "Reducing vmalloc segment "
+                              "to 4kB pages because of "
+                              "non-cacheable mapping\n");
+                       psize = mmu_vmalloc_psize = MMU_PAGE_4K;
 #ifdef CONFIG_SPE_BASE
                        spu_flush_all_slbs(mm);
 #endif
                }
-               if (user_region) {
-                       if (psize != get_paca()->context.user_psize) {
-                               get_paca()->context = mm->context;
-                               slb_flush_and_rebolt();
-                       }
-               } else if (get_paca()->vmalloc_sllp !=
-                          mmu_psize_defs[mmu_vmalloc_psize].sllp) {
-                       get_paca()->vmalloc_sllp =
-                               mmu_psize_defs[mmu_vmalloc_psize].sllp;
+       }
+       if (user_region) {
+               if (psize != get_paca()->context.user_psize) {
+                       get_paca()->context.user_psize =
+                               mm->context.user_psize;
                        slb_flush_and_rebolt();
                }
+       } else if (get_paca()->vmalloc_sllp !=
+                  mmu_psize_defs[mmu_vmalloc_psize].sllp) {
+               get_paca()->vmalloc_sllp =
+                       mmu_psize_defs[mmu_vmalloc_psize].sllp;
+               slb_flush_and_rebolt();
        }
+#endif /* CONFIG_PPC_64K_PAGES */
+
+#ifdef CONFIG_PPC_HAS_HASH_64K
        if (psize == MMU_PAGE_64K)
                rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
        else
+#endif /* CONFIG_PPC_HAS_HASH_64K */
                rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
-#endif /* CONFIG_PPC_64K_PAGES */
 
 #ifndef CONFIG_PPC_64K_PAGES
        DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
@@ -772,42 +791,55 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
        unsigned long flags;
        int local = 0;
 
-       /* We don't want huge pages prefaulted for now
-        */
-       if (unlikely(in_hugepage_area(mm->context, ea)))
+       BUG_ON(REGION_ID(ea) != USER_REGION_ID);
+
+#ifdef CONFIG_PPC_MM_SLICES
+       /* We only prefault standard pages for now */
+       if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize));
                return;
+#endif
 
        DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx,"
                " trap=%lx\n", mm, mm->pgd, ea, access, trap);
 
-       /* Get PTE, VSID, access mask */
+       /* Get Linux PTE if available */
        pgdir = mm->pgd;
        if (pgdir == NULL)
                return;
        ptep = find_linux_pte(pgdir, ea);
        if (!ptep)
                return;
+
+#ifdef CONFIG_PPC_64K_PAGES
+       /* If either _PAGE_4K_PFN or _PAGE_NO_CACHE is set (and we are on
+        * a 64K kernel), then we don't preload, hash_page() will take
+        * care of it once we actually try to access the page.
+        * That way we don't have to duplicate all of the logic for segment
+        * page size demotion here
+        */
+       if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE))
+               return;
+#endif /* CONFIG_PPC_64K_PAGES */
+
+       /* Get VSID */
        vsid = get_vsid(mm->context.id, ea);
 
-       /* Hash it in */
+       /* Hash doesn't like irqs */
        local_irq_save(flags);
+
+       /* Is that local to this CPU ? */
        mask = cpumask_of_cpu(smp_processor_id());
        if (cpus_equal(mm->cpu_vm_mask, mask))
                local = 1;
-#ifndef CONFIG_PPC_64K_PAGES
-       __hash_page_4K(ea, access, vsid, ptep, trap, local);
-#else
-       if (mmu_ci_restrictions) {
-               /* If this PTE is non-cacheable, switch to 4k */
-               if (mm->context.user_psize == MMU_PAGE_64K &&
-                   (pte_val(*ptep) & _PAGE_NO_CACHE))
-                       demote_segment_4k(mm, ea);
-       }
+
+       /* Hash it in */
+#ifdef CONFIG_PPC_HAS_HASH_64K
        if (mm->context.user_psize == MMU_PAGE_64K)
                __hash_page_64K(ea, access, vsid, ptep, trap, local);
        else
-               __hash_page_4K(ea, access, vsid, ptep, trap, local);
 #endif /* CONFIG_PPC_64K_PAGES */
+               __hash_page_4K(ea, access, vsid, ptep, trap, local);
+
        local_irq_restore(flags);
 }
 
index 1f07f70ac89f6e213c2f70474e3a1ead890548b6..92a1b16fb7e3bab4fe1716d228d32961b77ee302 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/sysctl.h>
@@ -92,7 +91,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        pgd_t *pg;
        pud_t *pu;
 
-       BUG_ON(! in_hugepage_area(mm->context, addr));
+       BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
 
        addr &= HPAGE_MASK;
 
@@ -120,7 +119,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        pud_t *pu;
        hugepd_t *hpdp = NULL;
 
-       BUG_ON(! in_hugepage_area(mm->context, addr));
+       BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
 
        addr &= HPAGE_MASK;
 
@@ -303,7 +302,7 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
        start = addr;
        pgd = pgd_offset((*tlb)->mm, addr);
        do {
-               BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
+               BUG_ON(get_slice_psize((*tlb)->mm, addr) != mmu_huge_psize);
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
@@ -332,203 +331,13 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return __pte(old);
 }
 
-struct slb_flush_info {
-       struct mm_struct *mm;
-       u16 newareas;
-};
-
-static void flush_low_segments(void *parm)
-{
-       struct slb_flush_info *fi = parm;
-       unsigned long i;
-
-       BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_LOW_AREAS);
-
-       if (current->active_mm != fi->mm)
-               return;
-
-       /* Only need to do anything if this CPU is working in the same
-        * mm as the one which has changed */
-
-       /* update the paca copy of the context struct */
-       get_paca()->context = current->active_mm->context;
-
-       asm volatile("isync" : : : "memory");
-       for (i = 0; i < NUM_LOW_AREAS; i++) {
-               if (! (fi->newareas & (1U << i)))
-                       continue;
-               asm volatile("slbie %0"
-                            : : "r" ((i << SID_SHIFT) | SLBIE_C));
-       }
-       asm volatile("isync" : : : "memory");
-}
-
-static void flush_high_segments(void *parm)
-{
-       struct slb_flush_info *fi = parm;
-       unsigned long i, j;
-
-
-       BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_HIGH_AREAS);
-
-       if (current->active_mm != fi->mm)
-               return;
-
-       /* Only need to do anything if this CPU is working in the same
-        * mm as the one which has changed */
-
-       /* update the paca copy of the context struct */
-       get_paca()->context = current->active_mm->context;
-
-       asm volatile("isync" : : : "memory");
-       for (i = 0; i < NUM_HIGH_AREAS; i++) {
-               if (! (fi->newareas & (1U << i)))
-                       continue;
-               for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
-                       asm volatile("slbie %0"
-                                    :: "r" (((i << HTLB_AREA_SHIFT)
-                                             + (j << SID_SHIFT)) | SLBIE_C));
-       }
-       asm volatile("isync" : : : "memory");
-}
-
-static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
-{
-       unsigned long start = area << SID_SHIFT;
-       unsigned long end = (area+1) << SID_SHIFT;
-       struct vm_area_struct *vma;
-
-       BUG_ON(area >= NUM_LOW_AREAS);
-
-       /* Check no VMAs are in the region */
-       vma = find_vma(mm, start);
-       if (vma && (vma->vm_start < end))
-               return -EBUSY;
-
-       return 0;
-}
-
-static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
-{
-       unsigned long start = area << HTLB_AREA_SHIFT;
-       unsigned long end = (area+1) << HTLB_AREA_SHIFT;
-       struct vm_area_struct *vma;
-
-       BUG_ON(area >= NUM_HIGH_AREAS);
-
-       /* Hack, so that each addresses is controlled by exactly one
-        * of the high or low area bitmaps, the first high area starts
-        * at 4GB, not 0 */
-       if (start == 0)
-               start = 0x100000000UL;
-
-       /* Check no VMAs are in the region */
-       vma = find_vma(mm, start);
-       if (vma && (vma->vm_start < end))
-               return -EBUSY;
-
-       return 0;
-}
-
-static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
-{
-       unsigned long i;
-       struct slb_flush_info fi;
-
-       BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
-       BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
-
-       newareas &= ~(mm->context.low_htlb_areas);
-       if (! newareas)
-               return 0; /* The segments we want are already open */
-
-       for (i = 0; i < NUM_LOW_AREAS; i++)
-               if ((1 << i) & newareas)
-                       if (prepare_low_area_for_htlb(mm, i) != 0)
-                               return -EBUSY;
-
-       mm->context.low_htlb_areas |= newareas;
-
-       /* the context change must make it to memory before the flush,
-        * so that further SLB misses do the right thing. */
-       mb();
-
-       fi.mm = mm;
-       fi.newareas = newareas;
-       on_each_cpu(flush_low_segments, &fi, 0, 1);
-
-       return 0;
-}
-
-static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
-{
-       struct slb_flush_info fi;
-       unsigned long i;
-
-       BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
-       BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
-                    != NUM_HIGH_AREAS);
-
-       newareas &= ~(mm->context.high_htlb_areas);
-       if (! newareas)
-               return 0; /* The areas we want are already open */
-
-       for (i = 0; i < NUM_HIGH_AREAS; i++)
-               if ((1 << i) & newareas)
-                       if (prepare_high_area_for_htlb(mm, i) != 0)
-                               return -EBUSY;
-
-       mm->context.high_htlb_areas |= newareas;
-
-       /* the context change must make it to memory before the flush,
-        * so that further SLB misses do the right thing. */
-       mb();
-
-       fi.mm = mm;
-       fi.newareas = newareas;
-       on_each_cpu(flush_high_segments, &fi, 0, 1);
-
-       return 0;
-}
-
-int prepare_hugepage_range(unsigned long addr, unsigned long len, pgoff_t pgoff)
-{
-       int err = 0;
-
-       if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT))
-               return -EINVAL;
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-
-       if (addr < 0x100000000UL)
-               err = open_low_hpage_areas(current->mm,
-                                         LOW_ESID_MASK(addr, len));
-       if ((addr + len) > 0x100000000UL)
-               err = open_high_hpage_areas(current->mm,
-                                           HTLB_AREA_MASK(addr, len));
-#ifdef CONFIG_SPE_BASE
-       spu_flush_all_slbs(current->mm);
-#endif
-       if (err) {
-               printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
-                      " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
-                      addr, len,
-                      LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
-               return err;
-       }
-
-       return 0;
-}
-
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
        pte_t *ptep;
        struct page *page;
 
-       if (! in_hugepage_area(mm->context, address))
+       if (get_slice_psize(mm, address) != mmu_huge_psize)
                return ERR_PTR(-EINVAL);
 
        ptep = huge_pte_offset(mm, address);
@@ -552,359 +361,13 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
        return NULL;
 }
 
-/* Because we have an exclusive hugepage region which lies within the
- * normal user address space, we have to take special measures to make
- * non-huge mmap()s evade the hugepage reserved regions. */
-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
-                                    unsigned long len, unsigned long pgoff,
-                                    unsigned long flags)
-{
-       struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
-       unsigned long start_addr;
-
-       if (len > TASK_SIZE)
-               return -ENOMEM;
-
-       /* handle fixed mapping: prevent overlap with huge pages */
-       if (flags & MAP_FIXED) {
-               if (is_hugepage_only_range(mm, addr, len))
-                       return -EINVAL;
-               return addr;
-       }
-
-       if (addr) {
-               addr = PAGE_ALIGN(addr);
-               vma = find_vma(mm, addr);
-               if (((TASK_SIZE - len) >= addr)
-                   && (!vma || (addr+len) <= vma->vm_start)
-                   && !is_hugepage_only_range(mm, addr,len))
-                       return addr;
-       }
-       if (len > mm->cached_hole_size) {
-               start_addr = addr = mm->free_area_cache;
-       } else {
-               start_addr = addr = TASK_UNMAPPED_BASE;
-               mm->cached_hole_size = 0;
-       }
-
-full_search:
-       vma = find_vma(mm, addr);
-       while (TASK_SIZE - len >= addr) {
-               BUG_ON(vma && (addr >= vma->vm_end));
-
-               if (touches_hugepage_low_range(mm, addr, len)) {
-                       addr = ALIGN(addr+1, 1<<SID_SHIFT);
-                       vma = find_vma(mm, addr);
-                       continue;
-               }
-               if (touches_hugepage_high_range(mm, addr, len)) {
-                       addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
-                       vma = find_vma(mm, addr);
-                       continue;
-               }
-               if (!vma || addr + len <= vma->vm_start) {
-                       /*
-                        * Remember the place where we stopped the search:
-                        */
-                       mm->free_area_cache = addr + len;
-                       return addr;
-               }
-               if (addr + mm->cached_hole_size < vma->vm_start)
-                       mm->cached_hole_size = vma->vm_start - addr;
-               addr = vma->vm_end;
-               vma = vma->vm_next;
-       }
-
-       /* Make sure we didn't miss any holes */
-       if (start_addr != TASK_UNMAPPED_BASE) {
-               start_addr = addr = TASK_UNMAPPED_BASE;
-               mm->cached_hole_size = 0;
-               goto full_search;
-       }
-       return -ENOMEM;
-}
-
-/*
- * This mmap-allocator allocates new areas top-down from below the
- * stack's low limit (the base):
- *
- * Because we have an exclusive hugepage region which lies within the
- * normal user address space, we have to take special measures to make
- * non-huge mmap()s evade the hugepage reserved regions.
- */
-unsigned long
-arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
-                         const unsigned long len, const unsigned long pgoff,
-                         const unsigned long flags)
-{
-       struct vm_area_struct *vma, *prev_vma;
-       struct mm_struct *mm = current->mm;
-       unsigned long base = mm->mmap_base, addr = addr0;
-       unsigned long largest_hole = mm->cached_hole_size;
-       int first_time = 1;
-
-       /* requested length too big for entire address space */
-       if (len > TASK_SIZE)
-               return -ENOMEM;
-
-       /* handle fixed mapping: prevent overlap with huge pages */
-       if (flags & MAP_FIXED) {
-               if (is_hugepage_only_range(mm, addr, len))
-                       return -EINVAL;
-               return addr;
-       }
-
-       /* dont allow allocations above current base */
-       if (mm->free_area_cache > base)
-               mm->free_area_cache = base;
-
-       /* requesting a specific address */
-       if (addr) {
-               addr = PAGE_ALIGN(addr);
-               vma = find_vma(mm, addr);
-               if (TASK_SIZE - len >= addr &&
-                               (!vma || addr + len <= vma->vm_start)
-                               && !is_hugepage_only_range(mm, addr,len))
-                       return addr;
-       }
-
-       if (len <= largest_hole) {
-               largest_hole = 0;
-               mm->free_area_cache = base;
-       }
-try_again:
-       /* make sure it can fit in the remaining address space */
-       if (mm->free_area_cache < len)
-               goto fail;
-
-       /* either no address requested or cant fit in requested address hole */
-       addr = (mm->free_area_cache - len) & PAGE_MASK;
-       do {
-hugepage_recheck:
-               if (touches_hugepage_low_range(mm, addr, len)) {
-                       addr = (addr & ((~0) << SID_SHIFT)) - len;
-                       goto hugepage_recheck;
-               } else if (touches_hugepage_high_range(mm, addr, len)) {
-                       addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
-                       goto hugepage_recheck;
-               }
-
-               /*
-                * Lookup failure means no vma is above this address,
-                * i.e. return with success:
-                */
-               if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
-                       return addr;
-
-               /*
-                * new region fits between prev_vma->vm_end and
-                * vma->vm_start, use it:
-                */
-               if (addr+len <= vma->vm_start &&
-                         (!prev_vma || (addr >= prev_vma->vm_end))) {
-                       /* remember the address as a hint for next time */
-                       mm->cached_hole_size = largest_hole;
-                       return (mm->free_area_cache = addr);
-               } else {
-                       /* pull free_area_cache down to the first hole */
-                       if (mm->free_area_cache == vma->vm_end) {
-                               mm->free_area_cache = vma->vm_start;
-                               mm->cached_hole_size = largest_hole;
-                       }
-               }
-
-               /* remember the largest hole we saw so far */
-               if (addr + largest_hole < vma->vm_start)
-                       largest_hole = vma->vm_start - addr;
-
-               /* try just below the current vma->vm_start */
-               addr = vma->vm_start-len;
-       } while (len <= vma->vm_start);
-
-fail:
-       /*
-        * if hint left us with no space for the requested
-        * mapping then try again:
-        */
-       if (first_time) {
-               mm->free_area_cache = base;
-               largest_hole = 0;
-               first_time = 0;
-               goto try_again;
-       }
-       /*
-        * A failed mmap() very likely causes application failure,
-        * so fall back to the bottom-up function here. This scenario
-        * can happen with large stack limits and large mmap()
-        * allocations.
-        */
-       mm->free_area_cache = TASK_UNMAPPED_BASE;
-       mm->cached_hole_size = ~0UL;
-       addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-       /*
-        * Restore the topdown base:
-        */
-       mm->free_area_cache = base;
-       mm->cached_hole_size = ~0UL;
-
-       return addr;
-}
-
-static int htlb_check_hinted_area(unsigned long addr, unsigned long len)
-{
-       struct vm_area_struct *vma;
-
-       vma = find_vma(current->mm, addr);
-       if (TASK_SIZE - len >= addr &&
-           (!vma || ((addr + len) <= vma->vm_start)))
-               return 0;
-
-       return -ENOMEM;
-}
-
-static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
-{
-       unsigned long addr = 0;
-       struct vm_area_struct *vma;
-
-       vma = find_vma(current->mm, addr);
-       while (addr + len <= 0x100000000UL) {
-               BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
-
-               if (! __within_hugepage_low_range(addr, len, segmask)) {
-                       addr = ALIGN(addr+1, 1<<SID_SHIFT);
-                       vma = find_vma(current->mm, addr);
-                       continue;
-               }
-
-               if (!vma || (addr + len) <= vma->vm_start)
-                       return addr;
-               addr = ALIGN(vma->vm_end, HPAGE_SIZE);
-               /* Depending on segmask this might not be a confirmed
-                * hugepage region, so the ALIGN could have skipped
-                * some VMAs */
-               vma = find_vma(current->mm, addr);
-       }
-
-       return -ENOMEM;
-}
-
-static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
-{
-       unsigned long addr = 0x100000000UL;
-       struct vm_area_struct *vma;
-
-       vma = find_vma(current->mm, addr);
-       while (addr + len <= TASK_SIZE_USER64) {
-               BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
-
-               if (! __within_hugepage_high_range(addr, len, areamask)) {
-                       addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
-                       vma = find_vma(current->mm, addr);
-                       continue;
-               }
-
-               if (!vma || (addr + len) <= vma->vm_start)
-                       return addr;
-               addr = ALIGN(vma->vm_end, HPAGE_SIZE);
-               /* Depending on segmask this might not be a confirmed
-                * hugepage region, so the ALIGN could have skipped
-                * some VMAs */
-               vma = find_vma(current->mm, addr);
-       }
-
-       return -ENOMEM;
-}
 
 unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                        unsigned long len, unsigned long pgoff,
                                        unsigned long flags)
 {
-       int lastshift;
-       u16 areamask, curareas;
-
-       if (HPAGE_SHIFT == 0)
-               return -EINVAL;
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (len > TASK_SIZE)
-               return -ENOMEM;
-
-       if (!cpu_has_feature(CPU_FTR_16M_PAGE))
-               return -EINVAL;
-
-       /* Paranoia, caller should have dealt with this */
-       BUG_ON((addr + len)  < addr);
-
-       /* Handle MAP_FIXED */
-       if (flags & MAP_FIXED) {
-               if (prepare_hugepage_range(addr, len, pgoff))
-                       return -EINVAL;
-               return addr;
-       }
-
-       if (test_thread_flag(TIF_32BIT)) {
-               curareas = current->mm->context.low_htlb_areas;
-
-               /* First see if we can use the hint address */
-               if (addr && (htlb_check_hinted_area(addr, len) == 0)) {
-                       areamask = LOW_ESID_MASK(addr, len);
-                       if (open_low_hpage_areas(current->mm, areamask) == 0)
-                               return addr;
-               }
-
-               /* Next see if we can map in the existing low areas */
-               addr = htlb_get_low_area(len, curareas);
-               if (addr != -ENOMEM)
-                       return addr;
-
-               /* Finally go looking for areas to open */
-               lastshift = 0;
-               for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
-                    ! lastshift; areamask >>=1) {
-                       if (areamask & 1)
-                               lastshift = 1;
-
-                       addr = htlb_get_low_area(len, curareas | areamask);
-                       if ((addr != -ENOMEM)
-                           && open_low_hpage_areas(current->mm, areamask) == 0)
-                               return addr;
-               }
-       } else {
-               curareas = current->mm->context.high_htlb_areas;
-
-               /* First see if we can use the hint address */
-               /* We discourage 64-bit processes from doing hugepage
-                * mappings below 4GB (must use MAP_FIXED) */
-               if ((addr >= 0x100000000UL)
-                   && (htlb_check_hinted_area(addr, len) == 0)) {
-                       areamask = HTLB_AREA_MASK(addr, len);
-                       if (open_high_hpage_areas(current->mm, areamask) == 0)
-                               return addr;
-               }
-
-               /* Next see if we can map in the existing high areas */
-               addr = htlb_get_high_area(len, curareas);
-               if (addr != -ENOMEM)
-                       return addr;
-
-               /* Finally go looking for areas to open */
-               lastshift = 0;
-               for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
-                    ! lastshift; areamask >>=1) {
-                       if (areamask & 1)
-                               lastshift = 1;
-
-                       addr = htlb_get_high_area(len, curareas | areamask);
-                       if ((addr != -ENOMEM)
-                           && open_high_hpage_areas(current->mm, areamask) == 0)
-                               return addr;
-               }
-       }
-       printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
-              " enough areas\n");
-       return -ENOMEM;
+       return slice_get_unmapped_area(addr, len, flags,
+                                      mmu_huge_psize, 1, 0);
 }
 
 /*
index 4416d5140c53229acf03d5353f8aa6900e86b323..7312a265545f3e2f3b675595c17e6c46c44d5bbc 100644 (file)
@@ -146,21 +146,16 @@ static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
        memset(addr, 0, kmem_cache_size(cache));
 }
 
-#ifdef CONFIG_PPC_64K_PAGES
-static const unsigned int pgtable_cache_size[3] = {
-       PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE
-};
-static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
-       "pte_pmd_cache", "pmd_cache", "pgd_cache",
-};
-#else
 static const unsigned int pgtable_cache_size[2] = {
-       PTE_TABLE_SIZE, PMD_TABLE_SIZE
+       PGD_TABLE_SIZE, PMD_TABLE_SIZE
 };
 static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
-       "pgd_pte_cache", "pud_pmd_cache",
-};
+#ifdef CONFIG_PPC_64K_PAGES
+       "pgd_cache", "pmd_cache",
+#else
+       "pgd_cache", "pud_pmd_cache",
 #endif /* CONFIG_PPC_64K_PAGES */
+};
 
 #ifdef CONFIG_HUGETLB_PAGE
 /* Hugepages need one extra cache, initialized in hugetlbpage.c.  We
@@ -183,11 +178,8 @@ void pgtable_cache_init(void)
                    "for size: %08x...\n", name, i, size);
                pgtable_cache[i] = kmem_cache_create(name,
                                                     size, size,
-                                                    0,
+                                                    SLAB_PANIC,
                                                     zero_ctor,
                                                     NULL);
-               if (! pgtable_cache[i])
-                       panic("pgtable_cache_init(): could not create %s!\n",
-                             name);
        }
 }
index c4bcd7546424acff524d64536c6eb2e97854fa91..246eeea40ecec4ba0e5884fe114508bcab70dad9 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/highmem.h>
 #include <linux/initrd.h>
 #include <linux/pagemap.h>
+#include <linux/suspend.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -80,7 +81,6 @@ int page_is_ram(unsigned long pfn)
        return 0;
 #endif
 }
-EXPORT_SYMBOL(page_is_ram);
 
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                              unsigned long size, pgprot_t vma_prot)
@@ -277,6 +277,28 @@ void __init do_init_bootmem(void)
        init_bootmem_done = 1;
 }
 
+/* mark pages that don't exist as nosave */
+static int __init mark_nonram_nosave(void)
+{
+       unsigned long lmb_next_region_start_pfn,
+                     lmb_region_max_pfn;
+       int i;
+
+       for (i = 0; i < lmb.memory.cnt - 1; i++) {
+               lmb_region_max_pfn =
+                       (lmb.memory.region[i].base >> PAGE_SHIFT) +
+                       (lmb.memory.region[i].size >> PAGE_SHIFT);
+               lmb_next_region_start_pfn =
+                       lmb.memory.region[i+1].base >> PAGE_SHIFT;
+
+               if (lmb_region_max_pfn < lmb_next_region_start_pfn)
+                       register_nosave_region(lmb_region_max_pfn,
+                                              lmb_next_region_start_pfn);
+       }
+
+       return 0;
+}
+
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
@@ -308,6 +330,8 @@ void __init paging_init(void)
        max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 #endif
        free_area_init_nodes(max_zone_pfns);
+
+       mark_nonram_nosave();
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 
index 90a06ac02d5e5f35f44adf4366cc016b473463ee..7a78cdc0515a283cd13a6487b558adea435caf8b 100644 (file)
@@ -28,6 +28,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
        int index;
        int err;
+       int new_context = (mm->context.id == 0);
 
 again:
        if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
@@ -50,9 +51,18 @@ again:
        }
 
        mm->context.id = index;
+#ifdef CONFIG_PPC_MM_SLICES
+       /* The old code would re-promote on fork, we don't do that
+        * when using slices as it could cause problem promoting slices
+        * that have been forced down to 4K
+        */
+       if (new_context)
+               slice_set_user_psize(mm, mmu_virtual_psize);
+#else
        mm->context.user_psize = mmu_virtual_psize;
        mm->context.sllp = SLB_VSID_USER |
                mmu_psize_defs[mmu_virtual_psize].sllp;
+#endif
 
        return 0;
 }
index 9c4538bb04b0337f0452ac32516d8689b7c7fa46..2558c34eedaae4f3372eb30a1720f539f63e2f42 100644 (file)
@@ -40,7 +40,8 @@ extern int __map_without_bats;
 extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
-extern PTE *Hash, *Hash_end;
+struct _PTE;
+extern struct _PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
 extern unsigned int num_tlbcam_entries;
index b3a592b25ab3a7a18e31955af180ab6857763444..de45aa82d97b11c133fb14ccab6fbdf2e2bce450 100644 (file)
@@ -252,12 +252,15 @@ static int __cpuinit cpu_numa_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                numa_setup_cpu(lcpu);
                ret = NOTIFY_OK;
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                unmap_cpu_from_node(lcpu);
                break;
                ret = NOTIFY_OK;
index bca56037492732f258c8fa6603843b1102f51b0c..d8232b7a08f70043e45246e3c8018b093c7e37cc 100644 (file)
@@ -261,7 +261,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
        int err = -ENOMEM;
 
        /* Use upper 10 bits of VA to index the first level map */
-       pd = pmd_offset(pgd_offset_k(va), va);
+       pd = pmd_offset(pud_offset(pgd_offset_k(va), va), va);
        /* Use middle 10 bits of VA to index the second-level map */
        pg = pte_alloc_kernel(pd, va);
        if (pg != 0) {
@@ -354,23 +354,27 @@ int
 get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
 {
         pgd_t  *pgd;
+       pud_t   *pud;
         pmd_t  *pmd;
         pte_t  *pte;
         int     retval = 0;
 
         pgd = pgd_offset(mm, addr & PAGE_MASK);
         if (pgd) {
-                pmd = pmd_offset(pgd, addr & PAGE_MASK);
-                if (pmd_present(*pmd)) {
-                        pte = pte_offset_map(pmd, addr & PAGE_MASK);
-                        if (pte) {
-                               retval = 1;
-                               *ptep = pte;
-                               if (pmdp)
-                                       *pmdp = pmd;
-                               /* XXX caller needs to do pte_unmap, yuck */
-                        }
-                }
+               pud = pud_offset(pgd, addr & PAGE_MASK);
+               if (pud && pud_present(*pud)) {
+                       pmd = pmd_offset(pud, addr & PAGE_MASK);
+                       if (pmd_present(*pmd)) {
+                               pte = pte_offset_map(pmd, addr & PAGE_MASK);
+                               if (pte) {
+                                       retval = 1;
+                                       *ptep = pte;
+                                       if (pmdp)
+                                               *pmdp = pmd;
+                                       /* XXX caller needs to do pte_unmap, yuck */
+                               }
+                       }
+               }
         }
         return(retval);
 }
index 05066674a7a02fa2b07835d3068c15e951013173..ec1421a20aaab96d94f6ea162066a95df81fd602 100644 (file)
@@ -185,7 +185,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 
        if (Hash == 0)
                return;
-       pmd = pmd_offset(pgd_offset(mm, ea), ea);
+       pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea);
        if (!pmd_none(*pmd))
                add_hash_page(mm->context.id, ea, pmd_val(*pmd));
 }
index 224e960650a09ce3e1face7057fd8643d58a9e0d..304375a735747cfc868f67cfba4fc6715809b6c2 100644 (file)
@@ -198,12 +198,6 @@ void slb_initialize(void)
        static int slb_encoding_inited;
        extern unsigned int *slb_miss_kernel_load_linear;
        extern unsigned int *slb_miss_kernel_load_io;
-#ifdef CONFIG_HUGETLB_PAGE
-       extern unsigned int *slb_miss_user_load_huge;
-       unsigned long huge_llp;
-
-       huge_llp = mmu_psize_defs[mmu_huge_psize].sllp;
-#endif
 
        /* Prepare our SLB miss handler based on our page size */
        linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
@@ -220,11 +214,6 @@ void slb_initialize(void)
 
                DBG("SLB: linear  LLP = %04x\n", linear_llp);
                DBG("SLB: io      LLP = %04x\n", io_llp);
-#ifdef CONFIG_HUGETLB_PAGE
-               patch_slb_encoding(slb_miss_user_load_huge,
-                                  SLB_VSID_USER | huge_llp);
-               DBG("SLB: huge    LLP = %04x\n", huge_llp);
-#endif
        }
 
        get_paca()->stab_rr = SLB_NUM_BOLTED;
index b10e4707d7c1396f858f43ba4f9f30eb6d233072..cd1a93d4948ca85868dd943a60667f541229a26e 100644 (file)
@@ -82,31 +82,45 @@ _GLOBAL(slb_miss_kernel_load_io)
        srdi.   r9,r10,USER_ESID_BITS
        bne-    8f                      /* invalid ea bits set */
 
-       /* Figure out if the segment contains huge pages */
-#ifdef CONFIG_HUGETLB_PAGE
-BEGIN_FTR_SECTION
-       b       1f
-END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
+
+       /* when using slices, we extract the psize off the slice bitmaps
+        * and then we need to get the sllp encoding off the mmu_psize_defs
+        * array.
+        *
+        * XXX This is a bit inefficient especially for the normal case,
+        * so we should try to implement a fast path for the standard page
+        * size using the old sllp value so we avoid the array. We cannot
+        * really do dynamic patching unfortunately as processes might flip
+        * between 4k and 64k standard page size
+        */
+#ifdef CONFIG_PPC_MM_SLICES
        cmpldi  r10,16
 
-       lhz     r9,PACALOWHTLBAREAS(r13)
-       mr      r11,r10
+       /* Get the slice index * 4 in r11 and matching slice size mask in r9 */
+       ld      r9,PACALOWSLICESPSIZE(r13)
+       sldi    r11,r10,2
        blt     5f
+       ld      r9,PACAHIGHSLICEPSIZE(r13)
+       srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
+       andi.   r11,r11,0x3c
 
-       lhz     r9,PACAHIGHHTLBAREAS(r13)
-       srdi    r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT)
-
-5:     srd     r9,r9,r11
-       andi.   r9,r9,1
-       beq     1f
-_GLOBAL(slb_miss_user_load_huge)
-       li      r11,0
-       b       2f
-1:
-#endif /* CONFIG_HUGETLB_PAGE */
+5:     /* Extract the psize and multiply to get an array offset */
+       srd     r9,r9,r11
+       andi.   r9,r9,0xf
+       mulli   r9,r9,MMUPSIZEDEFSIZE
 
+       /* Now get to the array and obtain the sllp
+        */
+       ld      r11,PACATOC(r13)
+       ld      r11,mmu_psize_defs@got(r11)
+       add     r11,r11,r9
+       ld      r11,MMUPSIZESLLP(r11)
+       ori     r11,r11,SLB_VSID_USER
+#else
+       /* paca context sllp already contains the SLB_VSID_USER bits */
        lhz     r11,PACACONTEXTSLLP(r13)
-2:
+#endif /* CONFIG_PPC_MM_SLICES */
+
        ld      r9,PACACONTEXTID(r13)
        rldimi  r10,r9,USER_ESID_BITS,0
        b       slb_finish_load
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
new file mode 100644 (file)
index 0000000..f833dba
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ * address space "slices" (meta-segments) support
+ *
+ * Copyright (C) 2007 Benjamin Herrenschmidt, IBM Corporation.
+ *
+ * Based on hugetlb implementation
+ *
+ * Copyright (C) 2003 David Gibson, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <asm/mman.h>
+#include <asm/mmu.h>
+#include <asm/spu.h>
+
+static spinlock_t slice_convert_lock = SPIN_LOCK_UNLOCKED;
+
+
+#ifdef DEBUG
+int _slice_debug = 1;
+
+static void slice_print_mask(const char *label, struct slice_mask mask)
+{
+       char    *p, buf[16 + 3 + 16 + 1];
+       int     i;
+
+       if (!_slice_debug)
+               return;
+       p = buf;
+       for (i = 0; i < SLICE_NUM_LOW; i++)
+               *(p++) = (mask.low_slices & (1 << i)) ? '1' : '0';
+       *(p++) = ' ';
+       *(p++) = '-';
+       *(p++) = ' ';
+       for (i = 0; i < SLICE_NUM_HIGH; i++)
+               *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0';
+       *(p++) = 0;
+
+       printk(KERN_DEBUG "%s:%s\n", label, buf);
+}
+
+#define slice_dbg(fmt...) do { if (_slice_debug) pr_debug(fmt); } while(0)
+
+#else
+
+static void slice_print_mask(const char *label, struct slice_mask mask) {}
+#define slice_dbg(fmt...)
+
+#endif
+
+static struct slice_mask slice_range_to_mask(unsigned long start,
+                                            unsigned long len)
+{
+       unsigned long end = start + len - 1;
+       struct slice_mask ret = { 0, 0 };
+
+       if (start < SLICE_LOW_TOP) {
+               unsigned long mend = min(end, SLICE_LOW_TOP);
+               unsigned long mstart = min(start, SLICE_LOW_TOP);
+
+               ret.low_slices = (1u << (GET_LOW_SLICE_INDEX(mend) + 1))
+                       - (1u << GET_LOW_SLICE_INDEX(mstart));
+       }
+
+       if ((start + len) > SLICE_LOW_TOP)
+               ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1))
+                       - (1u << GET_HIGH_SLICE_INDEX(start));
+
+       return ret;
+}
+
+static int slice_area_is_free(struct mm_struct *mm, unsigned long addr,
+                             unsigned long len)
+{
+       struct vm_area_struct *vma;
+
+       if ((mm->task_size - len) < addr)
+               return 0;
+       vma = find_vma(mm, addr);
+       return (!vma || (addr + len) <= vma->vm_start);
+}
+
+static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice)
+{
+       return !slice_area_is_free(mm, slice << SLICE_LOW_SHIFT,
+                                  1ul << SLICE_LOW_SHIFT);
+}
+
+static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice)
+{
+       unsigned long start = slice << SLICE_HIGH_SHIFT;
+       unsigned long end = start + (1ul << SLICE_HIGH_SHIFT);
+
+       /* Hack, so that each addresses is controlled by exactly one
+        * of the high or low area bitmaps, the first high area starts
+        * at 4GB, not 0 */
+       if (start == 0)
+               start = SLICE_LOW_TOP;
+
+       return !slice_area_is_free(mm, start, end - start);
+}
+
+static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
+{
+       struct slice_mask ret = { 0, 0 };
+       unsigned long i;
+
+       for (i = 0; i < SLICE_NUM_LOW; i++)
+               if (!slice_low_has_vma(mm, i))
+                       ret.low_slices |= 1u << i;
+
+       if (mm->task_size <= SLICE_LOW_TOP)
+               return ret;
+
+       for (i = 0; i < SLICE_NUM_HIGH; i++)
+               if (!slice_high_has_vma(mm, i))
+                       ret.high_slices |= 1u << i;
+
+       return ret;
+}
+
+static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
+{
+       struct slice_mask ret = { 0, 0 };
+       unsigned long i;
+       u64 psizes;
+
+       psizes = mm->context.low_slices_psize;
+       for (i = 0; i < SLICE_NUM_LOW; i++)
+               if (((psizes >> (i * 4)) & 0xf) == psize)
+                       ret.low_slices |= 1u << i;
+
+       psizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++)
+               if (((psizes >> (i * 4)) & 0xf) == psize)
+                       ret.high_slices |= 1u << i;
+
+       return ret;
+}
+
+static int slice_check_fit(struct slice_mask mask, struct slice_mask available)
+{
+       return (mask.low_slices & available.low_slices) == mask.low_slices &&
+               (mask.high_slices & available.high_slices) == mask.high_slices;
+}
+
+static void slice_flush_segments(void *parm)
+{
+       struct mm_struct *mm = parm;
+       unsigned long flags;
+
+       if (mm != current->active_mm)
+               return;
+
+       /* update the paca copy of the context struct */
+       get_paca()->context = current->active_mm->context;
+
+       local_irq_save(flags);
+       slb_flush_and_rebolt();
+       local_irq_restore(flags);
+}
+
+static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
+{
+       /* Write the new slice psize bits */
+       u64 lpsizes, hpsizes;
+       unsigned long i, flags;
+
+       slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
+       slice_print_mask(" mask", mask);
+
+       /* We need to use a spinlock here to protect against
+        * concurrent 64k -> 4k demotion ...
+        */
+       spin_lock_irqsave(&slice_convert_lock, flags);
+
+       lpsizes = mm->context.low_slices_psize;
+       for (i = 0; i < SLICE_NUM_LOW; i++)
+               if (mask.low_slices & (1u << i))
+                       lpsizes = (lpsizes & ~(0xful << (i * 4))) |
+                               (((unsigned long)psize) << (i * 4));
+
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++)
+               if (mask.high_slices & (1u << i))
+                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
+                               (((unsigned long)psize) << (i * 4));
+
+       mm->context.low_slices_psize = lpsizes;
+       mm->context.high_slices_psize = hpsizes;
+
+       slice_dbg(" lsps=%lx, hsps=%lx\n",
+                 mm->context.low_slices_psize,
+                 mm->context.high_slices_psize);
+
+       spin_unlock_irqrestore(&slice_convert_lock, flags);
+       mb();
+
+       /* XXX this is sub-optimal but will do for now */
+       on_each_cpu(slice_flush_segments, mm, 0, 1);
+#ifdef CONFIG_SPU_BASE
+       spu_flush_all_slbs(mm);
+#endif
+}
+
+static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
+                                             unsigned long len,
+                                             struct slice_mask available,
+                                             int psize, int use_cache)
+{
+       struct vm_area_struct *vma;
+       unsigned long start_addr, addr;
+       struct slice_mask mask;
+       int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
+
+       if (use_cache) {
+               if (len <= mm->cached_hole_size) {
+                       start_addr = addr = TASK_UNMAPPED_BASE;
+                       mm->cached_hole_size = 0;
+               } else
+                       start_addr = addr = mm->free_area_cache;
+       } else
+               start_addr = addr = TASK_UNMAPPED_BASE;
+
+full_search:
+       for (;;) {
+               addr = _ALIGN_UP(addr, 1ul << pshift);
+               if ((TASK_SIZE - len) < addr)
+                       break;
+               vma = find_vma(mm, addr);
+               BUG_ON(vma && (addr >= vma->vm_end));
+
+               mask = slice_range_to_mask(addr, len);
+               if (!slice_check_fit(mask, available)) {
+                       if (addr < SLICE_LOW_TOP)
+                               addr = _ALIGN_UP(addr + 1,  1ul << SLICE_LOW_SHIFT);
+                       else
+                               addr = _ALIGN_UP(addr + 1,  1ul << SLICE_HIGH_SHIFT);
+                       continue;
+               }
+               if (!vma || addr + len <= vma->vm_start) {
+                       /*
+                        * Remember the place where we stopped the search:
+                        */
+                       if (use_cache)
+                               mm->free_area_cache = addr + len;
+                       return addr;
+               }
+               if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+               addr = vma->vm_end;
+       }
+
+       /* Make sure we didn't miss any holes */
+       if (use_cache && start_addr != TASK_UNMAPPED_BASE) {
+               start_addr = addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
+               goto full_search;
+       }
+       return -ENOMEM;
+}
+
+static unsigned long slice_find_area_topdown(struct mm_struct *mm,
+                                            unsigned long len,
+                                            struct slice_mask available,
+                                            int psize, int use_cache)
+{
+       struct vm_area_struct *vma;
+       unsigned long addr;
+       struct slice_mask mask;
+       int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
+
+       /* check if free_area_cache is useful for us */
+       if (use_cache) {
+               if (len <= mm->cached_hole_size) {
+                       mm->cached_hole_size = 0;
+                       mm->free_area_cache = mm->mmap_base;
+               }
+
+               /* either no address requested or can't fit in requested
+                * address hole
+                */
+               addr = mm->free_area_cache;
+
+               /* make sure it can fit in the remaining address space */
+               if (addr > len) {
+                       addr = _ALIGN_DOWN(addr - len, 1ul << pshift);
+                       mask = slice_range_to_mask(addr, len);
+                       if (slice_check_fit(mask, available) &&
+                           slice_area_is_free(mm, addr, len))
+                                       /* remember the address as a hint for
+                                        * next time
+                                        */
+                                       return (mm->free_area_cache = addr);
+               }
+       }
+
+       addr = mm->mmap_base;
+       while (addr > len) {
+               /* Go down by chunk size */
+               addr = _ALIGN_DOWN(addr - len, 1ul << pshift);
+
+               /* Check for hit with different page size */
+               mask = slice_range_to_mask(addr, len);
+               if (!slice_check_fit(mask, available)) {
+                       if (addr < SLICE_LOW_TOP)
+                               addr = _ALIGN_DOWN(addr, 1ul << SLICE_LOW_SHIFT);
+                       else if (addr < (1ul << SLICE_HIGH_SHIFT))
+                               addr = SLICE_LOW_TOP;
+                       else
+                               addr = _ALIGN_DOWN(addr, 1ul << SLICE_HIGH_SHIFT);
+                       continue;
+               }
+
+               /*
+                * Lookup failure means no vma is above this address,
+                * else if new region fits below vma->vm_start,
+                * return with success:
+                */
+               vma = find_vma(mm, addr);
+               if (!vma || (addr + len) <= vma->vm_start) {
+                       /* remember the address as a hint for next time */
+                       if (use_cache)
+                               mm->free_area_cache = addr;
+                       return addr;
+               }
+
+               /* remember the largest hole we saw so far */
+               if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+
+               /* try just below the current vma->vm_start */
+               addr = vma->vm_start;
+       }
+
+       /*
+        * A failed mmap() very likely causes application failure,
+        * so fall back to the bottom-up function here. This scenario
+        * can happen with large stack limits and large mmap()
+        * allocations.
+        */
+       addr = slice_find_area_bottomup(mm, len, available, psize, 0);
+
+       /*
+        * Restore the topdown base:
+        */
+       if (use_cache) {
+               mm->free_area_cache = mm->mmap_base;
+               mm->cached_hole_size = ~0UL;
+       }
+
+       return addr;
+}
+
+
+static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
+                                    struct slice_mask mask, int psize,
+                                    int topdown, int use_cache)
+{
+       if (topdown)
+               return slice_find_area_topdown(mm, len, mask, psize, use_cache);
+       else
+               return slice_find_area_bottomup(mm, len, mask, psize, use_cache);
+}
+
+unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
+                                     unsigned long flags, unsigned int psize,
+                                     int topdown, int use_cache)
+{
+       struct slice_mask mask;
+       struct slice_mask good_mask;
+       struct slice_mask potential_mask = {0,0} /* silence stupid warning */;
+       int pmask_set = 0;
+       int fixed = (flags & MAP_FIXED);
+       int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
+       struct mm_struct *mm = current->mm;
+
+       /* Sanity checks */
+       BUG_ON(mm->task_size == 0);
+
+       slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize);
+       slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d, use_cache=%d\n",
+                 addr, len, flags, topdown, use_cache);
+
+       if (len > mm->task_size)
+               return -ENOMEM;
+       if (fixed && (addr & ((1ul << pshift) - 1)))
+               return -EINVAL;
+       if (fixed && addr > (mm->task_size - len))
+               return -EINVAL;
+
+       /* If hint, make sure it matches our alignment restrictions */
+       if (!fixed && addr) {
+               addr = _ALIGN_UP(addr, 1ul << pshift);
+               slice_dbg(" aligned addr=%lx\n", addr);
+       }
+
+       /* First makeup a "good" mask of slices that have the right size
+        * already
+        */
+       good_mask = slice_mask_for_size(mm, psize);
+       slice_print_mask(" good_mask", good_mask);
+
+       /* First check hint if it's valid or if we have MAP_FIXED */
+       if ((addr != 0 || fixed) && (mm->task_size - len) >= addr) {
+
+               /* Don't bother with hint if it overlaps a VMA */
+               if (!fixed && !slice_area_is_free(mm, addr, len))
+                       goto search;
+
+               /* Build a mask for the requested range */
+               mask = slice_range_to_mask(addr, len);
+               slice_print_mask(" mask", mask);
+
+               /* Check if we fit in the good mask. If we do, we just return,
+                * nothing else to do
+                */
+               if (slice_check_fit(mask, good_mask)) {
+                       slice_dbg(" fits good !\n");
+                       return addr;
+               }
+
+               /* We don't fit in the good mask, check what other slices are
+                * empty and thus can be converted
+                */
+               potential_mask = slice_mask_for_free(mm);
+               potential_mask.low_slices |= good_mask.low_slices;
+               potential_mask.high_slices |= good_mask.high_slices;
+               pmask_set = 1;
+               slice_print_mask(" potential", potential_mask);
+               if (slice_check_fit(mask, potential_mask)) {
+                       slice_dbg(" fits potential !\n");
+                       goto convert;
+               }
+       }
+
+       /* If we have MAP_FIXED and failed the above step, then error out */
+       if (fixed)
+               return -EBUSY;
+
+ search:
+       slice_dbg(" search...\n");
+
+       /* Now let's see if we can find something in the existing slices
+        * for that size
+        */
+       addr = slice_find_area(mm, len, good_mask, psize, topdown, use_cache);
+       if (addr != -ENOMEM) {
+               /* Found within the good mask, we don't have to setup,
+                * we thus return directly
+                */
+               slice_dbg(" found area at 0x%lx\n", addr);
+               return addr;
+       }
+
+       /* Won't fit, check what can be converted */
+       if (!pmask_set) {
+               potential_mask = slice_mask_for_free(mm);
+               potential_mask.low_slices |= good_mask.low_slices;
+               potential_mask.high_slices |= good_mask.high_slices;
+               pmask_set = 1;
+               slice_print_mask(" potential", potential_mask);
+       }
+
+       /* Now let's see if we can find something in the existing slices
+        * for that size
+        */
+       addr = slice_find_area(mm, len, potential_mask, psize, topdown,
+                              use_cache);
+       if (addr == -ENOMEM)
+               return -ENOMEM;
+
+       mask = slice_range_to_mask(addr, len);
+       slice_dbg(" found potential area at 0x%lx\n", addr);
+       slice_print_mask(" mask", mask);
+
+ convert:
+       slice_convert(mm, mask, psize);
+       return addr;
+
+}
+EXPORT_SYMBOL_GPL(slice_get_unmapped_area);
+
+unsigned long arch_get_unmapped_area(struct file *filp,
+                                    unsigned long addr,
+                                    unsigned long len,
+                                    unsigned long pgoff,
+                                    unsigned long flags)
+{
+       return slice_get_unmapped_area(addr, len, flags,
+                                      current->mm->context.user_psize,
+                                      0, 1);
+}
+
+unsigned long arch_get_unmapped_area_topdown(struct file *filp,
+                                            const unsigned long addr0,
+                                            const unsigned long len,
+                                            const unsigned long pgoff,
+                                            const unsigned long flags)
+{
+       return slice_get_unmapped_area(addr0, len, flags,
+                                      current->mm->context.user_psize,
+                                      1, 1);
+}
+
+unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
+{
+       u64 psizes;
+       int index;
+
+       if (addr < SLICE_LOW_TOP) {
+               psizes = mm->context.low_slices_psize;
+               index = GET_LOW_SLICE_INDEX(addr);
+       } else {
+               psizes = mm->context.high_slices_psize;
+               index = GET_HIGH_SLICE_INDEX(addr);
+       }
+
+       return (psizes >> (index * 4)) & 0xf;
+}
+EXPORT_SYMBOL_GPL(get_slice_psize);
+
+/*
+ * This is called by hash_page when it needs to do a lazy conversion of
+ * an address space from real 64K pages to combo 4K pages (typically
+ * when hitting a non cacheable mapping on a processor or hypervisor
+ * that won't allow them for 64K pages).
+ *
+ * This is also called in init_new_context() to change back the user
+ * psize from whatever the parent context had it set to
+ *
+ * This function will only change the content of the {low,high)_slice_psize
+ * masks, it will not flush SLBs as this shall be handled lazily by the
+ * caller.
+ */
+void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
+{
+       unsigned long flags, lpsizes, hpsizes;
+       unsigned int old_psize;
+       int i;
+
+       slice_dbg("slice_set_user_psize(mm=%p, psize=%d)\n", mm, psize);
+
+       spin_lock_irqsave(&slice_convert_lock, flags);
+
+       old_psize = mm->context.user_psize;
+       slice_dbg(" old_psize=%d\n", old_psize);
+       if (old_psize == psize)
+               goto bail;
+
+       mm->context.user_psize = psize;
+       wmb();
+
+       lpsizes = mm->context.low_slices_psize;
+       for (i = 0; i < SLICE_NUM_LOW; i++)
+               if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
+                       lpsizes = (lpsizes & ~(0xful << (i * 4))) |
+                               (((unsigned long)psize) << (i * 4));
+
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++)
+               if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
+                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
+                               (((unsigned long)psize) << (i * 4));
+
+       mm->context.low_slices_psize = lpsizes;
+       mm->context.high_slices_psize = hpsizes;
+
+       slice_dbg(" lsps=%lx, hsps=%lx\n",
+                 mm->context.low_slices_psize,
+                 mm->context.high_slices_psize);
+
+ bail:
+       spin_unlock_irqrestore(&slice_convert_lock, flags);
+}
+
+/*
+ * is_hugepage_only_range() is used by generic code to verify wether
+ * a normal mmap mapping (non hugetlbfs) is valid on a given area.
+ *
+ * until the generic code provides a more generic hook and/or starts
+ * calling arch get_unmapped_area for MAP_FIXED (which our implementation
+ * here knows how to deal with), we hijack it to keep standard mappings
+ * away from us.
+ *
+ * because of that generic code limitation, MAP_FIXED mapping cannot
+ * "convert" back a slice with no VMAs to the standard page size, only
+ * get_unmapped_area() can. It would be possible to fix it here but I
+ * prefer working on fixing the generic code instead.
+ *
+ * WARNING: This will not work if hugetlbfs isn't enabled since the
+ * generic code will redefine that function as 0 in that. This is ok
+ * for now as we only use slices with hugetlbfs enabled. This should
+ * be fixed as the generic code gets fixed.
+ */
+int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
+                          unsigned long len)
+{
+       struct slice_mask mask, available;
+
+       mask = slice_range_to_mask(addr, len);
+       available = slice_mask_for_size(mm, mm->context.user_psize);
+
+#if 0 /* too verbose */
+       slice_dbg("is_hugepage_only_range(mm=%p, addr=%lx, len=%lx)\n",
+                mm, addr, len);
+       slice_print_mask(" mask", mask);
+       slice_print_mask(" available", available);
+#endif
+       return !slice_check_fit(mask, available);
+}
+
index eeeacab548e655f79f2f0ea90c86d16dd2b47ffd..132c6bc66ce1405f976a12e1d419e6e05c47e7f8 100644 (file)
@@ -227,7 +227,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
  * the first (bolted) segment, so that do_stab_bolted won't get a
  * recursive segment miss on the segment table itself.
  */
-void stabs_alloc(void)
+void __init stabs_alloc(void)
 {
        int cpu;
 
index 925ff70be8ba93ed9133a1f123067ff8527e9c9f..6a69417cbc0ef3cf0eaba041081b2f3a53ae5f96 100644 (file)
@@ -111,7 +111,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start,
        if (start >= end)
                return;
        end = (end - 1) | ~PAGE_MASK;
-       pmd = pmd_offset(pgd_offset(mm, start), start);
+       pmd = pmd_offset(pud_offset(pgd_offset(mm, start), start), start);
        for (;;) {
                pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
                if (pmd_end > end)
@@ -169,7 +169,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
                return;
        }
        mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
-       pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
+       pmd = pmd_offset(pud_offset(pgd_offset(mm, vmaddr), vmaddr), vmaddr);
        if (!pmd_none(*pmd))
                flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
        FINISH_FLUSH;
index fd8d08c325ebecca3083759360cbf6e6c30b1e8e..2bfc4d7e1aa259b37462735c97e299c67d5d9a3e 100644 (file)
@@ -143,16 +143,22 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
         */
        addr &= PAGE_MASK;
 
-       /* Get page size (maybe move back to caller) */
+       /* Get page size (maybe move back to caller).
+        *
+        * NOTE: when using special 64K mappings in 4K environment like
+        * for SPEs, we obtain the page size from the slice, which thus
+        * must still exist (and thus the VMA not reused) at the time
+        * of this call
+        */
        if (huge) {
 #ifdef CONFIG_HUGETLB_PAGE
                psize = mmu_huge_psize;
 #else
                BUG();
-               psize = pte_pagesize_index(pte); /* shutup gcc */
+               psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
 #endif
        } else
-               psize = pte_pagesize_index(pte);
+               psize = pte_pagesize_index(mm, addr, pte);
 
        /* Build full vaddr */
        if (!is_kernel_addr(addr)) {
index 626b29f38304e3c8339e61b52ddb619a5c5dd0f5..c29293befba9b69c0e0f673c82869e4343802230 100644 (file)
@@ -747,7 +747,7 @@ cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr)
                 * counter value etc.) are not copied to the actual registers
                 * until the performance monitor is enabled.  In order to get
                 * this to work as desired, the permormance monitor needs to
-                * be disabled while writting to the latches.  This is a
+                * be disabled while writing to the latches.  This is a
                 * HW design issue.
                 */
                cbe_enable_pm(cpu);
diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
new file mode 100644 (file)
index 0000000..42eabf8
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __POWERPC_PLATFORMS_44X_44X_H
+#define __POWERPC_PLATFORMS_44X_44X_H
+
+extern u8 as1_readb(volatile u8 __iomem  *addr);
+extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
+extern void ppc44x_reset_system(char *cmd);
+
+#endif /* __POWERPC_PLATFORMS_44X_44X_H */
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
new file mode 100644 (file)
index 0000000..8e66949
--- /dev/null
@@ -0,0 +1,56 @@
+#config BAMBOO
+#      bool "Bamboo"
+#      depends on 44x
+#      default n
+#      select 440EP
+#      help
+#        This option enables support for the IBM PPC440EP evaluation board.
+
+config EBONY
+       bool "Ebony"
+       depends on 44x
+       default y
+       select 440GP
+       help
+         This option enables support for the IBM PPC440GP evaluation board.
+
+#config LUAN
+#      bool "Luan"
+#      depends on 44x
+#      default n
+#      select 440SP
+#      help
+#        This option enables support for the IBM PPC440SP evaluation board.
+
+#config OCOTEA
+#      bool "Ocotea"
+#      depends on 44x
+#      default n
+#      select 440GX
+#      help
+#        This option enables support for the IBM PPC440GX evaluation board.
+
+# 44x specific CPU modules, selected based on the board above.
+config 440EP
+       bool
+       select PPC_FPU
+       select IBM440EP_ERR42
+
+config 440GP
+       bool
+       select IBM_NEW_EMAC_ZMII
+
+config 440GX
+       bool
+
+config 440SP
+       bool
+
+config 440A
+       bool
+       depends on 440GX
+       default y
+
+# 44x errata/workaround config symbols, selected by the CPU models above
+config IBM440EP_ERR42
+       bool
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
new file mode 100644 (file)
index 0000000..41d0a18
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_44x)      := misc_44x.o
+obj-$(CONFIG_EBONY)    += ebony.o
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
new file mode 100644 (file)
index 0000000..ad526ea
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Ebony board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003-2005 Zultys Technologies
+ *
+ * Rewritten and ported to the merged powerpc tree:
+ * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+#include <asm/of_platform.h>
+
+#include "44x.h"
+
+static struct of_device_id ebony_of_bus[] = {
+       { .type = "ibm,plb", },
+       { .type = "ibm,opb", },
+       { .type = "ibm,ebc", },
+       {},
+};
+
+static int __init ebony_device_probe(void)
+{
+       if (!machine_is(ebony))
+               return 0;
+
+       of_platform_bus_probe(NULL, ebony_of_bus, NULL);
+
+       return 0;
+}
+device_initcall(ebony_device_probe);
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init ebony_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
+               return 0;
+
+       return 1;
+}
+
+static void __init ebony_setup_arch(void)
+{
+}
+
+define_machine(ebony) {
+       .name                   = "Ebony",
+       .probe                  = ebony_probe,
+       .setup_arch             = ebony_setup_arch,
+       .progress               = udbg_progress,
+       .init_IRQ               = uic_init_tree,
+       .get_irq                = uic_get_irq,
+       .restart                = ppc44x_reset_system,
+       .calibrate_decr         = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S
new file mode 100644 (file)
index 0000000..3bce71d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This file contains miscellaneous low-level functions for PPC 44x.
+ *    Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+
+       .text
+
+/*
+ * Do an IO access in AS1
+ */
+_GLOBAL(as1_readb)
+       mfmsr   r7
+       ori     r0,r7,MSR_DS
+       sync
+       mtmsr   r0
+       sync
+       isync
+       lbz     r3,0(r3)
+       sync
+       mtmsr   r7
+       sync
+       isync
+       blr
+
+_GLOBAL(as1_writeb)
+       mfmsr   r7
+       ori     r0,r7,MSR_DS
+       sync
+       mtmsr   r0
+       sync
+       isync
+       stb     r3,0(r4)
+       sync
+       mtmsr   r7
+       sync
+       isync
+       blr
+
+/*
+ * void ppc44x_reset_system(char *cmd)
+ *
+ * At present, this routine just applies a system reset.
+ */
+_GLOBAL(ppc44x_reset_system)
+       mfspr   r13,SPRN_DBCR0
+       oris    r13,r13,DBCR0_RST_SYSTEM@h
+       mtspr   SPRN_DBCR0,r13
+       b       .                       /* Just in case the reset doesn't work */
index bc4aa4a80a124c5501b1dd9d60698052b9bbd2bb..3ffaa066c2c8b5660863d76647e8500b40d84235 100644 (file)
@@ -1,5 +1,6 @@
 config PPC_MPC52xx
        bool
+       select FSL_SOC
        default n
 
 config PPC_MPC5200
index 07cdbcacf1569348a7fffed925225640830e8c3c..b91e39c84d4687ff5559d05e3e5721037e5458ce 100644 (file)
@@ -8,3 +8,5 @@ endif
 
 obj-$(CONFIG_PPC_EFIKA)                += efika.o
 obj-$(CONFIG_PPC_LITE5200)     += lite5200.o
+
+obj-$(CONFIG_PM)               += mpc52xx_sleep.o mpc52xx_pm.o
index a6bba97314eb45a1248e0446753f86f57edf2369..f591a9fc19b9db179777d3f35f9597e00b19807c 100644 (file)
@@ -184,6 +184,16 @@ static void efika_show_cpuinfo(struct seq_file *m)
        of_node_put(root);
 }
 
+#ifdef CONFIG_PM
+static void efika_suspend_prepare(void __iomem *mbar)
+{
+       u8 pin = 4;     /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
+       u8 level = 1;   /* wakeup on high level */
+       /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
+       mpc52xx_set_wakeup_gpio(pin, level);
+}
+#endif
+
 static void __init efika_setup_arch(void)
 {
        rtas_initialize();
@@ -199,6 +209,11 @@ static void __init efika_setup_arch(void)
 
        efika_pcisetup();
 
+#ifdef CONFIG_PM
+       mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare;
+       mpc52xx_pm_init();
+#endif
+
        if (ppc_md.progress)
                ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
 }
index 8e2646ac417bf788d5223938decdf17b5c00d0b0..1cfc00dfb99a656f488249ea71adbe258084832b 100644 (file)
@@ -85,6 +85,28 @@ error:
        iounmap(gpio);
 }
 
+#ifdef CONFIG_PM
+static u32 descr_a;
+static void lite5200_suspend_prepare(void __iomem *mbar)
+{
+       u8 pin = 1;     /* GPIO_WKUP_1 (GPIO_PSC2_4) */
+       u8 level = 0;   /* wakeup on low level */
+       mpc52xx_set_wakeup_gpio(pin, level);
+
+       /*
+        * power down usb port
+        * this needs to be called before of-ohci suspend code
+        */
+       descr_a = in_be32(mbar + 0x1048);
+       out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100);
+}
+
+static void lite5200_resume_finish(void __iomem *mbar)
+{
+       out_be32(mbar + 0x1048, descr_a);
+}
+#endif
+
 static void __init lite5200_setup_arch(void)
 {
        struct device_node *np;
@@ -107,6 +129,12 @@ static void __init lite5200_setup_arch(void)
        mpc52xx_setup_cpu();    /* Generic */
        lite5200_setup_cpu();   /* Platorm specific */
 
+#ifdef CONFIG_PM
+       mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
+       mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
+       mpc52xx_pm_init();
+#endif
+
 #ifdef CONFIG_PCI
        np = of_find_node_by_type(NULL, "pci");
        if (np) {
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
new file mode 100644 (file)
index 0000000..fd40044
--- /dev/null
@@ -0,0 +1,191 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/mpc52xx.h>
+
+#include "mpc52xx_pic.h"
+
+
+/* these are defined in mpc52xx_sleep.S, and only used here */
+extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
+               struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_ds_sram(void);
+extern const long mpc52xx_ds_sram_size;
+extern void mpc52xx_ds_cached(void);
+extern const long mpc52xx_ds_cached_size;
+
+static void __iomem *mbar;
+static void __iomem *sdram;
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_gpio_wkup __iomem *gpiow;
+static void *sram;
+static int sram_size;
+
+struct mpc52xx_suspend mpc52xx_suspend;
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
+{
+       u16 tmp;
+
+       /* enable gpio */
+       out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin));
+       /* set as input */
+       out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin));
+       /* enable deep sleep interrupt */
+       out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin));
+       /* low/high level creates wakeup interrupt */
+       tmp = in_be16(&gpiow->wkup_itype);
+       tmp &= ~(0x3 << (pin * 2));
+       tmp |= (!level + 1) << (pin * 2);
+       out_be16(&gpiow->wkup_itype, tmp);
+       /* master enable */
+       out_8(&gpiow->wkup_maste, 1);
+
+       return 0;
+}
+
+int mpc52xx_pm_prepare(suspend_state_t state)
+{
+       if (state != PM_SUSPEND_STANDBY)
+               return -EINVAL;
+
+       /* map the whole register space */
+       mbar = mpc52xx_find_and_map("mpc5200");
+       if (!mbar) {
+               printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+               return -ENOSYS;
+       }
+       /* these offsets are from mpc5200 users manual */
+       sdram   = mbar + 0x100;
+       cdm     = mbar + 0x200;
+       intr    = mbar + 0x500;
+       gpiow   = mbar + 0xc00;
+       sram    = mbar + 0x8000;        /* Those will be handled by the */
+       sram_size = 0x4000;             /* bestcomm driver soon */
+
+       /* call board suspend code, if applicable */
+       if (mpc52xx_suspend.board_suspend_prepare)
+               mpc52xx_suspend.board_suspend_prepare(mbar);
+       else {
+               printk(KERN_ALERT "%s: %i don't know how to wake up the board\n",
+                               __func__, __LINE__);
+               goto out_unmap;
+       }
+
+       return 0;
+
+ out_unmap:
+       iounmap(mbar);
+       return -ENOSYS;
+}
+
+
+char saved_sram[0x4000];
+
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+       u32 clk_enables;
+       u32 msr, hid0;
+       u32 intr_main_mask;
+       void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+       unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
+       char saved_0x500[mpc52xx_ds_cached_size];
+
+       /* disable all interrupts in PIC */
+       intr_main_mask = in_be32(&intr->main_mask);
+       out_be32(&intr->main_mask, intr_main_mask | 0x1ffff);
+
+       /* don't let DEC expire any time soon */
+       mtspr(SPRN_DEC, 0x7fffffff);
+
+       /* save SRAM */
+       memcpy(saved_sram, sram, sram_size);
+
+       /* copy low level suspend code to sram */
+       memcpy(sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size);
+
+       out_8(&cdm->ccs_sleep_enable, 1);
+       out_8(&cdm->osc_sleep_enable, 1);
+       out_8(&cdm->ccs_qreq_test, 1);
+
+       /* disable all but SDRAM and bestcomm (SRAM) clocks */
+       clk_enables = in_be32(&cdm->clk_enables);
+       out_be32(&cdm->clk_enables, clk_enables & 0x00088000);
+
+       /* disable power management */
+       msr = mfmsr();
+       mtmsr(msr & ~MSR_POW);
+
+       /* enable sleep mode, disable others */
+       hid0 = mfspr(SPRN_HID0);
+       mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP);
+
+       /* save original, copy our irq handler, flush from dcache and invalidate icache */
+       memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size);
+       memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size);
+       flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+       /* call low-level sleep code */
+       mpc52xx_deep_sleep(sram, sdram, cdm, intr);
+
+       /* restore original irq handler */
+       memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size);
+       flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+       /* restore old power mode */
+       mtmsr(msr & ~MSR_POW);
+       mtspr(SPRN_HID0, hid0);
+       mtmsr(msr);
+
+       out_be32(&cdm->clk_enables, clk_enables);
+       out_8(&cdm->ccs_sleep_enable, 0);
+       out_8(&cdm->osc_sleep_enable, 0);
+
+       /* restore SRAM */
+       memcpy(sram, saved_sram, sram_size);
+
+       /* restart jiffies */
+       wakeup_decrementer();
+
+       /* reenable interrupts in PIC */
+       out_be32(&intr->main_mask, intr_main_mask);
+
+       return 0;
+}
+
+int mpc52xx_pm_finish(suspend_state_t state)
+{
+       /* call board resume code */
+       if (mpc52xx_suspend.board_resume_finish)
+               mpc52xx_suspend.board_resume_finish(mbar);
+
+       iounmap(mbar);
+
+       return 0;
+}
+
+static struct pm_ops mpc52xx_pm_ops = {
+       .valid          = mpc52xx_pm_valid,
+       .prepare        = mpc52xx_pm_prepare,
+       .enter          = mpc52xx_pm_enter,
+       .finish         = mpc52xx_pm_finish,
+};
+
+int __init mpc52xx_pm_init(void)
+{
+       pm_set_ops(&mpc52xx_pm_ops);
+       return 0;
+}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_sleep.S b/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
new file mode 100644 (file)
index 0000000..4dc170b
--- /dev/null
@@ -0,0 +1,154 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+
+.text
+
+_GLOBAL(mpc52xx_deep_sleep)
+mpc52xx_deep_sleep: /* args r3-r6: SRAM, SDRAM regs, CDM regs, INTR regs */
+
+       /* enable interrupts */
+       mfmsr   r7
+       ori     r7, r7, 0x8000 /* EE */
+       mtmsr   r7
+       sync; isync;
+
+       li      r10, 0 /* flag that irq handler sets */
+
+       /* enable tmr7 (or any other) interrupt */
+       lwz     r8, 0x14(r6) /* intr->main_mask */
+       ori     r8, r8, 0x1
+       xori    r8, r8, 0x1
+       stw     r8, 0x14(r6)
+       sync
+
+       /* emulate tmr7 interrupt */
+       li      r8, 0x1
+       stw     r8, 0x40(r6) /* intr->main_emulate */
+       sync
+
+       /* wait for it to happen */
+1:
+       cmpi    cr0, r10, 1
+       bne     cr0, 1b
+
+       /* lock icache */
+       mfspr   r10, SPRN_HID0
+       ori     r10, r10, 0x2000
+       sync; isync;
+       mtspr   SPRN_HID0, r10
+       sync; isync;
+
+
+       mflr    r9 /* save LR */
+
+       /* jump to sram */
+       mtlr    r3
+       blrl
+
+       mtlr    r9 /* restore LR */
+
+       /* unlock icache */
+       mfspr   r10, SPRN_HID0
+       ori     r10, r10, 0x2000
+       xori    r10, r10, 0x2000
+       sync; isync;
+       mtspr   SPRN_HID0, r10
+       sync; isync;
+
+
+       /* return to C code */
+       blr
+
+
+_GLOBAL(mpc52xx_ds_sram)
+mpc52xx_ds_sram:
+       /* put SDRAM into self-refresh */
+       lwz     r8, 0x4(r4)     /* sdram->ctrl */
+
+       oris    r8, r8, 0x8000 /* mode_en */
+       stw     r8, 0x4(r4)
+       sync
+
+       ori     r8, r8, 0x0002 /* soft_pre */
+       stw     r8, 0x4(r4)
+       sync
+       xori    r8, r8, 0x0002
+
+       xoris   r8, r8, 0x8000 /* !mode_en */
+       stw     r8, 0x4(r4)
+       sync
+
+       oris    r8, r8, 0x5000
+       xoris   r8, r8, 0x4000 /* ref_en !cke */
+       stw     r8, 0x4(r4)
+       sync
+
+       /* disable SDRAM clock */
+       lwz     r8, 0x14(r5) /* cdm->clkenable */
+       ori     r8, r8, 0x0008
+       xori    r8, r8, 0x0008
+       stw     r8, 0x14(r5)
+       sync
+
+
+       /* put mpc5200 to sleep */
+       mfmsr   r10
+       oris    r10, r10, 0x0004        /* POW = 1 */
+       sync; isync;
+       mtmsr   r10
+       sync; isync;
+
+
+       /* enable clock */
+       lwz     r8, 0x14(r5)
+       ori     r8, r8, 0x0008
+       stw     r8, 0x14(r5)
+       sync
+
+       /* get ram out of self-refresh */
+       lwz     r8, 0x4(r4)
+       oris    r8, r8, 0x5000 /* cke ref_en */
+       stw     r8, 0x4(r4)
+       sync
+
+       blr
+_GLOBAL(mpc52xx_ds_sram_size)
+mpc52xx_ds_sram_size:
+       .long $-mpc52xx_ds_sram
+
+
+/* ### interrupt handler for wakeup from deep-sleep ### */
+_GLOBAL(mpc52xx_ds_cached)
+mpc52xx_ds_cached:
+       mtspr   SPRN_SPRG0, r7
+       mtspr   SPRN_SPRG1, r8
+
+       /* disable emulated interrupt */
+       mfspr   r7, 311 /* MBAR */
+       addi    r7, r7, 0x540   /* intr->main_emul */
+       li      r8, 0
+       stw     r8, 0(r7)
+       sync
+       dcbf    0, r7
+
+       /* acknowledge wakeup, so CCS releases power pown */
+       mfspr   r7, 311 /* MBAR */
+       addi    r7, r7, 0x524   /* intr->enc_status */
+       lwz     r8, 0(r7)
+       ori     r8, r8, 0x0400
+       stw     r8, 0(r7)
+       sync
+       dcbf    0, r7
+
+       /* flag - we handled the interrupt */
+       li      r10, 1
+
+       mfspr   r8, SPRN_SPRG1
+       mfspr   r7, SPRN_SPRG0
+
+       rfi
+_GLOBAL(mpc52xx_ds_cached_size)
+mpc52xx_ds_cached_size:
+       .long $-mpc52xx_ds_cached
index fff09f5d6edfc126c2db322e868efa714fad71e3..94843ed52a9334b476724e4243cd56520e45b1db 100644 (file)
@@ -111,6 +111,7 @@ static struct of_device_id mpc832x_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "qe", },
+       { .type = "mdio", },
        {},
 };
 
index 6b71e9ffb11ac224fc174918cd11e98049513cd2..b0b22bb29de79045f34d81e7b1f6366973fd6bcb 100644 (file)
@@ -73,6 +73,7 @@ static struct of_device_id mpc832x_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "qe", },
+       { .type = "mdio", },
        {},
 };
 
index 526ed090a446a36c60b4b19db32e964339dc7087..bceeff8bbfd21045fb9c873a468720f6f6d90552 100644 (file)
@@ -118,6 +118,7 @@ static struct of_device_id mpc836x_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "qe", },
+       { .type = "mdio", },
        {},
 };
 
index 2867f85e632553a898a79ba9fe5295d022f3f676..bec84ffe708e013ed88cabd8b261823da201d2c7 100644 (file)
@@ -84,7 +84,7 @@ void __init mpc8544_ds_pic_init(void)
 #ifdef CONFIG_PPC_I8259
        /* Initialize the i8259 controller */
        for_each_node_by_type(np, "interrupt-controller")
-           if (device_is_compatible(np, "chrp,iic")) {
+           if (of_device_is_compatible(np, "chrp,iic")) {
                cascade_node = np;
                break;
        }
index 7e71636f90981a1767e8738b25afa014574a865a..1490eb3ce0d3d447b6d2731645db5f1c78203a7b 100644 (file)
@@ -197,7 +197,7 @@ static void __init mpc85xx_cds_pic_init(void)
 #ifdef CONFIG_PPC_I8259
        /* Initialize the i8259 controller */
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "chrp,iic")) {
+               if (of_device_is_compatible(np, "chrp,iic")) {
                        cascade_node = np;
                        break;
                }
index 54db41689954c4342733c09d5f19422deaf4fbbb..e3dddbfe66ff711f8a14860d62252c5ebb004080 100644 (file)
@@ -147,6 +147,7 @@ static struct of_device_id mpc85xx_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "qe", },
+       { .type = "mdio", },
        {},
 };
 
index 3d3d98f5bd4acb4e7b4585bb73d36dd62c40615a..90877565caa33238f2b83514df58a7dd0d0ac1c1 100644 (file)
@@ -102,7 +102,7 @@ mpc86xx_hpcn_init_irq(void)
 #ifdef CONFIG_PCI
        /* Initialize i8259 controller */
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "chrp,iic")) {
+               if (of_device_is_compatible(np, "chrp,iic")) {
                        cascade_node = np;
                        break;
                }
index 7ef0c6854799b68bc2164bce879fd86f832a52d1..ba55b0ff0f746a4c60dd848c06bfb41faa97d026 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 
-#include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/pci-bridge.h>
 #include <asm-powerpc/mpic.h>
 #include <asm/mpc86xx.h>
index a35315af5c532fa84ed3a6be3580f31c2e2676a8..cf0e7bc8c2e77350749bc85e75480c83e743b5a5 100644 (file)
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc86xads-setup.c
+/*arch/powerpc/platforms/8xx/mpc86xads_setup.c
  *
  * Platform setup for the Freescale mpc86xads board
  *
index a57b57785acd854c2598251ecf1206a9646d0a6d..c36e475d93dc86d3e5dea78731d06fa728810549 100644 (file)
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc885ads-setup.c
+/*arch/powerpc/platforms/8xx/mpc885ads_setup.c
  *
  * Platform setup for the Freescale mpc885ads board
  *
index 51e33347c14778727a5dfa651e95eb1e3d4b818f..361acfa2894c77839efe1470208457ee512f54b9 100644 (file)
@@ -42,6 +42,7 @@ source "arch/powerpc/platforms/83xx/Kconfig"
 source "arch/powerpc/platforms/85xx/Kconfig"
 source "arch/powerpc/platforms/86xx/Kconfig"
 source "arch/powerpc/platforms/embedded6xx/Kconfig"
+source "arch/powerpc/platforms/44x/Kconfig"
 #source "arch/powerpc/platforms/4xx/Kconfig
 
 config PPC_NATIVE
index 452004283f1707b31625428f93da4ddc39fcafcf..d6e041a46d25ee21e148a1ef153d2e04f6fcee5d 100644 (file)
@@ -6,7 +6,8 @@ obj-$(CONFIG_PPC_PMAC)          += powermac/
 endif
 endif
 obj-$(CONFIG_PPC_CHRP)         += chrp/
-obj-$(CONFIG_4xx)              += 4xx/
+#obj-$(CONFIG_4xx)             += 4xx/
+obj-$(CONFIG_44x)              += 44x/
 obj-$(CONFIG_PPC_MPC52xx)      += 52xx/
 obj-$(CONFIG_PPC_8xx)          += 8xx/
 obj-$(CONFIG_PPC_82xx)         += 82xx/
index 82551770917c5e7fb66eec807550b18d4b5e029b..9b2b386ccf48aa2f6ed0650aeca471a2dad29ea3 100644 (file)
@@ -35,6 +35,21 @@ config SPU_FS
          Units on machines implementing the Broadband Processor
          Architecture.
 
+config SPU_FS_64K_LS
+       bool "Use 64K pages to map SPE local  store"
+       # we depend on PPC_MM_SLICES for now rather than selecting
+       # it because we depend on hugetlbfs hooks being present. We
+       # will fix that when the generic code has been improved to
+       # not require hijacking hugetlbfs hooks.
+       depends on SPU_FS && PPC_MM_SLICES && !PPC_64K_PAGES
+       default y
+       select PPC_HAS_HASH_64K
+       help
+         This option causes SPE local stores to be mapped in process
+         address spaces using 64K pages while the rest of the kernel
+         uses 4K pages. This can improve performances of applications
+         using multiple SPEs by lowering the TLB pressure on them.
+
 config SPU_BASE
        bool
        default n
index 4fc4e92775d0d1735ef1f0c38eec093b1a1e3a4d..47264e7220295f9484f6f9adfdb4031072bf45ed 100644 (file)
@@ -227,7 +227,7 @@ void iic_request_IPIs(void)
 
 static int iic_host_match(struct irq_host *h, struct device_node *node)
 {
-       return device_is_compatible(node,
+       return of_device_is_compatible(node,
                                    "IBM,CBEA-Internal-Interrupt-Controller");
 }
 
@@ -256,7 +256,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
        unsigned int node, ext, unit, class;
        const u32 *val;
 
-       if (!device_is_compatible(ct,
+       if (!of_device_is_compatible(ct,
                                     "IBM,CBEA-Internal-Interrupt-Controller"))
                return -ENODEV;
        if (intsize != 1)
@@ -324,7 +324,7 @@ static int __init setup_iic(void)
 
        for (dn = NULL;
             (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
-               if (!device_is_compatible(dn,
+               if (!of_device_is_compatible(dn,
                                     "IBM,CBEA-Internal-Interrupt-Controller"))
                        continue;
                np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL);
index d68d920eb2c4e6bbe8894c3c3dc99caefb8a8fe5..7fb92f23f380a60c66a01eb7a5314ac6bbe79a93 100644 (file)
@@ -74,7 +74,7 @@ static void spider_io_flush(const volatile void __iomem *addr)
        /* Fast path if we have a non-0 token, it indicates which bus we
         * are on.
         *
-        * If the token is 0, that means either the the ioremap was done
+        * If the token is 0, that means either that the ioremap was done
         * before we initialized this layer, or it's a PIO operation. We
         * fallback to a low path in this case. Hopefully, internal devices
         * which are ioremap'ed early should use in_XX/out_XX functions
index 54b96183cb64466347cd6ca4a25090de56be6df1..db6654272e133112acecdc83f35ad20e5c80b914 100644 (file)
@@ -112,7 +112,7 @@ static void __init mpic_init_IRQ(void)
 
        for (dn = NULL;
             (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
-               if (!device_is_compatible(dn, "CBEA,platform-open-pic"))
+               if (!of_device_is_compatible(dn, "CBEA,platform-open-pic"))
                        continue;
 
                /* The MPIC driver will get everything it needs from the
index fb1f15797bbbb837b29b337d90217c4339e7e38c..05f4b3d3d756558295a0121477da5036186b2f49 100644 (file)
@@ -358,12 +358,12 @@ void __init spider_init_IRQ(void)
         */
        for (dn = NULL;
             (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
-               if (device_is_compatible(dn, "CBEA,platform-spider-pic")) {
+               if (of_device_is_compatible(dn, "CBEA,platform-spider-pic")) {
                        if (of_address_to_resource(dn, 0, &r)) {
                                printk(KERN_WARNING "spider-pic: Failed\n");
                                continue;
                        }
-               } else if (device_is_compatible(dn, "sti,platform-spider-pic")
+               } else if (of_device_is_compatible(dn, "sti,platform-spider-pic")
                           && (chip < 2)) {
                        static long hard_coded_pics[] =
                                { 0x24000008000ul, 0x34000008000ul};
index fec51525252e2dfba33d8bb0c860bbbc0630d974..a7f5a7653c62e19149fd9d8865d6e0bc2c3aa890 100644 (file)
@@ -144,12 +144,11 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 
        switch(REGION_ID(ea)) {
        case USER_REGION_ID:
-#ifdef CONFIG_HUGETLB_PAGE
-               if (in_hugepage_area(mm->context, ea))
-                       psize = mmu_huge_psize;
-               else
+#ifdef CONFIG_PPC_MM_SLICES
+               psize = get_slice_psize(mm, ea);
+#else
+               psize = mm->context.user_psize;
 #endif
-                       psize = mm->context.user_psize;
                vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
                                SLB_VSID_USER;
                break;
index 2cd89c11af5ac328209cdbcf7a0b76dcdd7c196c..328afcf895032e50a7f36b0a7f00a38d3ca7aade 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += switch.o fault.o
+obj-y += switch.o fault.o lscsa_alloc.o
 
 obj-$(CONFIG_SPU_FS) += spufs.o
 spufs-y += inode.o file.o context.o syscalls.o coredump.o
index 3322528fa6eb687c4f25965e9966cb6f7b364a49..d32db9ffc6ebc56f31a68ce28c111880f634ea34 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/poll.h>
index a87d9ca3dba26c926822f068e7e8ea0055cb60ba..8654749e317bae0aa67795dda4ba2eebdae50c3f 100644 (file)
@@ -36,10 +36,8 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        /* Binding to physical processor deferred
         * until spu_activate().
         */
-       spu_init_csa(&ctx->csa);
-       if (!ctx->csa.lscsa) {
+       if (spu_init_csa(&ctx->csa))
                goto out_free;
-       }
        spin_lock_init(&ctx->mmio_lock);
        spin_lock_init(&ctx->mapping_lock);
        kref_init(&ctx->kref);
index d010b2464a98cf3df710a4e5a9dc150c827506e8..45614c73c7841824d1a1f47834ebc2838bfbbe0a 100644 (file)
@@ -118,14 +118,32 @@ spufs_mem_write(struct file *file, const char __user *buffer,
 static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
                                          unsigned long address)
 {
-       struct spu_context *ctx = vma->vm_file->private_data;
-       unsigned long pfn, offset = address - vma->vm_start;
-
-       offset += vma->vm_pgoff << PAGE_SHIFT;
+       struct spu_context *ctx = vma->vm_file->private_data;
+       unsigned long pfn, offset, addr0 = address;
+#ifdef CONFIG_SPU_FS_64K_LS
+       struct spu_state *csa = &ctx->csa;
+       int psize;
+
+       /* Check what page size we are using */
+       psize = get_slice_psize(vma->vm_mm, address);
+
+       /* Some sanity checking */
+       BUG_ON(csa->use_big_pages != (psize == MMU_PAGE_64K));
+
+       /* Wow, 64K, cool, we need to align the address though */
+       if (csa->use_big_pages) {
+               BUG_ON(vma->vm_start & 0xffff);
+               address &= ~0xfffful;
+       }
+#endif /* CONFIG_SPU_FS_64K_LS */
 
+       offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
        if (offset >= LS_SIZE)
                return NOPFN_SIGBUS;
 
+       pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n",
+                addr0, address, offset);
+
        spu_acquire(ctx);
 
        if (ctx->state == SPU_STATE_SAVED) {
@@ -149,9 +167,24 @@ static struct vm_operations_struct spufs_mem_mmap_vmops = {
        .nopfn = spufs_mem_mmap_nopfn,
 };
 
-static int
-spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
-{
+static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+#ifdef CONFIG_SPU_FS_64K_LS
+       struct spu_context      *ctx = file->private_data;
+       struct spu_state        *csa = &ctx->csa;
+
+       /* Sanity check VMA alignment */
+       if (csa->use_big_pages) {
+               pr_debug("spufs_mem_mmap 64K, start=0x%lx, end=0x%lx,"
+                        " pgoff=0x%lx\n", vma->vm_start, vma->vm_end,
+                        vma->vm_pgoff);
+               if (vma->vm_start & 0xffff)
+                       return -EINVAL;
+               if (vma->vm_pgoff & 0xf)
+                       return -EINVAL;
+       }
+#endif /* CONFIG_SPU_FS_64K_LS */
+
        if (!(vma->vm_flags & VM_SHARED))
                return -EINVAL;
 
@@ -163,13 +196,34 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
+#ifdef CONFIG_SPU_FS_64K_LS
+unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
+                                     unsigned long len, unsigned long pgoff,
+                                     unsigned long flags)
+{
+       struct spu_context      *ctx = file->private_data;
+       struct spu_state        *csa = &ctx->csa;
+
+       /* If not using big pages, fallback to normal MM g_u_a */
+       if (!csa->use_big_pages)
+               return current->mm->get_unmapped_area(file, addr, len,
+                                                     pgoff, flags);
+
+       /* Else, try to obtain a 64K pages slice */
+       return slice_get_unmapped_area(addr, len, flags,
+                                      MMU_PAGE_64K, 1, 0);
+}
+#endif /* CONFIG_SPU_FS_64K_LS */
+
 static const struct file_operations spufs_mem_fops = {
-       .open    = spufs_mem_open,
-       .release = spufs_mem_release,
-       .read    = spufs_mem_read,
-       .write   = spufs_mem_write,
-       .llseek  = generic_file_llseek,
-       .mmap    = spufs_mem_mmap,
+       .open                   = spufs_mem_open,
+       .read                   = spufs_mem_read,
+       .write                  = spufs_mem_write,
+       .llseek                 = generic_file_llseek,
+       .mmap                   = spufs_mem_mmap,
+#ifdef CONFIG_SPU_FS_64K_LS
+       .get_unmapped_area      = spufs_get_unmapped_area,
+#endif
 };
 
 static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
index 428875c5e4ecec35559316967d37c18cdf01a9d9..fc4ed1ffbd4ffb379da5e25aad08c78b0bdf7057 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 
diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
new file mode 100644 (file)
index 0000000..f4b3c05
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * SPU local store allocation routines
+ *
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include <asm/mmu.h>
+
+static int spu_alloc_lscsa_std(struct spu_state *csa)
+{
+       struct spu_lscsa *lscsa;
+       unsigned char *p;
+
+       lscsa = vmalloc(sizeof(struct spu_lscsa));
+       if (!lscsa)
+               return -ENOMEM;
+       memset(lscsa, 0, sizeof(struct spu_lscsa));
+       csa->lscsa = lscsa;
+
+       /* Set LS pages reserved to allow for user-space mapping. */
+       for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+               SetPageReserved(vmalloc_to_page(p));
+
+       return 0;
+}
+
+static void spu_free_lscsa_std(struct spu_state *csa)
+{
+       /* Clear reserved bit before vfree. */
+       unsigned char *p;
+
+       if (csa->lscsa == NULL)
+               return;
+
+       for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+               ClearPageReserved(vmalloc_to_page(p));
+
+       vfree(csa->lscsa);
+}
+
+#ifdef CONFIG_SPU_FS_64K_LS
+
+#define SPU_64K_PAGE_SHIFT     16
+#define SPU_64K_PAGE_ORDER     (SPU_64K_PAGE_SHIFT - PAGE_SHIFT)
+#define SPU_64K_PAGE_COUNT     (1ul << SPU_64K_PAGE_ORDER)
+
+int spu_alloc_lscsa(struct spu_state *csa)
+{
+       struct page     **pgarray;
+       unsigned char   *p;
+       int             i, j, n_4k;
+
+       /* Check availability of 64K pages */
+       if (mmu_psize_defs[MMU_PAGE_64K].shift == 0)
+               goto fail;
+
+       csa->use_big_pages = 1;
+
+       pr_debug("spu_alloc_lscsa(csa=0x%p), trying to allocate 64K pages\n",
+                csa);
+
+       /* First try to allocate our 64K pages. We need 5 of them
+        * with the current implementation. In the future, we should try
+        * to separate the lscsa with the actual local store image, thus
+        * allowing us to require only 4 64K pages per context
+        */
+       for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) {
+               /* XXX This is likely to fail, we should use a special pool
+                *     similiar to what hugetlbfs does.
+                */
+               csa->lscsa_pages[i] = alloc_pages(GFP_KERNEL,
+                                                 SPU_64K_PAGE_ORDER);
+               if (csa->lscsa_pages[i] == NULL)
+                       goto fail;
+       }
+
+       pr_debug(" success ! creating vmap...\n");
+
+       /* Now we need to create a vmalloc mapping of these for the kernel
+        * and SPU context switch code to use. Currently, we stick to a
+        * normal kernel vmalloc mapping, which in our case will be 4K
+        */
+       n_4k = SPU_64K_PAGE_COUNT * SPU_LSCSA_NUM_BIG_PAGES;
+       pgarray = kmalloc(sizeof(struct page *) * n_4k, GFP_KERNEL);
+       if (pgarray == NULL)
+               goto fail;
+       for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++)
+               for (j = 0; j < SPU_64K_PAGE_COUNT; j++)
+                       /* We assume all the struct page's are contiguous
+                        * which should be hopefully the case for an order 4
+                        * allocation..
+                        */
+                       pgarray[i * SPU_64K_PAGE_COUNT + j] =
+                               csa->lscsa_pages[i] + j;
+       csa->lscsa = vmap(pgarray, n_4k, VM_USERMAP, PAGE_KERNEL);
+       kfree(pgarray);
+       if (csa->lscsa == NULL)
+               goto fail;
+
+       memset(csa->lscsa, 0, sizeof(struct spu_lscsa));
+
+       /* Set LS pages reserved to allow for user-space mapping.
+        *
+        * XXX isn't that a bit obsolete ? I think we should just
+        * make sure the page count is high enough. Anyway, won't harm
+        * for now
+        */
+       for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+               SetPageReserved(vmalloc_to_page(p));
+
+       pr_debug(" all good !\n");
+
+       return 0;
+fail:
+       pr_debug("spufs: failed to allocate lscsa 64K pages, falling back\n");
+       spu_free_lscsa(csa);
+       return spu_alloc_lscsa_std(csa);
+}
+
+void spu_free_lscsa(struct spu_state *csa)
+{
+       unsigned char *p;
+       int i;
+
+       if (!csa->use_big_pages) {
+               spu_free_lscsa_std(csa);
+               return;
+       }
+       csa->use_big_pages = 0;
+
+       if (csa->lscsa == NULL)
+               goto free_pages;
+
+       for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+               ClearPageReserved(vmalloc_to_page(p));
+
+       vunmap(csa->lscsa);
+       csa->lscsa = NULL;
+
+ free_pages:
+
+       for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++)
+               if (csa->lscsa_pages[i])
+                       __free_pages(csa->lscsa_pages[i], SPU_64K_PAGE_ORDER);
+}
+
+#else /* CONFIG_SPU_FS_64K_LS */
+
+int spu_alloc_lscsa(struct spu_state *csa)
+{
+       return spu_alloc_lscsa_std(csa);
+}
+
+void spu_free_lscsa(struct spu_state *csa)
+{
+       spu_free_lscsa_std(csa);
+}
+
+#endif /* !defined(CONFIG_SPU_FS_64K_LS) */
index 91030b8abdca6fbc62ca05efad87367f102c6885..b6ecb30e7d58b71ef8530f13bd02ea4bfe21039e 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/completion.h>
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/numa.h>
index 8347c4a3f894a4bd647cc64b128a6a9089126dda..71a0b41adb8c8ed320ba2325716f491ec99b34e0 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 
@@ -2189,40 +2188,30 @@ static void init_priv2(struct spu_state *csa)
  * as it is by far the largest of the context save regions,
  * and may need to be pinned or otherwise specially aligned.
  */
-void spu_init_csa(struct spu_state *csa)
+int spu_init_csa(struct spu_state *csa)
 {
-       struct spu_lscsa *lscsa;
-       unsigned char *p;
+       int rc;
 
        if (!csa)
-               return;
+               return -EINVAL;
        memset(csa, 0, sizeof(struct spu_state));
 
-       lscsa = vmalloc(sizeof(struct spu_lscsa));
-       if (!lscsa)
-               return;
+       rc = spu_alloc_lscsa(csa);
+       if (rc)
+               return rc;
 
-       memset(lscsa, 0, sizeof(struct spu_lscsa));
-       csa->lscsa = lscsa;
        spin_lock_init(&csa->register_lock);
 
-       /* Set LS pages reserved to allow for user-space mapping. */
-       for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE)
-               SetPageReserved(vmalloc_to_page(p));
-
        init_prob(csa);
        init_priv1(csa);
        init_priv2(csa);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
-       /* Clear reserved bit before vfree. */
-       unsigned char *p;
-       for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE)
-               ClearPageReserved(vmalloc_to_page(p));
-
-       vfree(csa->lscsa);
+       spu_free_lscsa(csa);
 }
 EXPORT_SYMBOL_GPL(spu_fini_csa);
index 1469d6478f67663b504b692416931e3879334353..d32fedc991d36d5a98452dcab5eccfbec09676c8 100644 (file)
@@ -267,7 +267,7 @@ chrp_find_bridges(void)
                model = of_get_property(dev, "model", NULL);
                if (model == NULL)
                        model = "<none>";
-               if (device_is_compatible(dev, "IBM,python")) {
+               if (of_device_is_compatible(dev, "IBM,python")) {
                        setup_python(hose, dev);
                } else if (is_mot
                           || strncmp(model, "Motorola, Grackle", 17) == 0) {
index 1870038a8e0a7ea3b47f26578e31559d962db284..373de4c063db98638281b388dc44d9401310baf8 100644 (file)
@@ -448,7 +448,7 @@ static void __init chrp_find_8259(void)
 
        /* Look for cascade */
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "chrp,iic")) {
+               if (of_device_is_compatible(np, "chrp,iic")) {
                        pic = np;
                        break;
                }
index 1d2307e87c305b4636e8c46bab2ddaef76359cc7..3ea0eb78568ed274fb590e33a07897e4a2289b45 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
index 9557908ef54578789322cc4fd75c5da7c4d6443d..8f3c2a73e1651f8918a2971b415ce8a84a2e0bd5 100644 (file)
@@ -20,16 +20,24 @@ config MPC7448HPC2
        select TSI108_BRIDGE
        select DEFAULT_UIMAGE
        select PPC_UDBG_16550
-       select MPIC
-       select MPIC_WEIRD
        help
          Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
          platform
+
+config PPC_HOLLY
+       bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
+       select TSI108_BRIDGE
+       select PPC_UDBG_16550
+       help
+         Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
+         Board with TSI108/9 bridge (Hickory/Holly)
 endchoice
 
 config TSI108_BRIDGE
        bool
-       depends on MPC7448HPC2
+       depends on MPC7448HPC2 || PPC_HOLLY
+       select MPIC
+       select MPIC_WEIRD
        default y
 
 config MPC10X_BRIDGE
index d3d11a3cd656f3cd0753fa9bbfcc7aa32fa4353d..b39fe4f470d5950c9b619863e27bd11bdae13e70 100644 (file)
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_MPC7448HPC2)      += mpc7448_hpc2.o
 obj-$(CONFIG_LINKSTATION)      += linkstation.o ls_uart.o
+obj-$(CONFIG_PPC_HOLLY)                += holly.o
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
new file mode 100644 (file)
index 0000000..3a0b4a0
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Board setup routines for the IBM 750GX/CL platform w/ TSI10x bridge
+ *
+ * Copyright 2007 IBM Corporation
+ *
+ * Stephen Winiecki <stevewin@us.ibm.com>
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * Based on code from mpc7448_hpc2.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/tsi108.h>
+#include <asm/pci-bridge.h>
+#include <asm/reg.h>
+#include <mm/mmu_decl.h>
+#include <asm/tsi108_irq.h>
+#include <asm/tsi108_pci.h>
+#include <asm/mpic.h>
+#include <asm/of_platform.h>
+
+#undef DEBUG
+
+#define HOLLY_PCI_CFG_PHYS 0x7c000000
+
+int holly_exclude_device(u_char bus, u_char devfn)
+{
+       if (bus == 0 && PCI_SLOT(devfn) == 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       else
+               return PCIBIOS_SUCCESSFUL;
+}
+
+static void holly_remap_bridge(void)
+{
+       u32 lut_val, lut_addr;
+       int i;
+
+       printk(KERN_INFO "Remapping PCI bridge\n");
+
+       /* Re-init the PCI bridge and LUT registers to have mappings that don't
+        * rely on PIBS
+        */
+       lut_addr = 0x900;
+       for (i = 0; i < 31; i++) {
+               tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000201);
+               lut_addr += 4;
+               tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
+               lut_addr += 4;
+       }
+
+       /* Reserve the last LUT entry for PCI I/O space */
+       tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000241);
+       lut_addr += 4;
+       tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
+
+       /* Map PCI I/O space */
+       tsi108_write_reg(TSI108_PCI_PFAB_IO_UPPER, 0x0);
+       tsi108_write_reg(TSI108_PCI_PFAB_IO, 0x1);
+
+       /* Map PCI CFG space */
+       tsi108_write_reg(TSI108_PCI_PFAB_BAR0_UPPER, 0x0);
+       tsi108_write_reg(TSI108_PCI_PFAB_BAR0, 0x7c000000 | 0x01);
+
+       /* We don't need MEM32 and PRM remapping so disable them */
+       tsi108_write_reg(TSI108_PCI_PFAB_MEM32, 0x0);
+       tsi108_write_reg(TSI108_PCI_PFAB_PFM3, 0x0);
+       tsi108_write_reg(TSI108_PCI_PFAB_PFM4, 0x0);
+
+       /* Set P2O_BAR0 */
+       tsi108_write_reg(TSI108_PCI_P2O_BAR0_UPPER, 0x0);
+       tsi108_write_reg(TSI108_PCI_P2O_BAR0, 0xc0000000);
+
+       /* Init the PCI LUTs to do no remapping */
+       lut_addr = 0x500;
+       lut_val = 0x00000002;
+
+       for (i = 0; i < 32; i++) {
+               tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, lut_val);
+               lut_addr += 4;
+               tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, 0x40000000);
+               lut_addr += 4;
+               lut_val += 0x02000000;
+       }
+       tsi108_write_reg(TSI108_PCI_P2O_PAGE_SIZES, 0x00007900);
+
+       /* Set 64-bit PCI bus address for system memory */
+       tsi108_write_reg(TSI108_PCI_P2O_BAR2_UPPER, 0x0);
+       tsi108_write_reg(TSI108_PCI_P2O_BAR2, 0x0);
+}
+
+static void __init holly_setup_arch(void)
+{
+       struct device_node *cpu;
+       struct device_node *np;
+
+       if (ppc_md.progress)
+               ppc_md.progress("holly_setup_arch():set_bridge", 0);
+
+       cpu = of_find_node_by_type(NULL, "cpu");
+       if (cpu) {
+               const unsigned int *fp;
+
+               fp = of_get_property(cpu, "clock-frequency", NULL);
+               if (fp)
+                       loops_per_jiffy = *fp / HZ;
+               else
+                       loops_per_jiffy = 50000000 / HZ;
+               of_node_put(cpu);
+       }
+       tsi108_csr_vir_base = get_vir_csrbase();
+
+       /* setup PCI host bridge */
+       holly_remap_bridge();
+
+       np = of_find_node_by_type(NULL, "pci");
+       if (np)
+               tsi108_setup_pci(np, HOLLY_PCI_CFG_PHYS, 1);
+
+       ppc_md.pci_exclude_device = holly_exclude_device;
+       if (ppc_md.progress)
+               ppc_md.progress("tsi108: resources set", 0x100);
+
+       printk(KERN_INFO "PPC750GX/CL Platform\n");
+}
+
+/*
+ * Interrupt setup and service.  Interrrupts on the holly come
+ * from the four external INT pins, PCI interrupts are routed via
+ * PCI interrupt control registers, it generates internal IRQ23
+ *
+ * Interrupt routing on the Holly Board:
+ * TSI108:PB_INT[0] -> CPU0:INT#
+ * TSI108:PB_INT[1] -> CPU0:MCP#
+ * TSI108:PB_INT[2] -> N/C
+ * TSI108:PB_INT[3] -> N/C
+ */
+static void __init holly_init_IRQ(void)
+{
+       struct mpic *mpic;
+       phys_addr_t mpic_paddr = 0;
+       struct device_node *tsi_pic;
+#ifdef CONFIG_PCI
+       unsigned int cascade_pci_irq;
+       struct device_node *tsi_pci;
+       struct device_node *cascade_node = NULL;
+#endif
+
+       tsi_pic = of_find_node_by_type(NULL, "open-pic");
+       if (tsi_pic) {
+               unsigned int size;
+               const void *prop = of_get_property(tsi_pic, "reg", &size);
+               mpic_paddr = of_translate_address(tsi_pic, prop);
+       }
+
+       if (mpic_paddr == 0) {
+               printk(KERN_ERR "%s: No tsi108 PIC found !\n", __func__);
+               return;
+       }
+
+       pr_debug("%s: tsi108 pic phys_addr = 0x%x\n", __func__, (u32) mpic_paddr);
+
+       mpic = mpic_alloc(tsi_pic, mpic_paddr,
+                       MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
+                       MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
+                       24,
+                       NR_IRQS-4, /* num_sources used */
+                       "Tsi108_PIC");
+
+       BUG_ON(mpic == NULL);
+
+       mpic_assign_isu(mpic, 0, mpic_paddr + 0x100);
+
+       mpic_init(mpic);
+
+#ifdef CONFIG_PCI
+       tsi_pci = of_find_node_by_type(NULL, "pci");
+       if (tsi_pci == NULL) {
+               printk(KERN_ERR "%s: No tsi108 pci node found !\n", __func__);
+               return;
+       }
+
+       cascade_node = of_find_node_by_type(NULL, "pic-router");
+       if (cascade_node == NULL) {
+               printk(KERN_ERR "%s: No tsi108 pci cascade node found !\n", __func__);
+               return;
+       }
+
+       cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
+       pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
+       tsi108_pci_int_init(cascade_node);
+       set_irq_data(cascade_pci_irq, mpic);
+       set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+#endif
+       /* Configure MPIC outputs to CPU0 */
+       tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
+       of_node_put(tsi_pic);
+}
+
+void holly_show_cpuinfo(struct seq_file *m)
+{
+       seq_printf(m, "vendor\t\t: IBM\n");
+       seq_printf(m, "machine\t\t: PPC750 GX/CL\n");
+}
+
+void holly_restart(char *cmd)
+{
+       __be32 __iomem *ocn_bar1 = NULL;
+       unsigned long bar;
+       struct device_node *bridge = NULL;
+       const void *prop;
+       int size;
+       phys_addr_t addr = 0xc0000000;
+
+       local_irq_disable();
+
+       bridge = of_find_node_by_type(NULL, "tsi-bridge");
+       if (bridge) {
+               prop = of_get_property(bridge, "reg", &size);
+               addr = of_translate_address(bridge, prop);
+       }
+       addr += (TSI108_PB_OFFSET + 0x414);
+
+       ocn_bar1 = ioremap(addr, 0x4);
+
+       /* Turn on the BOOT bit so the addresses are correctly
+        * routed to the HLP interface */
+       bar = ioread32be(ocn_bar1);
+       bar |= 2;
+       iowrite32be(bar, ocn_bar1);
+       iosync();
+
+       /* Set SRR0 to the reset vector and turn on MSR_IP */
+       mtspr(SPRN_SRR0, 0xfff00100);
+       mtspr(SPRN_SRR1, MSR_IP);
+
+       /* Do an rfi to jump back to firmware.  Somewhat evil,
+        * but it works
+        */
+       __asm__ __volatile__("rfi" : : : "memory");
+
+       /* Spin until reset happens.  Shouldn't really get here */
+       for (;;) ;
+}
+
+void holly_power_off(void)
+{
+       local_irq_disable();
+       /* No way to shut power off with software */
+       for (;;) ;
+}
+
+void holly_halt(void)
+{
+       holly_power_off();
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init holly_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "ibm,holly"))
+               return 0;
+       return 1;
+}
+
+static int ppc750_machine_check_exception(struct pt_regs *regs)
+{
+       const struct exception_table_entry *entry;
+
+       /* Are we prepared to handle this fault */
+       if ((entry = search_exception_tables(regs->nip)) != NULL) {
+               tsi108_clear_pci_cfg_error();
+               regs->msr |= MSR_RI;
+               regs->nip = entry->fixup;
+               return 1;
+       }
+       return 0;
+}
+
+define_machine(holly){
+       .name                           = "PPC750 GX/CL TSI",
+       .probe                          = holly_probe,
+       .setup_arch                     = holly_setup_arch,
+       .init_IRQ                       = holly_init_IRQ,
+       .show_cpuinfo                   = holly_show_cpuinfo,
+       .get_irq                        = mpic_get_irq,
+       .restart                        = holly_restart,
+       .calibrate_decr                 = generic_calibrate_decr,
+       .machine_check_exception        = ppc750_machine_check_exception,
+       .progress                       = udbg_progress,
+};
index c3f64ddb0be6e2e756a5e915b0276f72c62a9639..4542e0c837c07681dd6d929f562e22efefa6786d 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/reg.h>
 #include <mm/mmu_decl.h>
 #include "mpc7448_hpc2.h"
+#include <asm/tsi108_pci.h>
 #include <asm/tsi108_irq.h>
 #include <asm/mpic.h>
 
 #define DBG(fmt...) do { } while(0)
 #endif
 
+#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
+
 #ifndef CONFIG_PCI
 isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
 isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
 pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
 #endif
 
-extern int tsi108_setup_pci(struct device_node *dev);
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
-extern void tsi108_pci_int_init(struct device_node *node);
-extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
 
 int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
 {
@@ -72,28 +72,16 @@ int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
 
 static void __init mpc7448_hpc2_setup_arch(void)
 {
-       struct device_node *cpu;
        struct device_node *np;
        if (ppc_md.progress)
                ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
 
-       cpu = of_find_node_by_type(NULL, "cpu");
-       if (cpu != 0) {
-               const unsigned int *fp;
-
-               fp = of_get_property(cpu, "clock-frequency", NULL);
-               if (fp != 0)
-                       loops_per_jiffy = *fp / HZ;
-               else
-                       loops_per_jiffy = 50000000 / HZ;
-               of_node_put(cpu);
-       }
        tsi108_csr_vir_base = get_vir_csrbase();
 
        /* setup PCI host bridge */
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               tsi108_setup_pci(np);
+               tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0);
 
        ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
        if (ppc_md.progress)
@@ -222,7 +210,6 @@ static int __init mpc7448_hpc2_probe(void)
 
 static int mpc7448_machine_check_exception(struct pt_regs *regs)
 {
-       extern void tsi108_clear_pci_cfg_error(void);
        const struct exception_table_entry *entry;
 
        /* Are we prepared to handle this fault */
index 46c3a8e7c3a8a0a5b035991c9a34921423af8eca..761d9e971fc4bacb5413efc9dd4b02cb3da4bd8c 100644 (file)
@@ -7,7 +7,9 @@ menu "iSeries device drivers"
        depends on PPC_ISERIES
 
 config VIOCONS
-       tristate "iSeries Virtual Console Support (Obsolete)"
+       bool "iSeries Virtual Console Support (Obsolete)"
+       depends on !HVC_ISERIES
+       default n
        help
          This is the old virtual console driver for legacy iSeries.
          You should use the iSeries Hypervisor Virtual Console
index aee5908df7008aecfaa105c5e3b2db2a2b334da5..722335e32fd48399d51b2406ee5bfb9cba160d8f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
index 2ca2d8a9de97ac5bcf23148e62141df6978f069b..354b8dd2a2c1e2ccdf515e164c26fcf571c232fe 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
index b1d3b99c3f9d74abf96f5f5fa46b5f5de3b72a88..7aaa5bbc93630e24986491e8b1717bfef5794d13 100644 (file)
@@ -467,15 +467,15 @@ static int __init add_bridge(struct device_node *dev)
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        disp_name = NULL;
-       if (device_is_compatible(dev, "u3-agp")) {
+       if (of_device_is_compatible(dev, "u3-agp")) {
                setup_u3_agp(hose);
                disp_name = "U3-AGP";
                primary = 0;
-       } else if (device_is_compatible(dev, "u3-ht")) {
+       } else if (of_device_is_compatible(dev, "u3-ht")) {
                setup_u3_ht(hose);
                disp_name = "U3-HT";
                primary = 1;
-        } else if (device_is_compatible(dev, "u4-pcie")) {
+        } else if (of_device_is_compatible(dev, "u4-pcie")) {
                 setup_u4_pcie(hose);
                 disp_name = "U4-PCIE";
                 primary = 0;
@@ -556,12 +556,12 @@ void __init maple_pci_init(void)
                        continue;
                if (strcmp(np->type, "pci") && strcmp(np->type, "ht"))
                        continue;
-               if ((device_is_compatible(np, "u4-pcie") ||
-                    device_is_compatible(np, "u3-agp")) &&
+               if ((of_device_is_compatible(np, "u4-pcie") ||
+                    of_device_is_compatible(np, "u3-agp")) &&
                    add_bridge(np) == 0)
                        of_node_get(np);
 
-               if (device_is_compatible(np, "u3-ht")) {
+               if (of_device_is_compatible(np, "u3-ht")) {
                        of_node_get(np);
                        ht = np;
                }
index 2a30c5b2532e1e2e512d775fee618de75e356f00..354c058616299e7fdc7102a5c55fb89ee49fbe29 100644 (file)
@@ -231,7 +231,7 @@ static void __init maple_init_IRQ(void)
         */
 
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "open-pic")) {
+               if (of_device_is_compatible(np, "open-pic")) {
                        mpic_node = np;
                        break;
                }
index 2a57d602368594507b9fe8500caa0be86740eec8..3ae083851b01043383bda66a1518e737c8144c56 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/hw_irq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
+#include <asm/time.h>
 
 #define SDCASR_REG             0x0100
 #define SDCASR_REG_STRIDE      0x1000
@@ -204,6 +205,8 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
        policy->cur = pas_freqs[cur_astate].frequency;
        policy->cpus = cpu_online_map;
 
+       ppc_proc_freq = policy->cur * 1000ul;
+
        cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu);
 
        /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
@@ -270,6 +273,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
        mutex_unlock(&pas_switch_mutex);
 
+       ppc_proc_freq = freqs.new * 1000ul;
        return 0;
 }
 
index 056243da360b6dbce76218cd334bebfd37aa8214..bbc6dfcfaa91b835c96e8a5cbd6c629a15734d14 100644 (file)
@@ -173,19 +173,6 @@ static void __init pas_fixup_phb_resources(void)
 }
 
 
-void __devinit pas_pci_irq_fixup(struct pci_dev *dev)
-{
-       /* DMA is special, 84 interrupts (128 -> 211), all but 128
-        * need to be mapped by hand here.
-        */
-       if (dev->vendor == 0x1959 && dev->device == 0xa007) {
-               int i;
-               for (i = 129; i < 212; i++)
-                       irq_create_mapping(NULL, i);
-       }
-}
-
-
 void __init pas_pci_init(void)
 {
        struct device_node *np, *root;
index f88f0ec4c8cb2d6ec042021e67a8d3e07c8064a3..c5a3f61f8d857ba010108b01be9e75f624145a56 100644 (file)
@@ -114,7 +114,7 @@ static __init void pas_init_IRQ(void)
        mpic_node = NULL;
 
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "open-pic")) {
+               if (of_device_is_compatible(np, "open-pic")) {
                        mpic_node = np;
                        break;
                }
@@ -211,7 +211,10 @@ static struct of_device_id pasemi_bus_ids[] = {
 
 static int __init pasemi_publish_devices(void)
 {
-       /* Publish OF platform devices for southbridge IOs */
+       if (!machine_is(pasemi))
+               return 0;
+
+       /* Publish OF platform devices for SDC and other non-PCI devices */
        of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
 
        return 0;
@@ -248,5 +251,4 @@ define_machine(pas) {
        .calibrate_decr         = generic_calibrate_decr,
        .progress               = pas_progress,
        .machine_check_exception = pas_machine_check_handler,
-       .pci_irq_fixup          = pas_pci_irq_fixup,
 };
index 567d5523b6909e294f4fd204890848e940265a2e..00f50298c342aad55c982687e03bddbde0d731cb 100644 (file)
@@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
 
 static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -ENODEV;
-
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
        policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
-       policy->cpus = cpu_possible_map;
+       /* secondary CPUs are tied to the primary one by the
+        * cpufreq core if in the secondary policy we tell it that
+        * it actually must be one policy together with all others. */
+       policy->cpus = cpu_online_map;
        cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
 
        return cpufreq_frequency_table_cpuinfo(policy,
index 52cfdd86c92847767538793721199989060c00f5..f29705f8047de2be29b70e302be880ea694408fd 100644 (file)
@@ -1418,7 +1418,7 @@ static long g5_eth_phy_reset(struct device_node *node, long param, long value)
        phy = of_get_next_child(node, NULL);
        if (!phy)
                return -ENODEV;
-       need_reset = device_is_compatible(phy, "B5221");
+       need_reset = of_device_is_compatible(phy, "B5221");
        of_node_put(phy);
        if (!need_reset)
                return 0;
@@ -2624,7 +2624,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
        for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
                if (!compat)
                        break;
-               if (device_is_compatible(node, compat))
+               if (of_device_is_compatible(node, compat))
                        break;
        }
        if (!node)
@@ -2728,7 +2728,7 @@ initial_serial_shutdown(struct device_node *np)
        conn = of_get_property(np, "AAPL,connector", &len);
        if (conn && (strcmp(conn, "infrared") == 0))
                port_type = PMAC_SCC_IRDA;
-       else if (device_is_compatible(np, "cobalt"))
+       else if (of_device_is_compatible(np, "cobalt"))
                modem = 1;
        else if (slots && slots->count > 0) {
                if (strcmp(slots->name, "IrDA") == 0)
@@ -2787,7 +2787,7 @@ set_initial_features(void)
                 */
                np = of_find_node_by_name(NULL, "ethernet");
                while(np) {
-                       if (device_is_compatible(np, "K2-GMAC"))
+                       if (of_device_is_compatible(np, "K2-GMAC"))
                                g5_gmac_enable(np, 0, 1);
                        np = of_find_node_by_name(np, "ethernet");
                }
@@ -2799,7 +2799,7 @@ set_initial_features(void)
                 */
                np = of_find_node_by_name(NULL, "firewire");
                while(np) {
-                       if (device_is_compatible(np, "pci106b,5811")) {
+                       if (of_device_is_compatible(np, "pci106b,5811")) {
                                macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
                                g5_fw_enable(np, 0, 1);
                        }
@@ -2817,8 +2817,8 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "ethernet");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && device_is_compatible(np, "gmac"))
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && of_device_is_compatible(np, "gmac"))
                                core99_gmac_enable(np, 0, 1);
                        np = of_find_node_by_name(np, "ethernet");
                }
@@ -2831,10 +2831,10 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "firewire");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && (device_is_compatible(np, "pci106b,18") ||
-                               device_is_compatible(np, "pci106b,30") ||
-                               device_is_compatible(np, "pci11c1,5811"))) {
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && (of_device_is_compatible(np, "pci106b,18") ||
+                               of_device_is_compatible(np, "pci106b,30") ||
+                               of_device_is_compatible(np, "pci11c1,5811"))) {
                                macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
                                core99_firewire_enable(np, 0, 1);
                        }
@@ -2845,8 +2845,8 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "ata-6");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && device_is_compatible(np, "kauai-ata")) {
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && of_device_is_compatible(np, "kauai-ata")) {
                                core99_ata100_enable(np, 1);
                        }
                        np = of_find_node_by_name(np, "ata-6");
index 5430e146b3e91c5aa603ac258935b485f8599b63..3f507ab9c5e5accf21dbd741d821dd9f5832f40c 100644 (file)
@@ -1207,7 +1207,7 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
                                if (strcmp(np->name, p->name))
                                        continue;
                                if (p->compatible &&
-                                   !device_is_compatible(np, p->compatible))
+                                   !of_device_is_compatible(np, p->compatible))
                                        continue;
                                if (p->quirks & pmac_i2c_quirk_skip)
                                        break;
index 692945c149194e77914318f71a9f8240567664d8..c6f0f9e738e562293eca7a71f486e2d6405135e2 100644 (file)
@@ -553,7 +553,7 @@ static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
         * identify the chip using flash id commands and base ourselves on
         * a list of known chips IDs
         */
-       if (device_is_compatible(dp, "amd-0137")) {
+       if (of_device_is_compatible(dp, "amd-0137")) {
                core99_erase_bank = amd_erase_bank;
                core99_write_bank = amd_write_bank;
        } else {
@@ -588,7 +588,7 @@ int __init pmac_nvram_init(void)
                }
        }
 
-       is_core_99 = device_is_compatible(dp, "nvram,flash");
+       is_core_99 = of_device_is_compatible(dp, "nvram,flash");
        if (is_core_99) {
                err = core99_nvram_setup(dp, r1.start);
                goto bail;
index 22c4ae4c69348350b0d155418b4fe678515ef0ea..c4af9e21ac9329532ca1bd7735fe336115576cf4 100644 (file)
@@ -934,15 +934,15 @@ static int __init add_bridge(struct device_node *dev)
 
        /* 64 bits only bridges */
 #ifdef CONFIG_PPC64
-       if (device_is_compatible(dev, "u3-agp")) {
+       if (of_device_is_compatible(dev, "u3-agp")) {
                setup_u3_agp(hose);
                disp_name = "U3-AGP";
                primary = 0;
-       } else if (device_is_compatible(dev, "u3-ht")) {
+       } else if (of_device_is_compatible(dev, "u3-ht")) {
                setup_u3_ht(hose);
                disp_name = "U3-HT";
                primary = 1;
-       } else if (device_is_compatible(dev, "u4-pcie")) {
+       } else if (of_device_is_compatible(dev, "u4-pcie")) {
                setup_u4_pcie(hose);
                disp_name = "U4-PCIE";
                primary = 0;
@@ -953,7 +953,7 @@ static int __init add_bridge(struct device_node *dev)
 
        /* 32 bits only bridges */
 #ifdef CONFIG_PPC32
-       if (device_is_compatible(dev, "uni-north")) {
+       if (of_device_is_compatible(dev, "uni-north")) {
                primary = setup_uninorth(hose, &rsrc);
                disp_name = "UniNorth";
        } else if (strcmp(dev->name, "pci") == 0) {
@@ -1129,21 +1129,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
                return 0;
 
        uninorth_child = node->parent &&
-               device_is_compatible(node->parent, "uni-north");
+               of_device_is_compatible(node->parent, "uni-north");
 
        /* Firewire & GMAC were disabled after PCI probe, the driver is
         * claiming them, we must re-enable them now.
         */
        if (uninorth_child && !strcmp(node->name, "firewire") &&
-           (device_is_compatible(node, "pci106b,18") ||
-            device_is_compatible(node, "pci106b,30") ||
-            device_is_compatible(node, "pci11c1,5811"))) {
+           (of_device_is_compatible(node, "pci106b,18") ||
+            of_device_is_compatible(node, "pci106b,30") ||
+            of_device_is_compatible(node, "pci11c1,5811"))) {
                pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
                pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
                updatecfg = 1;
        }
        if (uninorth_child && !strcmp(node->name, "ethernet") &&
-           device_is_compatible(node, "gmac")) {
+           of_device_is_compatible(node, "gmac")) {
                pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
                updatecfg = 1;
        }
@@ -1203,18 +1203,18 @@ void __init pmac_pcibios_after_init(void)
 #endif /* CONFIG_BLK_DEV_IDE */
 
        for_each_node_by_name(nd, "firewire") {
-               if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
-                                  device_is_compatible(nd, "pci106b,30") ||
-                                  device_is_compatible(nd, "pci11c1,5811"))
-                   && device_is_compatible(nd->parent, "uni-north")) {
+               if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") ||
+                                  of_device_is_compatible(nd, "pci106b,30") ||
+                                  of_device_is_compatible(nd, "pci11c1,5811"))
+                   && of_device_is_compatible(nd->parent, "uni-north")) {
                        pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
                        pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
                }
        }
        of_node_put(nd);
        for_each_node_by_name(nd, "ethernet") {
-               if (nd->parent && device_is_compatible(nd, "gmac")
-                   && device_is_compatible(nd->parent, "uni-north"))
+               if (nd->parent && of_device_is_compatible(nd, "gmac")
+                   && of_device_is_compatible(nd->parent, "uni-north"))
                        pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
        }
        of_node_put(nd);
index ae5097ac0378118855d2267caa3655acba306d40..87cd6805171a6bb4b4e3c7775a22d6c175098516 100644 (file)
@@ -364,7 +364,7 @@ static void __init pmac_pic_probe_oldstyle(void)
                slave = of_find_node_by_name(master, "mac-io");
 
                /* Check ordering of master & slave */
-               if (device_is_compatible(master, "gatwick")) {
+               if (of_device_is_compatible(master, "gatwick")) {
                        struct device_node *tmp;
                        BUG_ON(slave == NULL);
                        tmp = master;
index b820cabac697ceef08d9a786ded2e37ccbe1df3e..a410bc76a8a8ee5cc4bb2226a0906e37e7054329 100644 (file)
@@ -439,76 +439,14 @@ static void __init find_boot_device(void)
 #endif
 }
 
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
-       printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-       return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
-       printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-       /* Giveup the lazy FPU & vec so we don't have to back them
-        * up from the low level code
-        */
-       enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-       if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
-               enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-       return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
-       printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-       /* Restore userland MMU context */
-       set_context(current->active_mm->context.id, current->active_mm->pgd);
-
-       return 0;
-}
-
-static int pmac_pm_valid(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_DISK:
-               return 1;
-       /* can't do any other states via generic mechanism yet */
-       default:
-               return 0;
-       }
-}
-
-static struct pm_ops pmac_pm_ops = {
-       .pm_disk_mode   = PM_DISK_SHUTDOWN,
-       .prepare        = pmac_pm_prepare,
-       .enter          = pmac_pm_enter,
-       .finish         = pmac_pm_finish,
-       .valid          = pmac_pm_valid,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
 static int initializing = 1;
 
 static int pmac_late_init(void)
 {
        initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
-       pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
+       /* this is udbg (which is __init) and we can later use it during
+        * cpu hotplug (in smp_core99_kick_cpu) */
+       ppc_md.progress = NULL;
        return 0;
 }
 
@@ -721,12 +659,57 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
        /* We need to use normal PCI probing for the AGP bus,
         * since the device for the AGP bridge isn't in the tree.
         */
-       if (bus->self == NULL && (device_is_compatible(node, "u3-agp") ||
-                                 device_is_compatible(node, "u4-pcie")))
+       if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
+                                 of_device_is_compatible(node, "u4-pcie")))
                return PCI_PROBE_NORMAL;
        return PCI_PROBE_DEVTREE;
 }
-#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+       /*
+        * turn off as much as possible, we'll be
+        * kicked out as this will only be invoked
+        * on core99 platforms for now ...
+        */
+
+       printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+       __get_cpu_var(cpu_state) = CPU_DEAD;
+       smp_wmb();
+
+       /*
+        * during the path that leads here preemption is disabled,
+        * reenable it now so that when coming up preempt count is
+        * zero correctly
+        */
+       preempt_enable();
+
+       /*
+        * hard-disable interrupts for the non-NAP case, the NAP code
+        * needs to re-enable interrupts (but soft-disables them)
+        */
+       hard_irq_disable();
+
+       while (1) {
+               /* let's not take timer interrupts too often ... */
+               set_dec(0x7fffffff);
+
+               /* should always be true at this point */
+               if (cpu_has_feature(CPU_FTR_CAN_NAP))
+                       power4_cpu_offline_powersave();
+               else {
+                       HMT_low();
+                       HMT_very_low();
+               }
+       }
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#endif /* CONFIG_PPC64 */
 
 define_machine(powermac) {
        .name                   = "PowerMac",
@@ -763,6 +746,6 @@ define_machine(powermac) {
        .phys_mem_access_prot   = pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-       .cpu_die                = generic_mach_cpu_die,
+       .cpu_die                = pmac_cpu_die,
 #endif
 };
index 6f32c4eca6e5f48c78eda6f00fd3c98087290537..686ed82bde79a6608abcf5915848a47a6ff8ffc8 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
@@ -562,7 +561,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
        /* Look for the clock chip */
        while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
                p = of_get_parent(cc);
-               ok = p && device_is_compatible(p, "uni-n-i2c");
+               ok = p && of_device_is_compatible(p, "uni-n-i2c");
                of_node_put(p);
                if (!ok)
                        continue;
@@ -575,11 +574,11 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
                        continue;
                switch (*reg) {
                case 0xd2:
-                       if (device_is_compatible(cc,"pulsar-legacy-slewing")) {
+                       if (of_device_is_compatible(cc,"pulsar-legacy-slewing")) {
                                pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
                                pmac_tb_pulsar_addr = 0xd2;
                                name = "Pulsar";
-                       } else if (device_is_compatible(cc, "cy28508")) {
+                       } else if (of_device_is_compatible(cc, "cy28508")) {
                                pmac_tb_freeze = smp_core99_cypress_tb_freeze;
                                name = "Cypress";
                        }
@@ -900,7 +899,7 @@ void smp_core99_cpu_die(unsigned int cpu)
        cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
@@ -910,8 +909,16 @@ struct smp_ops_t core99_smp_ops = {
        .setup_cpu      = smp_core99_setup_cpu,
        .give_timebase  = smp_core99_give_timebase,
        .take_timebase  = smp_core99_take_timebase,
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+#if defined(CONFIG_HOTPLUG_CPU)
+# if defined(CONFIG_PPC32)
        .cpu_disable    = smp_core99_cpu_disable,
        .cpu_die        = smp_core99_cpu_die,
+# endif
+# if defined(CONFIG_PPC64)
+       .cpu_disable    = generic_cpu_disable,
+       .cpu_die        = generic_cpu_die,
+       /* intentionally do *NOT* assign cpu_enable,
+        * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
index ea60c451cf87f65e02c04284f9682f2642071bf0..a1409e450c70172faa23bdeb85c2a8021054b5aa 100644 (file)
@@ -273,7 +273,8 @@ void __init ps3_map_htab(void)
 
        result = lv1_map_htab(0, &htab_addr);
 
-       htab = (hpte_t *)__ioremap(htab_addr, htab_size, PAGE_READONLY_X);
+       htab = (hpte_t *)__ioremap(htab_addr, htab_size,
+                                  pgprot_val(PAGE_READONLY_X));
 
        DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
                htab_addr, (unsigned long)htab);
index 631c30095617889efa43a8af7dcde0bbfc91c998..9da82c266ba9ccc45110a5b2daa9f32004253001 100644 (file)
@@ -89,7 +89,18 @@ struct ps3_private {
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
 
-int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
+/**
+ * ps3_virq_setup - virq related setup.
+ * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
+ * serviced on.
+ * @outlet: The HV outlet from the various create outlet routines.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls irq_create_mapping() to get a virq and sets the chip data to
+ * ps3_private data.
+ */
+
+int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
        unsigned int *virq)
 {
        int result;
@@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
                goto fail_create;
        }
 
-       /* Binds outlet to cpu + virq. */
-
-       result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
-
-       if (result) {
-               pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
-               __func__, __LINE__, ps3_result(result));
-               result = -EPERM;
-               goto fail_connect;
-       }
-
        pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
                outlet, cpu, *virq);
 
@@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
        return result;
 
 fail_set:
-       lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq);
-fail_connect:
        irq_dispose_mapping(*virq);
 fail_create:
        return result;
 }
-EXPORT_SYMBOL_GPL(ps3_alloc_irq);
 
-int ps3_free_irq(unsigned int virq)
+/**
+ * ps3_virq_destroy - virq related teardown.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears chip data and calls irq_dispose_mapping() for the virq.
+ */
+
+int ps3_virq_destroy(unsigned int virq)
 {
-       int result;
        const struct ps3_private *pd = get_irq_chip_data(virq);
 
        pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
                pd->node, pd->cpu, virq);
 
-       result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
-
-       if (result)
-               pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
-               __func__, __LINE__, ps3_result(result));
-
        set_irq_chip_data(virq, NULL);
        irq_dispose_mapping(virq);
-       return result;
+
+       pr_debug("%s:%d <-\n", __func__, __LINE__);
+       return 0;
 }
-EXPORT_SYMBOL_GPL(ps3_free_irq);
 
 /**
- * ps3_alloc_io_irq - Assign a virq to a system bus device.
+ * ps3_irq_plug_setup - Generic outlet and virq related setup.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @outlet: The HV outlet from the various create outlet routines.
  * @virq: The assigned Linux virq.
  *
- * An io irq represents a non-virtualized device interrupt.  interrupt_id
- * coresponds to the interrupt number of the interrupt controller.
+ * Sets up virq and connects the irq plug.
  */
 
-int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
        unsigned int *virq)
 {
        int result;
-       unsigned long outlet;
+       struct ps3_private *pd;
 
-       result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
+       result = ps3_virq_setup(cpu, outlet, virq);
 
        if (result) {
-               pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
-                       __func__, __LINE__, ps3_result(result));
-               return result;
+               pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
+               goto fail_setup;
        }
 
-       result = ps3_alloc_irq(cpu, outlet, virq);
-       BUG_ON(result);
+       pd = get_irq_chip_data(*virq);
+
+       /* Binds outlet to cpu + virq. */
+
+       result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
 
+       if (result) {
+               pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
+               __func__, __LINE__, ps3_result(result));
+               result = -EPERM;
+               goto fail_connect;
+       }
+
+       return result;
+
+fail_connect:
+       ps3_virq_destroy(*virq);
+fail_setup:
        return result;
 }
-EXPORT_SYMBOL_GPL(ps3_alloc_io_irq);
+EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
+
+/**
+ * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
+ * @virq: The assigned Linux virq.
+ *
+ * Disconnects the irq plug and tears down virq.
+ * Do not call for system bus event interrupts setup with
+ * ps3_sb_event_receive_port_setup().
+ */
 
-int ps3_free_io_irq(unsigned int virq)
+int ps3_irq_plug_destroy(unsigned int virq)
 {
        int result;
+       const struct ps3_private *pd = get_irq_chip_data(virq);
 
-       result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+       pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
+               pd->node, pd->cpu, virq);
+
+       result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
 
        if (result)
-               pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
-                       __func__, __LINE__, ps3_result(result));
+               pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
+               __func__, __LINE__, ps3_result(result));
 
-       ps3_free_irq(virq);
+       ps3_virq_destroy(virq);
 
        return result;
 }
-EXPORT_SYMBOL_GPL(ps3_free_io_irq);
+EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
 
 /**
- * ps3_alloc_event_irq - Allocate a virq for use with a system event.
+ * ps3_event_receive_port_setup - Setup an event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
  * @virq: The assigned Linux virq.
  *
  * The virq can be used with lv1_connect_interrupt_event_receive_port() to
- * arrange to receive events, or with ps3_send_event_locally() to signal
- * events.
+ * arrange to receive interrupts from system-bus devices, or with
+ * ps3_send_event_locally() to signal events.
  */
 
-int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
+int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
 {
        int result;
        unsigned long outlet;
@@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
                return result;
        }
 
-       result = ps3_alloc_irq(cpu, outlet, virq);
+       result = ps3_irq_plug_setup(cpu, outlet, virq);
        BUG_ON(result);
 
        return result;
 }
+EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
+
+/**
+ * ps3_event_receive_port_destroy - Destroy an event receive port.
+ * @virq: The assigned Linux virq.
+ *
+ * Since ps3_event_receive_port_destroy destroys the receive port outlet,
+ * SB devices need to call disconnect_interrupt_event_receive_port() before
+ * this.
+ */
 
-int ps3_free_event_irq(unsigned int virq)
+int ps3_event_receive_port_destroy(unsigned int virq)
 {
        int result;
 
-       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+       pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
 
        result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq)
                pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
 
-       ps3_free_irq(virq);
+       /* lv1_destruct_event_receive_port() destroys the IRQ plug,
+        * so don't call ps3_irq_plug_destroy() here.
+        */
+
+       result = ps3_virq_destroy(virq);
+       BUG_ON(result);
 
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
+EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
 
 int ps3_send_event_locally(unsigned int virq)
 {
@@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int virq)
 }
 
 /**
- * ps3_connect_event_irq - Assign a virq to a system bus device.
+ * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
  * @did: The HV device identifier read from the system repository.
@@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq)
  * coresponds to the software interrupt number.
  */
 
-int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
+int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
        const struct ps3_device_id *did, unsigned int interrupt_id,
        unsigned int *virq)
 {
+       /* this should go in system-bus.c */
+
        int result;
 
-       result = ps3_alloc_event_irq(cpu, virq);
+       result = ps3_event_receive_port_setup(cpu, virq);
 
        if (result)
                return result;
@@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
                pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
                        " failed: %s\n", __func__, __LINE__,
                        ps3_result(result));
-               ps3_free_event_irq(*virq);
+               ps3_event_receive_port_destroy(*virq);
                *virq = NO_IRQ;
                return result;
        }
@@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
 
        return 0;
 }
+EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 
-int ps3_disconnect_event_irq(const struct ps3_device_id *did,
+int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
        unsigned int interrupt_id, unsigned int virq)
 {
+       /* this should go in system-bus.c */
+
        int result;
 
        pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
@@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
                        " failed: %s\n", __func__, __LINE__,
                        ps3_result(result));
 
-       ps3_free_event_irq(virq);
+       result = ps3_event_receive_port_destroy(virq);
+       BUG_ON(result);
 
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
+EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
 
 /**
- * ps3_alloc_vuart_irq - Configure the system virtual uart virq.
+ * ps3_io_irq_setup - Setup a system bus io irq.
+ * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
+ * serviced on.
+ * @interrupt_id: The device interrupt id read from the system repository.
+ * @virq: The assigned Linux virq.
+ *
+ * An io irq represents a non-virtualized device interrupt.  interrupt_id
+ * coresponds to the interrupt number of the interrupt controller.
+ */
+
+int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+       unsigned int *virq)
+{
+       int result;
+       unsigned long outlet;
+
+       result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
+
+       if (result) {
+               pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       result = ps3_irq_plug_setup(cpu, outlet, virq);
+       BUG_ON(result);
+
+       return result;
+}
+EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
+
+int ps3_io_irq_destroy(unsigned int virq)
+{
+       int result;
+
+       result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+
+       if (result)
+               pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
+       result = ps3_irq_plug_destroy(virq);
+       BUG_ON(result);
+
+       return result;
+}
+EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
+
+/**
+ * ps3_vuart_irq_setup - Setup the system virtual uart virq.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
  * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
@@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
  * freeing the interrupt will return a wrong state error.
  */
 
-int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
+int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
        unsigned int *virq)
 {
        int result;
@@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
                return result;
        }
 
-       result = ps3_alloc_irq(cpu, outlet, virq);
+       result = ps3_irq_plug_setup(cpu, outlet, virq);
        BUG_ON(result);
 
        return result;
 }
 
-int ps3_free_vuart_irq(unsigned int virq)
+int ps3_vuart_irq_destroy(unsigned int virq)
 {
        int result;
 
@@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq)
                return result;
        }
 
-       ps3_free_irq(virq);
+       result = ps3_irq_plug_destroy(virq);
+       BUG_ON(result);
 
        return result;
 }
 
 /**
- * ps3_alloc_spe_irq - Configure an spe virq.
+ * ps3_spe_irq_setup - Setup an spe virq.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
  * @spe_id: The spe_id returned from lv1_construct_logical_spe().
@@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq)
  *
  */
 
-int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
+int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
        unsigned int class, unsigned int *virq)
 {
        int result;
@@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
                return result;
        }
 
-       result = ps3_alloc_irq(cpu, outlet, virq);
+       result = ps3_irq_plug_setup(cpu, outlet, virq);
        BUG_ON(result);
 
        return result;
 }
 
-int ps3_free_spe_irq(unsigned int virq)
+int ps3_spe_irq_destroy(unsigned int virq)
 {
-       ps3_free_irq(virq);
+       int result = ps3_irq_plug_destroy(virq);
+       BUG_ON(result);
        return 0;
 }
 
index 2014d2b444496f95526b4e659f3715134361ff67..f8a3e206c584b42f97b811da0b09b1402633bb95 100644 (file)
@@ -826,5 +826,4 @@ void __init ps3_mm_init(void)
 void ps3_mm_shutdown(void)
 {
        ps3_mm_region_destroy(&map.r1);
-       map.total = map.rm.size;
 }
index ac5df9688dcb9685e06434e901b0b200498dba84..c9894933084f212131831e5fedd2a335200e81ba 100644 (file)
@@ -137,6 +137,12 @@ early_param("ps3fb", early_parse_ps3fb);
 #define prealloc_ps3fb_videomemory()   do { } while (0)
 #endif
 
+static int ps3_set_dabr(u64 dabr)
+{
+       enum {DABR_USER = 1, DABR_KERNEL = 2,};
+
+       return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0;
+}
 
 static void __init ps3_setup_arch(void)
 {
@@ -234,6 +240,7 @@ define_machine(ps3) {
        .get_boot_time                  = ps3_get_boot_time,
        .set_rtc_time                   = ps3_set_rtc_time,
        .get_rtc_time                   = ps3_get_rtc_time,
+       .set_dabr                       = ps3_set_dabr,
        .calibrate_decr                 = ps3_calibrate_decr,
        .progress                       = ps3_progress,
        .restart                        = ps3_restart,
index 6fb887961a6d16128dfb203b9e5b18a5dbfc686d..8729348c06083af49b71ea18e78d4ee87e5471ab 100644 (file)
@@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu)
        BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
 
        for (i = 0; i < MSG_COUNT; i++) {
-               result = ps3_alloc_event_irq(cpu, &virqs[i]);
+               result = ps3_event_receive_port_setup(cpu, &virqs[i]);
 
                if (result)
                        continue;
@@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu)
        int i;
 
        DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+
        for (i = 0; i < MSG_COUNT; i++) {
-               ps3_free_event_irq(virqs[i]);
                free_irq(virqs[i], (void*)(long)i);
+               ps3_event_receive_port_destroy(virqs[i]);
                virqs[i] = NO_IRQ;
        }
+
        DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
 }
 
index a397e4e17c13ca93230f2a33977b4627170c3f21..651437cb2c183f0fab1938bd42cde56ef5f48670 100644 (file)
@@ -184,7 +184,7 @@ static int __init setup_areas(struct spu *spu)
 
        spu_pdata(spu)->shadow = __ioremap(
                spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
-               PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED);
+               pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
        if (!spu_pdata(spu)->shadow) {
                pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
                goto fail_ioremap;
@@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu)
 {
        int result;
 
-       result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+       result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
                0, &spu->irqs[0]);
 
        if (result)
                goto fail_alloc_0;
 
-       result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+       result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
                1, &spu->irqs[1]);
 
        if (result)
                goto fail_alloc_1;
 
-       result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+       result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
                2, &spu->irqs[2]);
 
        if (result)
@@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu)
        return result;
 
 fail_alloc_2:
-       ps3_free_spe_irq(spu->irqs[1]);
+       ps3_spe_irq_destroy(spu->irqs[1]);
 fail_alloc_1:
-       ps3_free_spe_irq(spu->irqs[0]);
+       ps3_spe_irq_destroy(spu->irqs[0]);
 fail_alloc_0:
        spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
        return result;
@@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu)
        result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
        BUG_ON(result);
 
-       ps3_free_spe_irq(spu->irqs[2]);
-       ps3_free_spe_irq(spu->irqs[1]);
-       ps3_free_spe_irq(spu->irqs[0]);
+       ps3_spe_irq_destroy(spu->irqs[2]);
+       ps3_spe_irq_destroy(spu->irqs[1]);
+       ps3_spe_irq_destroy(spu->irqs[0]);
 
        spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
 
index 90235d598751ab442221f104a9962574bcc8a0e9..ae1fc92dc1c976a7f397c9d04f2375e1bd2d7bf0 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_SCANLOG) += scanlog.o
 obj-$(CONFIG_EEH)      += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
 obj-$(CONFIG_KEXEC)    += kexec.o
 obj-$(CONFIG_PCI)      += pci.o pci_dlpar.o
+obj-$(CONFIG_PCI_MSI)  += msi.o
 
 obj-$(CONFIG_HOTPLUG_CPU)      += hotplug-cpu.o
 
index 48fbd442e9dfbef36bcd26fcaac748fc42b0eb05..093438b93bd9e102e9e332988f9c763af385958f 100644 (file)
@@ -100,6 +100,9 @@ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
 static DEFINE_SPINLOCK(slot_errbuf_lock);
 static int eeh_error_buf_size;
 
+#define EEH_PCI_REGS_LOG_LEN 4096
+static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
+
 /* System monitoring statistics */
 static unsigned long no_device;
 static unsigned long no_dn;
@@ -115,7 +118,8 @@ static unsigned long slot_resets;
 /* --------------------------------------------------------------- */
 /* Below lies the EEH event infrastructure */
 
-void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
+static void rtas_slot_error_detail(struct pci_dn *pdn, int severity,
+                                   char *driver_log, size_t loglen)
 {
        int config_addr;
        unsigned long flags;
@@ -133,7 +137,8 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
        rc = rtas_call(ibm_slot_error_detail,
                       8, 1, NULL, config_addr,
                       BUID_HI(pdn->phb->buid),
-                      BUID_LO(pdn->phb->buid), NULL, 0,
+                      BUID_LO(pdn->phb->buid),
+                      virt_to_phys(driver_log), loglen,
                       virt_to_phys(slot_errbuf),
                       eeh_error_buf_size,
                       severity);
@@ -143,6 +148,84 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
        spin_unlock_irqrestore(&slot_errbuf_lock, flags);
 }
 
+/**
+ * gather_pci_data - copy assorted PCI config space registers to buff
+ * @pdn: device to report data for
+ * @buf: point to buffer in which to log
+ * @len: amount of room in buffer
+ *
+ * This routine captures assorted PCI configuration space data,
+ * and puts them into a buffer for RTAS error logging.
+ */
+static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
+{
+       u32 cfg;
+       int cap, i;
+       int n = 0;
+
+       n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name);
+       printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name);
+
+       rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg);
+       n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
+       printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);
+
+       rtas_read_config(pdn, PCI_COMMAND, 4, &cfg);
+       n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
+       printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);
+
+       /* Dump out the PCI-X command and status regs */
+       cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX);
+       if (cap) {
+               rtas_read_config(pdn, cap, 4, &cfg);
+               n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
+               printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);
+
+               rtas_read_config(pdn, cap+4, 4, &cfg);
+               n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
+               printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);
+       }
+
+       /* If PCI-E capable, dump PCI-E cap 10, and the AER */
+       cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP);
+       if (cap) {
+               n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
+               printk(KERN_WARNING
+                      "EEH: PCI-E capabilities and status follow:\n");
+
+               for (i=0; i<=8; i++) {
+                       rtas_read_config(pdn, cap+4*i, 4, &cfg);
+                       n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
+                       printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
+               }
+
+               cap = pci_find_ext_capability(pdn->pcidev,PCI_EXT_CAP_ID_ERR);
+               if (cap) {
+                       n += scnprintf(buf+n, len-n, "pci-e AER:\n");
+                       printk(KERN_WARNING
+                              "EEH: PCI-E AER capability register set follows:\n");
+
+                       for (i=0; i<14; i++) {
+                               rtas_read_config(pdn, cap+4*i, 4, &cfg);
+                               n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
+                               printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg);
+                       }
+               }
+       }
+       return n;
+}
+
+void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
+{
+       size_t loglen = 0;
+       memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN);
+
+       rtas_pci_enable(pdn, EEH_THAW_MMIO);
+       loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
+
+       rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen);
+}
+
 /**
  * read_slot_reset_state - Read the reset state of a device node's slot
  * @dn: device node to read
@@ -579,6 +662,36 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
                        rc, state, pdn->node->full_name);
 }
 
+/**
+ * pcibios_set_pcie_slot_reset - Set PCI-E reset state
+ * @dev:       pci device struct
+ * @state:     reset state to enter
+ *
+ * Return value:
+ *     0 if success
+ **/
+int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
+{
+       struct device_node *dn = pci_device_to_OF_node(dev);
+       struct pci_dn *pdn = PCI_DN(dn);
+
+       switch (state) {
+       case pcie_deassert_reset:
+               rtas_pci_slot_reset(pdn, 0);
+               break;
+       case pcie_hot_reset:
+               rtas_pci_slot_reset(pdn, 1);
+               break;
+       case pcie_warm_reset:
+               rtas_pci_slot_reset(pdn, 3);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       return 0;
+}
+
 /**
  * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
  * @pdn: pci device node to be reset.
index 3170e003f76ada0a313888fe30d51e06c3917c4c..f07d849cfc84837e47ee560a19746387b7c424f7 100644 (file)
@@ -361,11 +361,12 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
                goto hard_fail;
        }
 
-       eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
        printk(KERN_WARNING
-          "EEH: This PCI device has failed %d times since last reboot: "
-               "location=%s driver=%s pci addr=%s\n",
-               frozen_pdn->eeh_freeze_count, location, drv_str, pci_str);
+          "EEH: This PCI device has failed %d times in the last hour:\n",
+               frozen_pdn->eeh_freeze_count);
+       printk(KERN_WARNING
+               "EEH: location=%s driver=%s pci addr=%s\n",
+               location, drv_str, pci_str);
 
        /* Walk the various device drivers attached to this slot through
         * a reset sequence, giving each an opportunity to do what it needs
@@ -375,6 +376,11 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
         */
        pci_walk_bus(frozen_bus, eeh_report_error, &result);
 
+       /* Since rtas may enable MMIO when posting the error log,
+        * don't post the error log until after all dev drivers
+        * have been informed. */
+       eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
+
        /* If all device drivers were EEH-unaware, then shut
         * down all of the device drivers, and hope they
         * go down willingly, without panicing the system.
index 66665c82415cc7810a0e42787bd8d93a198e31bb..eec684a8e44e1bc7176df1f29120631d1b8f5474 100644 (file)
@@ -504,6 +504,12 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
                        break;
        }
 
+       if (!pdn || !PCI_DN(pdn)) {
+               printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
+                      "no DMA window found for pci dev=%s dn=%s\n",
+                                pci_name(dev), dn? dn->full_name : "<null>");
+               return;
+       }
        DBG("  parent is %s\n", pdn->full_name);
 
        /* Check for parent == NULL so we don't try to setup the empty EADS
index 3a70e8ad7bc84120948dbfe7199180a561de2d11..362dfbc260a69d4bc629ecf789676e21f07d4b71 100644 (file)
@@ -231,13 +231,13 @@ void __init find_udbg_vterm(void)
                goto out;
        vtermno = termno[0];
 
-       if (device_is_compatible(stdout_node, "hvterm1")) {
+       if (of_device_is_compatible(stdout_node, "hvterm1")) {
                udbg_putc = udbg_putcLP;
                udbg_getc = udbg_getcLP;
                udbg_getc_poll = udbg_getc_pollLP;
                if (add_console)
                        add_preferred_console("hvc", termno[0] & 0xff, NULL);
-       } else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
+       } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
                vtermno = termno[0];
                udbg_putc = udbg_hvsi_putc;
                udbg_getc = udbg_hvsi_getc;
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
new file mode 100644 (file)
index 0000000..6063ea2
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2006 Jake Moilanen <moilanen@austin.ibm.com>, IBM Corp.
+ * Copyright 2006-2007 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+
+#include <asm/rtas.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+static int query_token, change_token;
+
+#define RTAS_QUERY_FN          0
+#define RTAS_CHANGE_FN         1
+#define RTAS_RESET_FN          2
+#define RTAS_CHANGE_MSI_FN     3
+#define RTAS_CHANGE_MSIX_FN    4
+
+static struct pci_dn *get_pdn(struct pci_dev *pdev)
+{
+       struct device_node *dn;
+       struct pci_dn *pdn;
+
+       dn = pci_device_to_OF_node(pdev);
+       if (!dn) {
+               dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n");
+               return NULL;
+       }
+
+       pdn = PCI_DN(dn);
+       if (!pdn) {
+               dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n");
+               return NULL;
+       }
+
+       return pdn;
+}
+
+/* RTAS Helpers */
+
+static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
+{
+       u32 addr, seq_num, rtas_ret[3];
+       unsigned long buid;
+       int rc;
+
+       addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+       buid = pdn->phb->buid;
+
+       seq_num = 1;
+       do {
+               if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN)
+                       rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
+                                       BUID_HI(buid), BUID_LO(buid),
+                                       func, num_irqs, seq_num);
+               else
+                       rc = rtas_call(change_token, 6, 3, rtas_ret, addr,
+                                       BUID_HI(buid), BUID_LO(buid),
+                                       func, num_irqs, seq_num);
+
+               seq_num = rtas_ret[1];
+       } while (rtas_busy_delay(rc));
+
+       if (rc == 0) /* Success */
+               rc = rtas_ret[0];
+
+       pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n",
+                func, num_irqs, rc);
+
+       return rc;
+}
+
+static void rtas_disable_msi(struct pci_dev *pdev)
+{
+       struct pci_dn *pdn;
+
+       pdn = get_pdn(pdev);
+       if (!pdn)
+               return;
+
+       if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
+               pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+}
+
+static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
+{
+       u32 addr, rtas_ret[2];
+       unsigned long buid;
+       int rc;
+
+       addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+       buid = pdn->phb->buid;
+
+       do {
+               rc = rtas_call(query_token, 4, 3, rtas_ret, addr,
+                              BUID_HI(buid), BUID_LO(buid), offset);
+       } while (rtas_busy_delay(rc));
+
+       if (rc) {
+               pr_debug("rtas_msi: error (%d) querying source number\n", rc);
+               return rc;
+       }
+
+       return rtas_ret[0];
+}
+
+static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+
+               set_irq_msi(entry->irq, NULL);
+               irq_dispose_mapping(entry->irq);
+       }
+
+       rtas_disable_msi(pdev);
+}
+
+static int check_req_msi(struct pci_dev *pdev, int nvec)
+{
+       struct device_node *dn;
+       struct pci_dn *pdn;
+       const u32 *req_msi;
+
+       pdn = get_pdn(pdev);
+       if (!pdn)
+               return -ENODEV;
+
+       dn = pdn->node;
+
+       req_msi = of_get_property(dn, "ibm,req#msi", NULL);
+       if (!req_msi) {
+               pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name);
+               return -ENOENT;
+       }
+
+       if (*req_msi < nvec) {
+               pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec);
+               return -ENOSPC;
+       }
+
+       return 0;
+}
+
+static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSIX)
+               pr_debug("rtas_msi: MSI-X untested, trying anyway.\n");
+
+       return check_req_msi(pdev, nvec);
+}
+
+static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       struct pci_dn *pdn;
+       int hwirq, virq, i, rc;
+       struct msi_desc *entry;
+
+       pdn = get_pdn(pdev);
+       if (!pdn)
+               return -ENODEV;
+
+       /*
+        * Try the new more explicit firmware interface, if that fails fall
+        * back to the old interface. The old interface is known to never
+        * return MSI-Xs.
+        */
+       if (type == PCI_CAP_ID_MSI) {
+               rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
+
+               if (rc != nvec) {
+                       pr_debug("rtas_msi: trying the old firmware call.\n");
+                       rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
+               }
+       } else
+               rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
+
+       if (rc != nvec) {
+               pr_debug("rtas_msi: rtas_change_msi() failed\n");
+
+               /*
+                * In case of an error it's not clear whether the device is
+                * left with MSI enabled or not, so we explicitly disable.
+                */
+               goto out_free;
+       }
+
+       i = 0;
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               hwirq = rtas_query_irq_number(pdn, i);
+               if (hwirq < 0) {
+                       rc = hwirq;
+                       pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
+                       goto out_free;
+               }
+
+               virq = irq_create_mapping(NULL, hwirq);
+
+               if (virq == NO_IRQ) {
+                       pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
+                       rc = -ENOSPC;
+                       goto out_free;
+               }
+
+               dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
+               set_irq_msi(virq, entry);
+               unmask_msi_irq(virq);
+       }
+
+       return 0;
+
+ out_free:
+       rtas_teardown_msi_irqs(pdev);
+       return rc;
+}
+
+static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
+{
+       /* No LSI -> leave MSIs (if any) configured */
+       if (pdev->irq == NO_IRQ) {
+               dev_dbg(&pdev->dev, "rtas_msi: no LSI, nothing to do.\n");
+               return;
+       }
+
+       /* No MSI -> MSIs can't have been assigned by fw, leave LSI */
+       if (check_req_msi(pdev, 1)) {
+               dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n");
+               return;
+       }
+
+       dev_dbg(&pdev->dev, "rtas_msi: disabling existing MSI.\n");
+       rtas_disable_msi(pdev);
+}
+
+static int rtas_msi_init(void)
+{
+       query_token  = rtas_token("ibm,query-interrupt-source-number");
+       change_token = rtas_token("ibm,change-msi");
+
+       if ((query_token == RTAS_UNKNOWN_SERVICE) ||
+                       (change_token == RTAS_UNKNOWN_SERVICE)) {
+               pr_debug("rtas_msi: no RTAS tokens, no MSI support.\n");
+               return -1;
+       }
+
+       pr_debug("rtas_msi: Registering RTAS MSI callbacks.\n");
+
+       WARN_ON(ppc_md.setup_msi_irqs);
+       ppc_md.setup_msi_irqs = rtas_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs;
+       ppc_md.msi_check_device = rtas_msi_check_device;
+
+       WARN_ON(ppc_md.pci_irq_fixup);
+       ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;
+
+       return 0;
+}
+arch_initcall(rtas_msi_init);
index fdc1a369f767c971bee0b1ccf5f51b93cf539496..ffaf6c5c517bda0527945e4ff7146f28c668db19 100644 (file)
@@ -79,6 +79,7 @@ pcibios_remove_pci_devices(struct pci_bus *bus)
                pci_remove_bus_device(dev);
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
 /* Must be called before pci_bus_add_devices */
 void
index 33eec2822c668f21bac7c9a9577cc01ac94573e1..470db6efaeb635fdebbab2d93d14a7f031d58feb 100644 (file)
@@ -168,7 +168,7 @@ static void __init pseries_mpic_init_IRQ(void)
 
        /* Look for cascade */
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "chrp,iic")) {
+               if (of_device_is_compatible(np, "chrp,iic")) {
                        cascade = np;
                        break;
                }
index 896cbf340c429fd74615522532695d4b76880c7b..b854e7f1001c60c79697cd96c957b388a0fe7b98 100644 (file)
@@ -477,7 +477,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
         * like vdevices, events, etc... The trick we use here is to match
         * everything here except the legacy 8259 which is compatible "chrp,iic"
         */
-       return !device_is_compatible(node, "chrp,iic");
+       return !of_device_is_compatible(node, "chrp,iic");
 }
 
 static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
@@ -618,7 +618,7 @@ static void __init xics_setup_8259_cascade(void)
        unsigned long intack = 0;
 
        for_each_node_by_type(np, "interrupt-controller")
-               if (device_is_compatible(np, "chrp,iic")) {
+               if (of_device_is_compatible(np, "chrp,iic")) {
                        found = np;
                        break;
                }
index e96ca9618dbb39541d42973aa4ae1528b3929cd2..9ce775c38ab7a2696728a8ef18f5577d7b0847a3 100644 (file)
@@ -2,7 +2,9 @@ ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS                   += -mno-minimal-toc
 endif
 
-obj-$(CONFIG_MPIC)             += mpic.o
+mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
+obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
+
 obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
 obj-$(CONFIG_PPC_DCR)          += dcr.o
@@ -26,7 +28,6 @@ endif
 
 # Temporary hack until we have migrated to asm-powerpc
 ifeq ($(ARCH),powerpc)
-obj-$(CONFIG_MTD)              += rom.o
 obj-$(CONFIG_CPM2)             += cpm2_common.o cpm2_pic.o
 obj-$(CONFIG_8xx)              += mpc8xx_pic.o commproc.o
 obj-$(CONFIG_UCODE_PATCH)      += micropatch.o
index 336186dd7f10d2933a4ef02db41f625b6e9a51f8..a1d2042bb304be44dad2188fec3365d51f91cc0b 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
+#include <linux/suspend.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/iommu.h>
@@ -54,6 +55,9 @@ static unsigned long dart_tablesize;
 
 /* Virtual base address of the DART table */
 static u32 *dart_vbase;
+#ifdef CONFIG_PM
+static u32 *dart_copy;
+#endif
 
 /* Mapped base address for the dart */
 static unsigned int __iomem *dart;
@@ -346,6 +350,48 @@ void iommu_init_early_dart(void)
        set_pci_dma_ops(&dma_direct_ops);
 }
 
+#ifdef CONFIG_PM
+static void iommu_dart_save(void)
+{
+       memcpy(dart_copy, dart_vbase, 2*1024*1024);
+}
+
+static void iommu_dart_restore(void)
+{
+       memcpy(dart_vbase, dart_copy, 2*1024*1024);
+       dart_tlb_invalidate_all();
+}
+
+static int __init iommu_init_late_dart(void)
+{
+       unsigned long tbasepfn;
+       struct page *p;
+
+       /* if no dart table exists then we won't need to save it
+        * and the area has also not been reserved */
+       if (!dart_tablebase)
+               return 0;
+
+       tbasepfn = __pa(dart_tablebase) >> PAGE_SHIFT;
+       register_nosave_region_late(tbasepfn,
+                                   tbasepfn + ((1<<24) >> PAGE_SHIFT));
+
+       /* For suspend we need to copy the dart contents because
+        * it is not part of the regular mapping (see above) and
+        * thus not saved automatically. The memory for this copy
+        * must be allocated early because we need 2 MB. */
+       p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT);
+       BUG_ON(!p);
+       dart_copy = page_address(p);
+
+       ppc_md.iommu_save = iommu_dart_save;
+       ppc_md.iommu_restore = iommu_dart_restore;
+
+       return 0;
+}
+
+late_initcall(iommu_init_late_dart);
+#endif
 
 void __init alloc_dart_table(void)
 {
index 8a123c71449fffd9315b085158f0e1a8d6f5795a..cad175724359df4099a84b00c4af154cbd2362a5 100644 (file)
@@ -907,7 +907,7 @@ static int __init fs_enet_of_init(void)
                struct fs_platform_info fs_enet_data;
                const unsigned int *id;
                const unsigned int *phy_addr;
-               void *mac_addr;
+               const void *mac_addr;
                const phandle *ph;
                const char *model;
 
index 0b84b7c775d8c229ffe7289584810faf70d63710..4fd2bec89916f63d73b1184972035a2f40addd04 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/mpic.h>
 #include <asm/smp.h>
 
+#include "mpic.h"
+
 #ifdef DEBUG
 #define DBG(fmt...) printk(fmt)
 #else
@@ -354,6 +356,12 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
                tmp |= 0x22;
        writel(tmp, fixup->base + 4);
        spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+       /* use the lowest bit inverted to the actual HW,
+        * set if this fixup was enabled, clear otherwise */
+       mpic->save_data[source].fixup_data = tmp | 1;
+#endif
 }
 
 static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
@@ -375,8 +383,58 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
        tmp |= 1;
        writel(tmp, fixup->base + 4);
        spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+       /* use the lowest bit inverted to the actual HW,
+        * set if this fixup was enabled, clear otherwise */
+       mpic->save_data[source].fixup_data = tmp & ~1;
+#endif
 }
 
+#ifdef CONFIG_PCI_MSI
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+                                   unsigned int devfn)
+{
+       u8 __iomem *base;
+       u8 pos, flags;
+       u64 addr = 0;
+
+       for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+            pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+               u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+               if (id == PCI_CAP_ID_HT) {
+                       id = readb(devbase + pos + 3);
+                       if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
+                               break;
+               }
+       }
+
+       if (pos == 0)
+               return;
+
+       base = devbase + pos;
+
+       flags = readb(base + HT_MSI_FLAGS);
+       if (!(flags & HT_MSI_FLAGS_FIXED)) {
+               addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
+               addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
+       }
+
+       printk(KERN_DEBUG "mpic:   - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
+               PCI_SLOT(devfn), PCI_FUNC(devfn),
+               flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
+
+       if (!(flags & HT_MSI_FLAGS_ENABLE))
+               writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
+}
+#else
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+                                   unsigned int devfn)
+{
+       return;
+}
+#endif
+
 static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
                                    unsigned int devfn, u32 vdid)
 {
@@ -468,6 +526,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
                        goto next;
 
                mpic_scan_ht_pic(mpic, devbase, devfn, l);
+               mpic_scan_ht_msi(mpic, devbase, devfn);
 
        next:
                /* next device, if function 0 */
@@ -559,7 +618,7 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
  */
 
 
-static void mpic_unmask_irq(unsigned int irq)
+void mpic_unmask_irq(unsigned int irq)
 {
        unsigned int loops = 100000;
        struct mpic *mpic = mpic_from_irq(irq);
@@ -579,7 +638,7 @@ static void mpic_unmask_irq(unsigned int irq)
        } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
 }
 
-static void mpic_mask_irq(unsigned int irq)
+void mpic_mask_irq(unsigned int irq)
 {
        unsigned int loops = 100000;
        struct mpic *mpic = mpic_from_irq(irq);
@@ -600,7 +659,7 @@ static void mpic_mask_irq(unsigned int irq)
        } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
 }
 
-static void mpic_end_irq(unsigned int irq)
+void mpic_end_irq(unsigned int irq)
 {
        struct mpic *mpic = mpic_from_irq(irq);
 
@@ -733,7 +792,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
        }
 }
 
-static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
 {
        struct mpic *mpic = mpic_from_irq(virq);
        unsigned int src = mpic_irq_to_hw(virq);
@@ -834,6 +893,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
        if (hw >= mpic->irq_count)
                return -EINVAL;
 
+       mpic_msi_reserve_hwirq(mpic, hw);
+
        /* Default chip */
        chip = &mpic->hc_irq;
 
@@ -1142,8 +1203,10 @@ void __init mpic_init(struct mpic *mpic)
 
        /* Do the HT PIC fixups on U3 broken mpic */
        DBG("MPIC flags: %x\n", mpic->flags);
-       if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY))
-               mpic_scan_ht_pics(mpic);
+       if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) {
+               mpic_scan_ht_pics(mpic);
+               mpic_u3msi_init(mpic);
+       }
 
        for (i = 0; i < mpic->num_sources; i++) {
                /* start with vector = source number, and masked */
@@ -1167,6 +1230,12 @@ void __init mpic_init(struct mpic *mpic)
 
        /* Set current processor priority to 0 */
        mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
+
+#ifdef CONFIG_PM
+       /* allocate memory to save mpic state */
+       mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
+       BUG_ON(mpic->save_data == NULL);
+#endif
 }
 
 void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1333,8 +1402,11 @@ unsigned int mpic_get_one_irq(struct mpic *mpic)
 #ifdef DEBUG_LOW
        DBG("%s: get_one_irq(): %d\n", mpic->name, src);
 #endif
-       if (unlikely(src == mpic->spurious_vec))
+       if (unlikely(src == mpic->spurious_vec)) {
+               if (mpic->flags & MPIC_SPV_EOI)
+                       mpic_eoi(mpic);
                return NO_IRQ;
+       }
        return irq_linear_revmap(mpic->irqhost, src);
 }
 
@@ -1417,3 +1489,79 @@ void __devinit smp_mpic_setup_cpu(int cpu)
        mpic_setup_this_cpu();
 }
 #endif /* CONFIG_SMP */
+
+#ifdef CONFIG_PM
+static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+       int i;
+
+       for (i = 0; i < mpic->num_sources; i++) {
+               mpic->save_data[i].vecprio =
+                       mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
+               mpic->save_data[i].dest =
+                       mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
+       }
+
+       return 0;
+}
+
+static int mpic_resume(struct sys_device *dev)
+{
+       struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+       int i;
+
+       for (i = 0; i < mpic->num_sources; i++) {
+               mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
+                              mpic->save_data[i].vecprio);
+               mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+                              mpic->save_data[i].dest);
+
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+       {
+               struct mpic_irq_fixup *fixup = &mpic->fixups[i];
+
+               if (fixup->base) {
+                       /* we use the lowest bit in an inverted meaning */
+                       if ((mpic->save_data[i].fixup_data & 1) == 0)
+                               continue;
+
+                       /* Enable and configure */
+                       writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+
+                       writel(mpic->save_data[i].fixup_data & ~1,
+                              fixup->base + 4);
+               }
+       }
+#endif
+       } /* end for loop */
+
+       return 0;
+}
+#endif
+
+static struct sysdev_class mpic_sysclass = {
+#ifdef CONFIG_PM
+       .resume = mpic_resume,
+       .suspend = mpic_suspend,
+#endif
+       set_kset_name("mpic"),
+};
+
+static int mpic_init_sys(void)
+{
+       struct mpic *mpic = mpics;
+       int error, id = 0;
+
+       error = sysdev_class_register(&mpic_sysclass);
+
+       while (mpic && !error) {
+               mpic->sysdev.cls = &mpic_sysclass;
+               mpic->sysdev.id = id++;
+               error = sysdev_register(&mpic->sysdev);
+               mpic = mpic->next;
+       }
+       return error;
+}
+
+device_initcall(mpic_init_sys);
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
new file mode 100644 (file)
index 0000000..3a1c3d2
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _POWERPC_SYSDEV_MPIC_H
+#define _POWERPC_SYSDEV_MPIC_H
+
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#ifdef CONFIG_PCI_MSI
+extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+extern int mpic_msi_init_allocator(struct mpic *mpic);
+extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
+extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
+extern int mpic_u3msi_init(struct mpic *mpic);
+#else
+static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
+                                         irq_hw_number_t hwirq)
+{
+       return;
+}
+
+static inline int mpic_u3msi_init(struct mpic *mpic)
+{
+       return -1;
+}
+#endif
+
+extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern void mpic_end_irq(unsigned int irq);
+extern void mpic_mask_irq(unsigned int irq);
+extern void mpic_unmask_irq(unsigned int irq);
+
+#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
new file mode 100644 (file)
index 0000000..b076793
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/bitmap.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+
+static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+       pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
+       bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
+}
+
+void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+       unsigned long flags;
+
+       /* The mpic calls this even when there is no allocator setup */
+       if (!mpic->hwirq_bitmap)
+               return;
+
+       spin_lock_irqsave(&mpic->bitmap_lock, flags);
+       __mpic_msi_reserve_hwirq(mpic, hwirq);
+       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
+{
+       unsigned long flags;
+       int offset, order = get_count_order(num);
+
+       spin_lock_irqsave(&mpic->bitmap_lock, flags);
+       /*
+        * This is fast, but stricter than we need. We might want to add
+        * a fallback routine which does a linear search with no alignment.
+        */
+       offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
+                                        order);
+       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+
+       pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
+                num, order, offset);
+
+       return offset;
+}
+
+void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
+{
+       unsigned long flags;
+       int order = get_count_order(num);
+
+       pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
+                num, order, offset);
+
+       spin_lock_irqsave(&mpic->bitmap_lock, flags);
+       bitmap_release_region(mpic->hwirq_bitmap, offset, order);
+       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+       irq_hw_number_t hwirq;
+       struct irq_host_ops *ops = mpic->irqhost->ops;
+       struct device_node *np;
+       int flags, index, i;
+       struct of_irq oirq;
+
+       pr_debug("mpic: found U3, guessing msi allocator setup\n");
+
+       /* Reserve source numbers we know are reserved in the HW */
+       for (i = 0;   i < 8;   i++)
+               __mpic_msi_reserve_hwirq(mpic, i);
+
+       for (i = 42;  i < 46;  i++)
+               __mpic_msi_reserve_hwirq(mpic, i);
+
+       for (i = 100; i < 105; i++)
+               __mpic_msi_reserve_hwirq(mpic, i);
+
+       np = NULL;
+       while ((np = of_find_all_nodes(np))) {
+               pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+
+               index = 0;
+               while (of_irq_map_one(np, index++, &oirq) == 0) {
+                       ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+                                               oirq.size, &hwirq, &flags);
+                       __mpic_msi_reserve_hwirq(mpic, hwirq);
+               }
+       }
+
+       return 0;
+}
+#else
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+       return -1;
+}
+#endif
+
+static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
+{
+       int i, len;
+       const u32 *p;
+
+       p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
+       if (!p) {
+               pr_debug("mpic: no msi-available-ranges property found on %s\n",
+                         mpic->of_node->full_name);
+               return -ENODEV;
+       }
+
+       if (len % 8 != 0) {
+               printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
+                      "property on %s\n", mpic->of_node->full_name);
+               return -EINVAL;
+       }
+
+       bitmap_allocate_region(mpic->hwirq_bitmap, 0,
+                              get_count_order(mpic->irq_count));
+
+       /* Format is: (<u32 start> <u32 count>)+ */
+       len /= sizeof(u32);
+       for (i = 0; i < len / 2; i++, p += 2)
+               mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
+
+       return 0;
+}
+
+int mpic_msi_init_allocator(struct mpic *mpic)
+{
+       int rc, size;
+
+       BUG_ON(mpic->hwirq_bitmap);
+       spin_lock_init(&mpic->bitmap_lock);
+
+       size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
+       pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
+
+       if (mem_init_done)
+               mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
+       else
+               mpic->hwirq_bitmap = alloc_bootmem(size);
+
+       if (!mpic->hwirq_bitmap) {
+               pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
+               return -ENOMEM;
+       }
+
+       memset(mpic->hwirq_bitmap, 0, size);
+
+       rc = mpic_msi_reserve_dt_hwirqs(mpic);
+       if (rc) {
+               if (mpic->flags & MPIC_U3_HT_IRQS)
+                       rc = mpic_msi_reserve_u3_hwirqs(mpic);
+
+               if (rc)
+                       goto out_free;
+       }
+
+       return 0;
+
+ out_free:
+       if (mem_init_done)
+               kfree(mpic->hwirq_bitmap);
+
+       mpic->hwirq_bitmap = NULL;
+       return rc;
+}
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
new file mode 100644 (file)
index 0000000..305b864
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2006, Segher Boessenkool, IBM Corporation.
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* A bit ugly, can we get this from the pci_dev somehow? */
+static struct mpic *msi_mpic;
+
+static void mpic_u3msi_mask_irq(unsigned int irq)
+{
+       mask_msi_irq(irq);
+       mpic_mask_irq(irq);
+}
+
+static void mpic_u3msi_unmask_irq(unsigned int irq)
+{
+       mpic_unmask_irq(irq);
+       unmask_msi_irq(irq);
+}
+
+static struct irq_chip mpic_u3msi_chip = {
+       .shutdown       = mpic_u3msi_mask_irq,
+       .mask           = mpic_u3msi_mask_irq,
+       .unmask         = mpic_u3msi_unmask_irq,
+       .eoi            = mpic_end_irq,
+       .set_type       = mpic_set_irq_type,
+       .typename       = "MPIC-U3MSI",
+};
+
+static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
+{
+       u8 flags;
+       u32 tmp;
+       u64 addr;
+
+       pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);
+
+       if (flags & HT_MSI_FLAGS_FIXED)
+               return HT_MSI_FIXED_ADDR;
+
+       pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
+       addr = tmp & HT_MSI_ADDR_LO_MASK;
+       pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
+       addr = addr | ((u64)tmp << 32);
+
+       return addr;
+}
+
+static u64 find_ht_magic_addr(struct pci_dev *pdev)
+{
+       struct pci_bus *bus;
+       unsigned int pos;
+
+       for (bus = pdev->bus; bus; bus = bus->parent) {
+               pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
+               if (pos)
+                       return read_ht_magic_addr(bus->self, pos);
+       }
+
+       return 0;
+}
+
+static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSIX)
+               pr_debug("u3msi: MSI-X untested, trying anyway.\n");
+
+       /* If we can't find a magic address then MSI ain't gonna work */
+       if (find_ht_magic_addr(pdev) == 0) {
+               pr_debug("u3msi: no magic address found for %s\n",
+                        pci_name(pdev));
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       struct msi_desc *entry;
+
+        list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+
+               set_irq_msi(entry->irq, NULL);
+               mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
+               irq_dispose_mapping(entry->irq);
+       }
+
+       return;
+}
+
+static void u3msi_compose_msi_msg(struct pci_dev *pdev, int virq,
+                                 struct msi_msg *msg)
+{
+       u64 addr;
+
+       addr = find_ht_magic_addr(pdev);
+       msg->address_lo = addr & 0xFFFFFFFF;
+       msg->address_hi = addr >> 32;
+       msg->data = virq_to_hw(virq);
+
+       pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) at address 0x%lx\n",
+                virq, virq_to_hw(virq), addr);
+}
+
+static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       irq_hw_number_t hwirq;
+       int rc;
+       unsigned int virq;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               hwirq = mpic_msi_alloc_hwirqs(msi_mpic, 1);
+               if (hwirq < 0) {
+                       rc = hwirq;
+                       pr_debug("u3msi: failed allocating hwirq\n");
+                       goto out_free;
+               }
+
+               virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+               if (virq == NO_IRQ) {
+                       pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq);
+                       mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
+                       rc = -ENOSPC;
+                       goto out_free;
+               }
+
+               set_irq_msi(virq, entry);
+               set_irq_chip(virq, &mpic_u3msi_chip);
+               set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+
+               u3msi_compose_msi_msg(pdev, virq, &msg);
+               write_msi_msg(virq, &msg);
+
+               hwirq++;
+       }
+
+       return 0;
+
+ out_free:
+       u3msi_teardown_msi_irqs(pdev);
+       return rc;
+}
+
+int mpic_u3msi_init(struct mpic *mpic)
+{
+       int rc;
+
+       rc = mpic_msi_init_allocator(mpic);
+       if (rc) {
+               pr_debug("u3msi: Error allocating bitmap!\n");
+               return rc;
+       }
+
+       pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");
+
+       BUG_ON(msi_mpic);
+       msi_mpic = mpic;
+
+       WARN_ON(ppc_md.setup_msi_irqs);
+       ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
+       ppc_md.msi_check_device = u3msi_msi_check_device;
+
+       return 0;
+}
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
deleted file mode 100644 (file)
index c855a3b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * ROM device registration
- *
- * (C) 2006 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.
- */
-
-#include <linux/kernel.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
-
-static int __init powerpc_flash_init(void)
-{
-       struct device_node *node = NULL;
-
-       /*
-        * Register all the devices which type is "rom"
-        */
-       while ((node = of_find_node_by_type(node, "rom")) != NULL) {
-               if (node->name == NULL) {
-                       printk(KERN_WARNING "powerpc_flash_init: found 'rom' "
-                               "device, but with no name, skipping...\n");
-                       continue;
-               }
-               of_platform_device_create(node, node->name, NULL);
-       }
-       return 0;
-}
-
-arch_initcall(powerpc_flash_init);
index 337039ee51e623acf3c8c940639886757e76ca12..7d3b09b7d5449244683e97ab0b6539b9072a345c 100644 (file)
@@ -107,8 +107,9 @@ static int __init tsi108_eth_of_init(void)
                        goto err;
                }
 
-               mac_addr = of_get_property(np, "address", NULL);
-               memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+               mac_addr = of_get_mac_address(np);
+               if (mac_addr)
+                       memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
 
                ph = of_get_property(np, "phy-handle", NULL);
                phy = of_find_node_by_phandle(*ph);
@@ -129,6 +130,8 @@ static int __init tsi108_eth_of_init(void)
                tsi_eth_data.phyregs = res.start;
                tsi_eth_data.phy = *phy_id;
                tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
+               if (of_device_is_compatible(phy, "bcm54xx"))
+                       tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
                of_node_put(phy);
                ret =
                    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
index 58b9e7f8abf276b51406b0ddf421f6a0bd415836..2153163fa593b22643f09f2aa4b2d4a3ba1a3d55 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/tsi108.h>
+#include <asm/tsi108_pci.h>
 #include <asm/tsi108_irq.h>
 #include <asm/prom.h>
 
@@ -49,6 +50,7 @@
        ((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base)
 
 u32 tsi108_pci_cfg_base;
+static u32 tsi108_pci_cfg_phys;
 u32 tsi108_csr_vir_base;
 static struct device_node *pci_irq_node;
 static struct irq_host *pci_irq_host;
@@ -185,7 +187,7 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 
 void tsi108_clear_pci_cfg_error(void)
 {
-       tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS);
+       tsi108_clear_pci_error(tsi108_pci_cfg_phys);
 }
 
 static struct pci_ops tsi108_direct_pci_ops = {
@@ -193,17 +195,17 @@ static struct pci_ops tsi108_direct_pci_ops = {
        tsi108_direct_write_config
 };
 
-int __init tsi108_setup_pci(struct device_node *dev)
+int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
 {
        int len;
        struct pci_controller *hose;
        struct resource rsrc;
        const int *bus_range;
-       int primary = 0, has_address = 0;
+       int has_address = 0;
 
        /* PCI Config mapping */
-       tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS,
-                       TSI108_PCI_CFG_SIZE);
+       tsi108_pci_cfg_base = (u32)ioremap(cfg_phys, TSI108_PCI_CFG_SIZE);
+       tsi108_pci_cfg_phys = cfg_phys;
        DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
            tsi108_pci_cfg_base);
 
index 968fb40af9dc45adaa40a5c2e40227bf385de08c..89059895a20d0ef8f8866759eae18855f43030d4 100644 (file)
@@ -221,7 +221,7 @@ static struct uic * __init uic_init_one(struct device_node *node)
        const u32 *indexp, *dcrreg;
        int len;
 
-       BUG_ON(! device_is_compatible(node, "ibm,uic"));
+       BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
 
        uic = alloc_bootmem(sizeof(*uic));
        if (! uic)
index b481db1dacb4a7b3f2c35e49a0789612bbc591a7..28fdf4f50c274e2b574aacf58945e13af45c89a3 100644 (file)
@@ -1217,7 +1217,6 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
 {
        unsigned long size, offset;
        const char *name;
-       char *modname;
 
        *startp = *endp = 0;
        if (pc == 0)
@@ -1225,7 +1224,7 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
        if (setjmp(bus_error_jmp) == 0) {
                catch_memory_errors = 1;
                sync();
-               name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
+               name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
                if (name != NULL) {
                        *startp = pc - offset;
                        *endp = pc - offset + size;
index c5850a272650b688e462a9b1415e9c3514df5f1c..e8e94321b59e6fd653188c40078a6239cb8146a2 100644 (file)
@@ -35,7 +35,7 @@ int
 main(void)
 {
        DEFINE(THREAD, offsetof(struct task_struct, thread));
-       DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(MM, offsetof(struct task_struct, mm));
        DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(KSP, offsetof(struct thread_struct, ksp));
index 0a7e42d54eaf59dceca3eaa658b7db8986ffbe39..aa07b63c0a6cb95fca625d0afa7b2f9e62ff8234 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/capability.h>
 #include <linux/ctype.h>
 #include <linux/threads.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
index 96a55972b986bd7103270ceeabd037e21edbb4bb..055998575cb48ec3d484bb2094a7c2aa8e119d08 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
index 7ce5364fdb3b0d2243c072c1b21bdbe6c46dcc3c..bf72204125c57ec77553368a7d67b7cef3f655a6 100644 (file)
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc866ads-setup.c
+/*arch/ppc/platforms/mpc866ads_setup.c
  *
  * Platform setup for the Freescale mpc866ads board
  *
index 10659c24b1beb2c4369afe48868e2b86d719ec0d..9192777d0f78469c9791970327a2b97f4d7d47c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-ppc/ipic.c
+ * arch/ppc/syslib/ipic.c
  *
  * IPIC routines implementations.
  *
index 5dadca3e0d61646415f7fd17dce2d99ce1a4bd8b..c4b369b50f9ce243fc46ffab47d5e0077d56ed93 100644 (file)
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/dma-mapping.h>
 #include <asm/ppc4xx_dma.h>
 
 void
index 4a17dd3927c133ce7fdac31a04a4836c965295fd..3d4be1412f60cee2d32107f0b2200d9d55a22e71 100644 (file)
 
 #include <linux/platform_device.h>
 
+/* ML300/403 reference design framebuffer driver platform data struct */
+struct xilinxfb_platform_data {
+       u32 rotate_screen;
+       u32 screen_height_mm;
+       u32 screen_width_mm;
+};
+
 void __init virtex_early_serial_map(void);
 
 /* Prototype for device fixup routine.  Implement this routine in the
index ee89b33145d58584761159391ebea59117db1c51..81a2b92ab0c2b777d2a6dc3b7c594a9ffb547945 100644 (file)
@@ -567,9 +567,11 @@ appldata_cpu_notify(struct notifier_block *self,
 {
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                appldata_online_cpu((long) hcpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                appldata_offline_cpu((long) hcpu);
                break;
        default:
index 99ff9f08e4d737112c655ce539e52e9c78607189..d1defbbfcd8129ac1f3a5926e94a0a5a4f05d2e7 100644 (file)
@@ -54,7 +54,7 @@ config S390_PRNG
        default "m"
        help
          Select this option if you want to use the s390 pseudo random number
-         generator. The PRNG is part of the cryptograhic processor functions
+         generator. The PRNG is part of the cryptographic processor functions
          and uses triple-DES to generate secure random numbers like the
          ANSI X9.17 standard. The PRNG is usable via the char device
          /dev/prandom.
index ec514fe5ccd02bb3f652ef5c962e4eb5d3ba7ed6..1375f8a4469e8e89d56fadba47e9992fbcee6963 100644 (file)
@@ -15,7 +15,7 @@
 
 int main(void)
 {
-       DEFINE(__THREAD_info, offsetof(struct task_struct, thread_info),);
+       DEFINE(__THREAD_info, offsetof(struct task_struct, stack),);
        DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
        DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
        DEFINE(__THREAD_mm_segment,
index 80a54a0149ab5956935476b56b28855b262d6f15..a5692c460bad04ebbf2a7efb7053d6750916ec91 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index dabaf98943d0c2577aad6ea20e18bcf46e2c7515..a057ebf108a7733a413e3470f4c9f788817eecbb 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kallsyms.h>
 #include <linux/reboot.h>
 #include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -33,7 +34,6 @@
 #include <asm/s390_ext.h>
 #include <asm/lowcore.h>
 #include <asm/debug.h>
-#include <asm/kdebug.h>
 
 #ifndef CONFIG_64BIT
 #define ONELONG "%08lx: "
index 23c61f6d965b29f4593928ccd1b00e99320104c1..e39333ae0fcf29fb5312beb5342b1841e4781a3b 100644 (file)
@@ -24,8 +24,8 @@
 #include <linux/ptrace.h>
 #include <linux/preempt.h>
 #include <linux/stop_machine.h>
+#include <linux/kdebug.h>
 #include <asm/cacheflush.h>
-#include <asm/kdebug.h>
 #include <asm/sections.h>
 #include <asm/uaccess.h>
 #include <linux/module.h>
@@ -271,23 +271,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 }
 
 /* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                        struct pt_regs *regs)
 {
-       struct kretprobe_instance *ri;
+       ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
 
-       if ((ri = get_free_rp_inst(rp)) != NULL) {
-               ri->rp = rp;
-               ri->task = current;
-               ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
-
-               /* Replace the return addr with trampoline addr */
-               regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
-
-               add_rp_inst(ri);
-       } else {
-               rp->nmissed++;
-       }
+       /* Replace the return addr with trampoline addr */
+       regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
 }
 
 static int __kprobes kprobe_handler(struct pt_regs *regs)
@@ -671,3 +661,10 @@ int __init arch_init_kprobes(void)
 {
        return register_kprobe(&trampoline_p);
 }
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (p->addr == (kprobe_opcode_t *) & kretprobe_trampoline)
+               return 1;
+       return 0;
+}
index 11d9b0197626979a216e91f34182eaac7355e7d7..eb43c3b31269c64fe7da6f04f8a99bc53c82d2b2 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
index 3c41907799a11ab9cbcb2db3f772491427bb5ecc..d264671c1b71e996b38563a398e7109cb9946028 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 3754e2031b39f27014a649bc3ed4b68ac57e6e78..09f028a3266ba7698061422c3dfd5c0f2998827a 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
@@ -790,10 +789,12 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                if (sysdev_create_file(s, &attr_capability))
                        return NOTIFY_BAD;
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                sysdev_remove_file(s, &attr_capability);
                break;
        }
index 2e5c65a1863eaada4750a1c36ed0baa3ff3be5ea..515ff9011dd742e33a5bfb54c4d55d99818937d9 100644 (file)
@@ -59,7 +59,7 @@ static unsigned long save_context_stack(struct stack_trace *trace,
        }
 }
 
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
        register unsigned long sp asm ("15");
        unsigned long orig_sp, new_sp;
@@ -69,20 +69,16 @@ void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
        new_sp = save_context_stack(trace, &trace->skip, orig_sp,
                                S390_lowcore.panic_stack - PAGE_SIZE,
                                S390_lowcore.panic_stack);
-       if ((new_sp != orig_sp) && !trace->all_contexts)
+       if (new_sp != orig_sp)
                return;
        new_sp = save_context_stack(trace, &trace->skip, new_sp,
                                S390_lowcore.async_stack - ASYNC_SIZE,
                                S390_lowcore.async_stack);
-       if ((new_sp != orig_sp) && !trace->all_contexts)
+       if (new_sp != orig_sp)
                return;
-       if (task)
-               save_context_stack(trace, &trace->skip, new_sp,
-                                  (unsigned long) task_stack_page(task),
-                                  (unsigned long) task_stack_page(task) + THREAD_SIZE);
-       else
-               save_context_stack(trace, &trace->skip, new_sp,
-                                  S390_lowcore.thread_info,
-                                  S390_lowcore.thread_info + THREAD_SIZE);
+
+       save_context_stack(trace, &trace->skip, new_sp,
+                          S390_lowcore.thread_info,
+                          S390_lowcore.thread_info + THREAD_SIZE);
        return;
 }
index 3a77c22cda78443f427b8f36479162137285bebb..1c90c7e999782949ddf6efeda76f4c71fbead09e 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 711dae8da7ada19403d23ba51d84e26daffdf3a5..9c2872a7cca723f163ec91783ebf85315883d8ed 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
+#include <linux/sysdev.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/smp.h>
index 49dec830373ae40dbc8e84b7aed8a02862b689d7..cbfe73034c30154dd05ca70eb8760dcdd38f7167 100644 (file)
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/kdebug.h>
 #include <linux/kallsyms.h>
 #include <linux/reboot.h>
 #include <linux/kprobes.h>
@@ -40,7 +40,6 @@
 #include <asm/s390_ext.h>
 #include <asm/lowcore.h>
 #include <asm/debug.h>
-#include <asm/kdebug.h>
 
 /* Called from entry.S only */
 extern void handle_per_exception(struct pt_regs *regs);
@@ -70,20 +69,6 @@ static int kstack_depth_to_print = 12;
 static int kstack_depth_to_print = 20;
 #endif /* CONFIG_64BIT */
 
-ATOMIC_NOTIFIER_HEAD(s390die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 /*
  * For show_trace we have tree different stack to consider:
  *   - the panic stack which is used if the kernel stack has overflown
index 91f705adc3f90adca915c794e7af4a0170e0b696..8b924b359774a40abb9042c2737b5ac9f6c637a2 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/kdebug.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -30,7 +31,6 @@
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
-#include <asm/kdebug.h>
 #include <asm/s390_ext.h>
 
 #ifndef CONFIG_64BIT
index d74eb120a9c6b2255deb2812e8069b635f9b9a32..038179ecf6a904dd03fe65f9ab1d0654d4e2427a 100644 (file)
@@ -52,6 +52,9 @@ config GENERIC_IOMAP
 config GENERIC_TIME
        def_bool n
 
+config GENERIC_CLOCKEVENTS
+       def_bool n
+
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
@@ -436,11 +439,11 @@ endmenu
 
 menu "Timer and clock configuration"
 
-if !GENERIC_TIME
-
 config SH_TMU
        bool "TMU timer support"
        depends on CPU_SH3 || CPU_SH4
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        default y
        help
          This enables the use of the TMU as the system timer.
@@ -459,8 +462,6 @@ config SH_MTU2
        help
          This enables the use of the MTU2 as the system timer.
 
-endif
-
 config SH_TIMER_IRQ
        int
        default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
@@ -468,24 +469,6 @@ config SH_TIMER_IRQ
        default "140" if CPU_SUBTYPE_SH7206
        default "16"
 
-config NO_IDLE_HZ
-       bool "Dynamic tick timer"
-       help
-         Select this option if you want to disable continuous timer ticks
-         and have them programmed to occur as required. This option saves
-         power as the system can remain in idle state for longer.
-
-         By default dynamic tick is disabled during the boot, and can be
-         manually enabled with:
-
-           echo 1 > /sys/devices/system/timer/timer0/dyn_tick
-
-         Alternatively, if you want dynamic tick automatically enabled
-         during boot, pass "dyntick=enable" via the kernel command string.
-
-         Please note that dynamic tick may affect the accuracy of
-         timekeeping on some platforms depending on the implementation.
-
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
        default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
@@ -509,6 +492,8 @@ config SH_CLK_MD
        help
          MD2 - MD0 pin setting.
 
+source "kernel/time/Kconfig"
+
 endmenu
 
 menu "CPU Frequency scaling"
index a83a5d9587bb3532abd3c33ba4ee39f11f818e43..4058b4f50d44eda199717a64d09fc2e2169545ba 100644 (file)
@@ -93,6 +93,7 @@ static void __init landisk_setup(char **cmdline_p)
  */
 struct sh_machine_vector mv_landisk __initmv = {
        .mv_name = "LANDISK",
+       .mv_nr_irqs = 72,
        .mv_setup = landisk_setup,
        .mv_init_irq = init_landisk_IRQ,
 };
index 770defed9c4a886124b2ee8199094be8c62d1d07..52c7bfa57c2c64c18ba7d41b378a352d10a01f1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/sh/kernel/setup_7751se.c
+ * linux/arch/sh/boards/se/7751/setup.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
  *
index 6cb92676c5fc4a51178a72524a61ee6d93ac7f11..e13f06bebd9221c9247d27754b0fcd396eb11e57 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for the Linux SuperH-specific device drivers.
 #
 
+obj-y          += dma/
+
 obj-$(CONFIG_PCI)              += pci/
-obj-$(CONFIG_SH_DMA)           += dma/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_PUSH_SWITCH)      += push-switch.o
 obj-$(CONFIG_HEARTBEAT)                += heartbeat.o
index defc13c37d483c3d4b064f1035609546ba3d4633..99935f9daf4b89b53825eefdf7df3ae2546e4d10 100644 (file)
@@ -1,12 +1,12 @@
 menu "DMA support"
 
-config SH_DMA
-       bool "DMA controller (DMAC) support"
-       help
-         Selecting this option will provide same API as PC's Direct Memory
-         Access Controller(8237A) for SuperH DMAC.
+config SH_DMA_API
+       bool
 
-         If unsure, say N.
+config SH_DMA
+       bool "SuperH on-chip DMA controller (DMAC) support"
+       select SH_DMA_API
+       default n
 
 config NR_ONCHIP_DMA_CHANNELS
        depends on SH_DMA
@@ -53,4 +53,12 @@ config DMA_PAGE_OPS_CHANNEL
          in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
          are dual-address capable.
 
+config SH_DMABRG
+       bool "SH7760 DMABRG support"
+       depends on CPU_SUBTYPE_SH7760
+       help
+         The DMABRG does data transfers from main memory to Audio/USB units
+         of the SH7760.
+         Say Y if you want to use Audio/USB DMA on your SH7760 board.
+
 endmenu
index db1295d32268b51fdd393227bac89a0347004696..1ac812d2448837dd02ae30a784ab91d69554f349 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the SuperH DMA specific kernel interface routines under Linux.
 #
 
-obj-y                          += dma-api.o
+obj-$(CONFIG_SH_DMA_API)       += dma-api.o dma-sysfs.o
 obj-$(CONFIG_ISA_DMA_API)      += dma-isa.o
-obj-$(CONFIG_SYSFS)            += dma-sysfs.o
 obj-$(CONFIG_SH_DMA)           += dma-sh.o
 obj-$(CONFIG_SH_DREAMCAST)     += dma-pvr2.o dma-g2.o
+obj-$(CONFIG_SH_DMABRG)                += dmabrg.o
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
new file mode 100644 (file)
index 0000000..9d0a293
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * SH7760 DMABRG IRQ handling
+ *
+ * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
+ *  licensed under the GPLv2.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/dmabrg.h>
+#include <asm/io.h>
+
+/*
+ * The DMABRG is a special DMA unit within the SH7760. It does transfers
+ * from USB-SRAM/Audio units to main memory (and also the LCDC; but that
+ * part is sensibly placed  in the LCDC  registers and requires no irqs)
+ * It has 3 IRQ lines which trigger 10 events, and works independently
+ * from the traditional SH DMAC (although it blocks usage of DMAC 0)
+ *
+ * BRGIRQID   | component | dir | meaning      | source
+ * -----------------------------------------------------
+ *     0      | USB-DMA   | ... | xfer done    | DMABRGI1
+ *     1      | USB-UAE   | ... | USB addr err.| DMABRGI0
+ *     2      | HAC0/SSI0 | play| all done     | DMABRGI1
+ *     3      | HAC0/SSI0 | play| half done    | DMABRGI2
+ *     4      | HAC0/SSI0 | rec | all done     | DMABRGI1
+ *     5      | HAC0/SSI0 | rec | half done    | DMABRGI2
+ *     6      | HAC1/SSI1 | play| all done     | DMABRGI1
+ *     7      | HAC1/SSI1 | play| half done    | DMABRGI2
+ *     8      | HAC1/SSI1 | rec | all done     | DMABRGI1
+ *     9      | HAC1/SSI1 | rec | half done    | DMABRGI2
+ *
+ * all can be enabled/disabled in the DMABRGCR register,
+ * as well as checked if they occured.
+ *
+ * DMABRGI0 services  USB  DMA  Address  errors,  but it still must be
+ * enabled/acked in the DMABRGCR register.  USB-DMA complete indicator
+ * is grouped together with the audio buffer end indicators, too bad...
+ *
+ * DMABRGCR:   Bits 31-24: audio-dma ENABLE flags,
+ *             Bits 23-16: audio-dma STATUS flags,
+ *             Bits  9-8:  USB error/xfer ENABLE,
+ *             Bits  1-0:  USB error/xfer STATUS.
+ *     Ack an IRQ by writing 0 to the STATUS flag.
+ *     Mask IRQ by writing 0 to ENABLE flag.
+ *
+ * Usage is almost like with any other IRQ:
+ *  dmabrg_request_irq(BRGIRQID, handler, data)
+ *  dmabrg_free_irq(BRGIRQID)
+ *
+ * handler prototype:  void brgirqhandler(void *data)
+ */
+
+#define DMARSRA                0xfe090000
+#define DMAOR          0xffa00040
+#define DMACHCR0       0xffa0000c
+#define DMABRGCR       0xfe3c0000
+
+#define DMAOR_BRG      0x0000c000
+#define DMAOR_DMEN     0x00000001
+
+#define DMABRGI0       68
+#define DMABRGI1       69
+#define DMABRGI2       70
+
+struct dmabrg_handler {
+       void (*handler)(void *);
+       void *data;
+} *dmabrg_handlers;
+
+static inline void dmabrg_call_handler(int i)
+{
+       dmabrg_handlers[i].handler(dmabrg_handlers[i].data);
+}
+
+/*
+ * main DMABRG irq handler. It acks irqs and then
+ * handles every set and unmasked bit sequentially.
+ * No locking and no validity checks; it should be
+ * as fast as possible (audio!)
+ */
+static irqreturn_t dmabrg_irq(int irq, void *data)
+{
+       unsigned long dcr;
+       unsigned int i;
+
+       dcr = ctrl_inl(DMABRGCR);
+       ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */
+       dcr &= dcr >> 8;        /* ignore masked */
+
+       /* USB stuff, get it out of the way first */
+       if (dcr & 1)
+               dmabrg_call_handler(DMABRGIRQ_USBDMA);
+       if (dcr & 2)
+               dmabrg_call_handler(DMABRGIRQ_USBDMAERR);
+
+       /* Audio */
+       dcr >>= 16;
+       while (dcr) {
+               i = __ffs(dcr);
+               dcr &= dcr - 1;
+               dmabrg_call_handler(i + DMABRGIRQ_A0TXF);
+       }
+       return IRQ_HANDLED;
+}
+
+static void dmabrg_disable_irq(unsigned int dmairq)
+{
+       unsigned long dcr;
+       dcr = ctrl_inl(DMABRGCR);
+       dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+       ctrl_outl(dcr, DMABRGCR);
+}
+
+static void dmabrg_enable_irq(unsigned int dmairq)
+{
+       unsigned long dcr;
+       dcr = ctrl_inl(DMABRGCR);
+       dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+       ctrl_outl(dcr, DMABRGCR);
+}
+
+int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*),
+                      void *data)
+{
+       if ((dmairq > 9) || !handler)
+               return -ENOENT;
+       if (dmabrg_handlers[dmairq].handler)
+               return -EBUSY;
+
+       dmabrg_handlers[dmairq].handler = handler;
+       dmabrg_handlers[dmairq].data = data;
+       
+       dmabrg_enable_irq(dmairq);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dmabrg_request_irq);
+
+void dmabrg_free_irq(unsigned int dmairq)
+{
+       if (likely(dmairq < 10)) {
+               dmabrg_disable_irq(dmairq);
+               dmabrg_handlers[dmairq].handler = NULL;
+               dmabrg_handlers[dmairq].data = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(dmabrg_free_irq);
+
+static int __init dmabrg_init(void)
+{
+       unsigned long or;
+       int ret;
+
+       dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler),
+                                 GFP_KERNEL);
+       if (!dmabrg_handlers)
+               return -ENOMEM;
+
+#ifdef CONFIG_SH_DMA
+       /* request DMAC channel 0 before anyone else can get it */
+       ret = request_dma(0, "DMAC 0 (DMABRG)");
+       if (ret < 0)
+               printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n");
+#endif
+
+       ctrl_outl(0, DMABRGCR);
+       ctrl_outl(0, DMACHCR0);
+       ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */
+
+       /* enable DMABRG mode, enable the DMAC */
+       or = ctrl_inl(DMAOR);
+       ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
+
+       ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG USB address error", NULL);
+       if (ret)
+               goto out0;
+
+       ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG Transfer End", NULL);
+       if (ret)
+               goto out1;
+
+       ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG Transfer Half", NULL);
+       if (ret == 0)
+               return ret;
+
+       free_irq(DMABRGI1, 0);
+out1:  free_irq(DMABRGI0, 0);
+out0:  kfree(dmabrg_handlers);
+       return ret;
+}
+subsys_initcall(dmabrg_init);
index efecb3d5995c24e8dd7221420b0205da06ab3d4a..d67656a44b15eeea661c4bbcf2429dcebb4a4c42 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
index 350972ae9410df1e11b37658e6ce993817b6cc33..965fa2572b2368230bffb56ee00be7d8714eebdf 100644 (file)
@@ -2,9 +2,8 @@
 # Makefile for the Linux/SuperH SH-2A backends.
 #
 
-obj-y  := common.o probe.o
+obj-y  := common.o probe.o opcode_helper.o
 
-common-y       += $(addprefix ../sh2/, ex.o)
-common-y       += $(addprefix ../sh2/, entry.o)
+common-y       += $(addprefix ../sh2/, ex.o entry.o)
 
 obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
new file mode 100644 (file)
index 0000000..9704b79
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/opcode_helper.c
+ *
+ * Helper for the SH-2A 32-bit opcodes.
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <asm/system.h>
+
+/*
+ * Instructions on SH are generally fixed at 16-bits, however, SH-2A
+ * introduces some 32-bit instructions. Since there are no real
+ * constraints on their use (and they can be mixed and matched), we need
+ * to check the instruction encoding to work out if it's a true 32-bit
+ * instruction or not.
+ *
+ * Presently, 32-bit opcodes have only slight variations in what the
+ * actual encoding looks like in the first-half of the instruction, which
+ * makes it fairly straightforward to differentiate from the 16-bit ones.
+ *
+ * First 16-bits of encoding           Used by
+ *
+ *     0011nnnnmmmm0001        mov.b, mov.w, mov.l, fmov.d,
+ *                             fmov.s, movu.b, movu.w
+ *
+ *     0011nnnn0iii1001        bclr.b, bld.b, bset.b, bst.b, band.b,
+ *                             bandnot.b, bldnot.b, bor.b, bornot.b,
+ *                             bxor.b
+ *
+ *     0000nnnniiii0000        movi20
+ *     0000nnnniiii0001        movi20s
+ */
+unsigned int instruction_size(unsigned int insn)
+{
+       /* Look for the common cases */
+       switch ((insn & 0xf00f)) {
+       case 0x0000:    /* movi20 */
+       case 0x0001:    /* movi20s */
+       case 0x3001:    /* 32-bit mov/fmov/movu variants */
+               return 4;
+       }
+
+       /* And the special cases.. */
+       switch ((insn & 0xf08f)) {
+       case 0x3009:    /* 32-bit b*.b bit operations */
+               return 4;
+       }
+
+       return 2;
+}
index 426f6db01fc69d117621398e5be60f29a09f261a..f455c3509789b8ba5b4943e758b31b27d9626695 100644 (file)
@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void)
 {
        /* Just SH7206 for now .. */
        current_cpu_data.type                   = CPU_SH7206;
+       current_cpu_data.flags                  |= CPU_HAS_OP32;
 
        current_cpu_data.dcache.ways            = 4;
        current_cpu_data.dcache.way_incr        = (1 << 11);
index f3e827f29a46b298eb6a31561fe80dfe09340460..832c0b4a1e6ca2fe78583e57af93ebd44f78d7bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/entry.S
+ * arch/sh/kernel/cpu/sh3/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2006  Paul Mundt
index ba3082d640b5f1d06191a7cc9671ee62a4bb111e..2b2a9e02fb752d1e358f41787369cb8731412501 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  arch/sh/kernel/cpu/sh3/ex.S
  *
- *  The SH-3 exception vector table.
+ *  The SH-3 and SH-4 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2006  Paul Mundt
@@ -9,7 +9,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
 #include <linux/linkage.h>
 
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table)
        .long   exception_error ! address error load
        .long   exception_error ! address error store   /* 100 */
 #endif
-       .long   exception_error ! fpu_exception /* 120 */
-       .long   exception_error                 /* 140 */
+#if defined(CONFIG_SH_FPU)
+       .long   do_fpu_error            /* 120 */
+#else
+       .long   exception_error         /* 120 */
+#endif
+       .long   exception_error         /* 140 */
        .long   system_call     ! Unconditional Trap     /* 160 */
        .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
        .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap)
         * away offsets can be manually inserted in to their appropriate
         * location via set_exception_table_{evt,vec}().
         */
-       .balign 4096,0,4096
+       .balign 4096,0,4096
index 19ca68c71884176ed9f7f2230ab4618660842a47..8add10bd82683d5efd5064faee11b0746e146c61 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the Linux/SuperH SH-4 backends.
 #
 
-obj-y  := ex.o probe.o common.o
-common-y       += $(addprefix ../sh3/, entry.o)
+obj-y  := probe.o common.o
+common-y       += $(addprefix ../sh3/, entry.o ex.o)
 
-obj-$(CONFIG_SH_FPU)                    += fpu.o
+obj-$(CONFIG_SH_FPU)                   += fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)          += sq.o
 
 # CPU subtype setup
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
deleted file mode 100644 (file)
index ac8ab57..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  arch/sh/kernel/cpu/sh4/ex.S
- *
- *  The SH-4 exception vector table.
-
- *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003 - 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/linkage.h>
-
-       .align 2
-       .data
-
-ENTRY(exception_handling_table)
-       .long   exception_error         /* 000 */
-       .long   exception_error
-#if defined(CONFIG_MMU)
-       .long   tlb_miss_load           /* 040 */
-       .long   tlb_miss_store
-       .long   initial_page_write
-       .long   tlb_protection_violation_load
-       .long   tlb_protection_violation_store
-       .long   address_error_load
-       .long   address_error_store     /* 100 */
-#else
-       .long   exception_error ! tlb miss load         /* 040 */
-       .long   exception_error ! tlb miss store
-       .long   exception_error ! initial page write
-       .long   exception_error ! tlb prot violation load
-       .long   exception_error ! tlb prot violation store
-       .long   exception_error ! address error load
-       .long   exception_error ! address error store   /* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
-       .long   do_fpu_error            /* 120 */
-#else
-       .long   exception_error         /* 120 */
-#endif
-       .long   exception_error         /* 140 */
-       .long   system_call     ! Unconditional Trap     /* 160 */
-       .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
-       .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
-       .long   debug_enter     /* 1C0 */       ! Allow trap to debugger
-#else
-       .long   exception_none  /* 1C0 */       ! Not implemented yet
-#endif
-ENTRY(user_break_point_trap)
-       .long   break_point_trap        /* 1E0 */
-
-       /*
-        * Pad the remainder of the table out, exceptions residing in far
-        * away offsets can be manually inserted in to their appropriate
-        * location via set_exception_table_{evt,vec}().
-        */
-       .balign 4096,0,4096
index 7624677f66281e7ef31b99d9b48caf1bc7534b5d..d61dd599169f97b0acb1f42fc9b19acc2dd26835 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/processor.h>
+#include <asm/system.h>
 #include <asm/io.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs)
                nextpc = regs->pr;
                finsn = *(unsigned short *) (regs->pc + 2);
        } else {
-               nextpc = regs->pc + 2;
+               nextpc = regs->pc + instruction_size(insn);
                finsn = insn;
        }
 
index 2fa5cb2ae68d58cfe98ef3b4dd77500e69c2e8a8..6d5ba373a75e461db8ded6d7d669c5104043aac9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4/clock-sh73180.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh73180.c
  *
  * SH73180 support for the clock framework
  *
index 1707a213f0cf7b00b6276f112aa837032b5951b6..7adc4f16e95ae4f3fd66a8ea384e6244ad16c095 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
  *
  * SH7343/SH7722 support for the clock framework
  *
index c8694bac64775ebbc9ef45c9d6a46483ecbe1d0d..8e236062c721860fb5f39768c09f4eb2859bb6cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4/clock-sh7770.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7770.c
  *
  * SH7770 support for the clock framework
  *
index 9e6a216750c800529788b340aa12fdb7f5956f17..01f3da619d3d95f259b19153e556fe1ea721718f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4/clock-sh7780.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7780.c
  *
  * SH7780 support for the clock framework
  *
index 9048c0326d879452cee49cfbccec42d4812aae26..9833493d8867a097549182ba55aec047df4ee526 100644 (file)
@@ -192,20 +192,14 @@ int __init setup_early_printk(char *buf)
        }
 #endif
 
-       if (likely(early_console))
+       if (likely(early_console)) {
+               if (keep_early)
+                       early_console->flags &= ~CON_BOOT;
+               else
+                       early_console->flags |= CON_BOOT;
                register_console(early_console);
+       }
 
        return 0;
 }
 early_param("earlyprintk", setup_early_printk);
-
-void __init disable_early_printk(void)
-{
-       if (!early_console_initialized || !early_console)
-               return;
-       if (!keep_early) {
-               printk("disabling early console\n");
-               unregister_console(early_console);
-       } else
-               printk("keeping early console\n");
-}
index 329b3f3051de9d53bb5b58b7418e595d11d74e09..6b4f5748d0be682a2b6334ca7d6f5ccc406be271 100644 (file)
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
 #include <asm/ubc.h>
 
 static int hlt_counter;
@@ -58,12 +61,15 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
 
+               tick_nohz_stop_sched_tick();
                while (!need_resched())
                        idle();
+               tick_nohz_restart_sched_tick();
 
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
+               check_pgt_cache();
        }
 }
 
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+       if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+       if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
index 855f7246cfffb4a4d597a11bd5ffc654a32e348a..3fb5fc0b550da970cb5cb8e0a1f5e524a4b2b734 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 477d2a854fc4e4a59d0f83cec2341b8648b10fd1..c27729135935d77a8a4387fdb562e3bb86158357 100644 (file)
@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
        "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-       "ptea", "llsc", "l2", NULL
+       "ptea", "llsc", "l2", "op32", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
index 17f0b50c5678193d24f94b0470ea6e57bc450d5b..c1cfcb9f047c1803f3e5564079bdba127f6509e4 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/sched.h>
 #include <linux/in6.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
@@ -59,8 +58,6 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL(__div64_32);
-
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */
index 9f39ef1f73dae8402c115dd92e854fce972ff2f5..b32c35a7c0a3e42512765962e8b71c0c1096a5c8 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
@@ -24,7 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
-
+#include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -501,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                                }
                        /* fallthrough */
                        case -ERESTARTNOINTR:
-                               regs->pc -= 2;
+                               regs->pc -= instruction_size(
+                                               ctrl_inw(regs->pc - 4));
+                               break;
                }
        } else {
                /* gUSA handling */
@@ -517,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                        regs->regs[15] = regs->regs[1];
                        if (regs->pc < regs->regs[0])
                                /* Go to rewind point #1 */
-                               regs->pc = regs->regs[0] + offset - 2;
+                               regs->pc = regs->regs[0] + offset -
+                                       instruction_size(ctrl_inw(regs->pc-4));
                }
 #ifdef CONFIG_PREEMPT
                local_irq_restore(flags);
@@ -601,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
                    regs->regs[0] == -ERESTARTSYS ||
                    regs->regs[0] == -ERESTARTNOINTR) {
                        regs->regs[0] = save_r0;
-                       regs->pc -= 2;
+                       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
                } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
-                       regs->pc -= 2;
+                       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
                        regs->regs[3] = __NR_restart_syscall;
                }
        }
index 0d5268afe80f35fff78b48cd2c559225c4fedb4a..d41e561be20eafacbacf9c99fd08a84d1f1e2321 100644 (file)
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
-       unsigned long *sp;
-
-       if (!task)
-               task = current;
-       if (task == current)
-               sp = (unsigned long *)current_stack_pointer;
-       else
-               sp = (unsigned long *)task->thread.sp;
+       unsigned long *sp = (unsigned long *)current_stack_pointer;
 
        while (!kstack_end(sp)) {
                unsigned long addr = *sp++;
index e18f183e1035b70864dac90245c60727d9e8d13c..76b1bc7f70297adc324ad84c8aedfbdb2004acca 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 38fc8cd3ea3a12fbe35dc6a014d12b651eab6795..4357d1a6358f61ba39a2ab7094fdfd968daec8aa 100644 (file)
@@ -354,3 +354,4 @@ ENTRY(sys_call_table)
        .long sys_move_pages
        .long sys_getcpu
        .long sys_epoll_pwait
+       .long sys_utimensat             /* 320 */
index d47e775962e955054f8e0296f4f3a5fdd65377e5..a3a67d151e520285b08c7fd58cc93d618e079fe6 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002 - 2006  Paul Mundt
+ *  Copyright (C) 2002 - 2007  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
@@ -15,6 +15,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/clockchips.h>
 #include <asm/clock.h>
 #include <asm/rtc.h>
 #include <asm/timer.h>
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs)
        return 0;
 }
 
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static cycle_t null_hpt_read(void)
+{
+       return 0;
+}
+
 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv)
 EXPORT_SYMBOL(do_settimeofday);
 #endif /* !CONFIG_GENERIC_TIME */
 
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
@@ -138,6 +148,7 @@ void handle_timer_tick(void)
                        last_rtc_update = xtime.tv_sec - 600;
        }
 }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_PM
 int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = {
        .resume  = timer_resume,
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-static int timer_dyn_tick_enable(void)
+static int __init timer_init_sysfs(void)
 {
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long flags;
-       int ret = -ENODEV;
-
-       if (dyn_tick) {
-               spin_lock_irqsave(&dyn_tick->lock, flags);
-               ret = 0;
-               if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
-                       ret = dyn_tick->enable();
-
-                       if (ret == 0)
-                               dyn_tick->state |= DYN_TICK_ENABLED;
-               }
-               spin_unlock_irqrestore(&dyn_tick->lock, flags);
-       }
+       int ret = sysdev_class_register(&timer_sysclass);
+       if (ret != 0)
+               return ret;
 
-       return ret;
+       sys_timer->dev.cls = &timer_sysclass;
+       return sysdev_register(&sys_timer->dev);
 }
+device_initcall(timer_init_sysfs);
 
-static int timer_dyn_tick_disable(void)
-{
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long flags;
-       int ret = -ENODEV;
-
-       if (dyn_tick) {
-               spin_lock_irqsave(&dyn_tick->lock, flags);
-               ret = 0;
-               if (dyn_tick->state & DYN_TICK_ENABLED) {
-                       ret = dyn_tick->disable();
-
-                       if (ret == 0)
-                               dyn_tick->state &= ~DYN_TICK_ENABLED;
-               }
-               spin_unlock_irqrestore(&dyn_tick->lock, flags);
-       }
-
-       return ret;
-}
+void (*board_time_init)(void);
 
 /*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
+ * Shamelessly based on the MIPS and Sparc64 work.
  */
-void timer_dyn_reprogram(void)
-{
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long next, seq, flags;
-
-       if (!dyn_tick)
-               return;
-
-       spin_lock_irqsave(&dyn_tick->lock, flags);
-       if (dyn_tick->state & DYN_TICK_ENABLED) {
-               next = next_timer_interrupt();
-               do {
-                       seq = read_seqbegin(&xtime_lock);
-                       dyn_tick->reprogram(next - jiffies);
-               } while (read_seqretry(&xtime_lock, seq));
-       }
-       spin_unlock_irqrestore(&dyn_tick->lock, flags);
-}
+static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
+unsigned long sh_hpt_frequency = 0;
+
+#define NSEC_PER_CYC_SHIFT     10
+
+struct clocksource clocksource_sh = {
+       .name           = "SuperH",
+       .rating         = 200,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .read           = null_hpt_read,
+       .shift          = 16,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
 
-static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+static void __init init_sh_clocksource(void)
 {
-       return sprintf(buf, "%i\n",
-                      (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
-}
+       if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
+               return;
 
-static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
-                                 size_t count)
-{
-       unsigned int enable = simple_strtoul(buf, NULL, 2);
+       clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
+                                                 clocksource_sh.shift);
 
-       if (enable)
-               timer_dyn_tick_enable();
-       else
-               timer_dyn_tick_disable();
+       timer_ticks_per_nsec_quotient =
+               clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
 
-       return count;
+       clocksource_register(&clocksource_sh);
 }
-static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
 
-/*
- * dyntick=enable|disable
- */
-static char dyntick_str[4] __initdata = "";
-
-static int __init dyntick_setup(char *str)
+#ifdef CONFIG_GENERIC_TIME
+unsigned long long sched_clock(void)
 {
-       if (str)
-               strlcpy(dyntick_str, str, sizeof(dyntick_str));
-       return 1;
+       unsigned long long ticks = clocksource_sh.read();
+       return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
 }
-
-__setup("dyntick=", dyntick_setup);
-#endif
-
-static int __init timer_init_sysfs(void)
-{
-       int ret = sysdev_class_register(&timer_sysclass);
-       if (ret != 0)
-               return ret;
-
-       sys_timer->dev.cls = &timer_sysclass;
-       ret = sysdev_register(&sys_timer->dev);
-
-#ifdef CONFIG_NO_IDLE_HZ
-       if (ret == 0 && sys_timer->dyn_tick) {
-               ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
-
-               /*
-                * Turn on dynamic tick after calibrate delay
-                * for correct bogomips
-                */
-               if (ret == 0 && dyntick_str[0] == 'e')
-                       ret = timer_dyn_tick_enable();
-       }
 #endif
 
-       return ret;
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
 void __init time_init(void)
 {
        if (board_time_init)
@@ -316,10 +249,15 @@ void __init time_init(void)
        sys_timer = get_sys_timer();
        printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
 
-#ifdef CONFIG_NO_IDLE_HZ
-       if (sys_timer->dyn_tick)
-               spin_lock_init(&sys_timer->dyn_tick->lock);
-#endif
+       if (sys_timer->ops->read)
+               clocksource_sh.read = sys_timer->ops->read;
+
+       init_sh_clocksource();
+
+       if (sh_hpt_frequency)
+               printk("Using %lu.%03lu MHz high precision timer.\n",
+                      ((sh_hpt_frequency + 500) / 1000) / 1000,
+                      ((sh_hpt_frequency + 500) / 1000) % 1000);
 
 #if defined(CONFIG_SH_KGDB)
        /*
index a574b93a4e7b8fac6473c01f4ef0a3cadfba0e02..82de6895ade5e9f6fcb3961c09a205942f0dd1b5 100644 (file)
@@ -115,7 +115,7 @@ static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
 static struct irqaction cmt_irq = {
        .name           = "timer",
        .handler        = cmt_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .mask           = CPU_MASK_NONE,
 };
 
index fffcd1c098733b8a2a0bfd36fa6d16f2087a1217..b7499a2a9188b97f7b9d949961f35e7afd0c9d5e 100644 (file)
@@ -110,7 +110,7 @@ static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
 static struct irqaction mtu2_irq = {
        .name           = "timer",
        .handler        = mtu2_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .mask           = CPU_MASK_NONE,
 };
 
index ad1ede52fc9cf1c66f63982b18a9fdd192f06837..2d997e2a5b6cc6a0961810c8b02beb49df44efac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005 - 2007  Paul Mundt
  *
  * TMU handling code hacked out of arch/sh/kernel/time.c
  *
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/seqlock.h>
+#include <linux/clockchips.h>
 #include <asm/timer.h>
 #include <asm/rtc.h>
 #include <asm/io.h>
 #include <asm/clock.h>
 
 #define TMU_TOCR_INIT  0x00
-#define TMU0_TCR_INIT  0x0020
-#define TMU_TSTR_INIT  1
+#define TMU_TCR_INIT   0x0020
 
-#define TMU0_TCR_CALIB 0x0000
+static int tmu_timer_start(void)
+{
+       ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+       return 0;
+}
 
-static unsigned long tmu_timer_get_offset(void)
+static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
 {
-       int count;
-       static int count_p = 0x7fffffff;    /* for the first call after boot */
-       static unsigned long jiffies_p = 0;
+       ctrl_outl(interval, TMU0_TCNT);
 
        /*
-        * cache volatile jiffies temporarily; we have IRQs turned off.
+        * TCNT reloads from TCOR on underflow, clear it if we don't
+        * intend to auto-reload
         */
-       unsigned long jiffies_t;
+       if (reload)
+               ctrl_outl(interval, TMU0_TCOR);
+       else
+               ctrl_outl(0, TMU0_TCOR);
 
-       /* timer count may underflow right here */
-       count = ctrl_inl(TMU0_TCNT);    /* read the latched count */
+       tmu_timer_start();
+}
 
-       jiffies_t = jiffies;
+static int tmu_timer_stop(void)
+{
+       ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+       return 0;
+}
 
-       /*
-        * avoiding timer inconsistencies (they are rare, but they happen)...
-        * there is one kind of problem that must be avoided here:
-        *  1. the timer counter underflows
-        */
+static cycle_t tmu_timer_read(void)
+{
+       return ~ctrl_inl(TMU1_TCNT);
+}
+
+static int tmu_set_next_event(unsigned long cycles,
+                             struct clock_event_device *evt)
+{
+       tmu0_timer_set_interval(cycles, 1);
+       return 0;
+}
 
-       if (jiffies_t == jiffies_p) {
-               if (count > count_p) {
-                       /* the nutcase */
-                       if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
-                               count -= LATCH;
-                       } else {
-                               printk("%s (): hardware timer problem?\n",
-                                      __FUNCTION__);
-                       }
-               }
-       } else
-               jiffies_p = jiffies_t;
-
-       count_p = count;
-
-       count = ((LATCH-1) - count) * TICK_SIZE;
-       count = (count + LATCH/2) / LATCH;
-
-       return count;
+static void tmu_set_mode(enum clock_event_mode mode,
+                        struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               ctrl_outl(0, TMU0_TCOR);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               break;
+       }
 }
 
+static struct clock_event_device tmu0_clockevent = {
+       .name           = "tmu0",
+       .shift          = 32,
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = tmu_set_mode,
+       .set_next_event = tmu_set_next_event,
+};
+
 static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
+       struct clock_event_device *evt = &tmu0_clockevent;
        unsigned long timer_status;
 
        /* Clear UNF bit */
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
        timer_status &= ~0x100;
        ctrl_outw(timer_status, TMU0_TCR);
 
-       /*
-        * Here we are in the timer irq handler. We just have irqs locally
-        * disabled but we don't know if the timer_bh is running on the other
-        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-        * the irq version of write_lock because as just said we have irq
-        * locally disabled. -arca
-        */
-       write_seqlock(&xtime_lock);
-       handle_timer_tick();
-       write_sequnlock(&xtime_lock);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
-static struct irqaction tmu_irq = {
-       .name           = "timer",
+static struct irqaction tmu0_irq = {
+       .name           = "periodic timer",
        .handler        = tmu_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .mask           = CPU_MASK_NONE,
 };
 
-static void tmu_clk_init(struct clk *clk)
+static void tmu0_clk_init(struct clk *clk)
 {
-       u8 divisor = TMU0_TCR_INIT & 0x7;
-       ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+       u8 divisor = TMU_TCR_INIT & 0x7;
+       ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
        clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static void tmu_clk_recalc(struct clk *clk)
+static void tmu0_clk_recalc(struct clk *clk)
 {
        u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
        clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static struct clk_ops tmu_clk_ops = {
-       .init           = tmu_clk_init,
-       .recalc         = tmu_clk_recalc,
+static struct clk_ops tmu0_clk_ops = {
+       .init           = tmu0_clk_init,
+       .recalc         = tmu0_clk_recalc,
 };
 
 static struct clk tmu0_clk = {
        .name           = "tmu0_clk",
-       .ops            = &tmu_clk_ops,
+       .ops            = &tmu0_clk_ops,
 };
 
-static int tmu_timer_start(void)
+static void tmu1_clk_init(struct clk *clk)
 {
-       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-       return 0;
+       u8 divisor = TMU_TCR_INIT & 0x7;
+       ctrl_outw(divisor, TMU1_TCR);
+       clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static int tmu_timer_stop(void)
+static void tmu1_clk_recalc(struct clk *clk)
 {
-       ctrl_outb(0, TMU_TSTR);
-       return 0;
+       u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
+       clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
+static struct clk_ops tmu1_clk_ops = {
+       .init           = tmu1_clk_init,
+       .recalc         = tmu1_clk_recalc,
+};
+
+static struct clk tmu1_clk = {
+       .name           = "tmu1_clk",
+       .ops            = &tmu1_clk_ops,
+};
+
 static int tmu_timer_init(void)
 {
        unsigned long interval;
+       unsigned long frequency;
 
-       setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
+       setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
 
        tmu0_clk.parent = clk_get(NULL, "module_clk");
+       tmu1_clk.parent = clk_get(NULL, "module_clk");
 
-       /* Start TMU0 */
        tmu_timer_stop();
+
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7785)
@@ -155,15 +179,29 @@ static int tmu_timer_init(void)
 #endif
 
        clk_register(&tmu0_clk);
+       clk_register(&tmu1_clk);
        clk_enable(&tmu0_clk);
+       clk_enable(&tmu1_clk);
 
-       interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
-       printk(KERN_INFO "Interval = %ld\n", interval);
+       frequency = clk_get_rate(&tmu0_clk);
+       interval = (frequency + HZ / 2) / HZ;
 
-       ctrl_outl(interval, TMU0_TCOR);
-       ctrl_outl(interval, TMU0_TCNT);
+       sh_hpt_frequency = clk_get_rate(&tmu1_clk);
+       ctrl_outl(~0, TMU1_TCNT);
+       ctrl_outl(~0, TMU1_TCOR);
 
-       tmu_timer_start();
+       tmu0_timer_set_interval(interval, 1);
+
+       tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
+                                     tmu0_clockevent.shift);
+       tmu0_clockevent.max_delta_ns =
+                       clockevent_delta2ns(-1, &tmu0_clockevent);
+       tmu0_clockevent.min_delta_ns =
+                       clockevent_delta2ns(1, &tmu0_clockevent);
+
+       tmu0_clockevent.cpumask = cpumask_of_cpu(0);
+
+       clockevents_register_device(&tmu0_clockevent);
 
        return 0;
 }
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = {
        .init           = tmu_timer_init,
        .start          = tmu_timer_start,
        .stop           = tmu_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
-       .get_offset     = tmu_timer_get_offset,
-#endif
+       .read           = tmu_timer_read,
 };
 
 struct sys_timer tmu_timer = {
index 7b40f0ff3dfc8701a8121dfddaaf3f9044db97c0..3a197649cd83c6c57227156fbcdd6d06e86ef7a2 100644 (file)
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
 #include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/kdebug.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
        }
 }
 
-ATOMIC_NOTIFIER_HEAD(shdie_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -505,7 +491,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
  simple:
        ret = handle_unaligned_ins(instruction,regs);
        if (ret==0)
-               regs->pc += 2;
+               regs->pc += instruction_size(instruction);
        return ret;
 }
 #endif /* CONFIG_CPU_SH2A */
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 
        err = do_fpu_inst(inst, regs);
        if (!err) {
-               regs->pc += 2;
+               regs->pc += instruction_size(inst);
                return;
        }
        /* not a FPU inst. */
index 7b0f66f033197b83d186231f6a16b5a12580130c..e146bafcd14fb11459e60f1db77549502b22644e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/vsyscall.c
+ * arch/sh/kernel/vsyscall/vsyscall.c
  *
  *  Copyright (C) 2006 Paul Mundt
  *
index 351714694d6d4b9b6f81d183e774f1fc47e0e215..f3ddd2133e6f4edffb5a7fc7958350d9d1c2f680 100644 (file)
@@ -24,9 +24,10 @@ inline void __const_udelay(unsigned long xloops)
        __asm__("dmulu.l        %0, %2\n\t"
                "sts    mach, %0"
                : "=r" (xloops)
-               : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
+               : "0" (xloops),
+                 "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy)
                : "macl", "mach");
-       __delay(xloops * HZ);
+       __delay(xloops);
 }
 
 void __udelay(unsigned long usecs)
index 12f3d394dc28e97df806d7884cb92b890f681e92..253346d7b316fc1bd3a934f6e37c8b038c18a303 100644 (file)
@@ -218,6 +218,9 @@ endmenu
 
 menu "Memory management options"
 
+config QUICKLIST
+       def_bool y
+
 config MMU
         bool "Support for memory management hardware"
        depends on !CPU_SH2
@@ -300,6 +303,10 @@ config NODES_SHIFT
 config ARCH_FLATMEM_ENABLE
        def_bool y
 
+config MAX_ACTIVE_REGIONS
+       int
+       default "1"
+
 config ARCH_POPULATES_NODE_MAP
        def_bool y
 
index 34d4e0c68fbb10e713699214214e47029584e9fb..923cb456819b0ceb79f3c66139602a45ae4f8232 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
index 0ecc117cade4525042e98b8240e1a0ebcda9b882..9207da67ff8a669841170bc73b600f9782d3037d 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
index cf2c2ee35a376dab1ef632f27fd1be51bf5e38cd..ae8c321d6e2a960e0e7fe1bd55ab5224e7a586cc 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 
index 4d030988b3681b3102e859d1f4464afbd23cdef8..8fe223a890ed4aaedf8947493f947041e4bed535 100644 (file)
@@ -67,6 +67,8 @@ void show_mem(void)
        printk("%d slab pages\n", slab);
        printk("%d pages shared\n", shared);
        printk("%d pages swap cached\n", cached);
+       printk(KERN_INFO "Total of %ld pages in page table cache\n",
+              quicklist_total_size());
 }
 
 #ifdef CONFIG_MMU
index d0d45e2e0ab319f62e94d0439798d0ac1c6e941f..02aae06527dc496620e2d4cc338d171b13e96e6a 100644 (file)
@@ -311,9 +311,9 @@ static int __init pmb_init(void)
 
        BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES));
 
-       pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry),
-                                     0, 0, pmb_cache_ctor, pmb_cache_dtor);
-       BUG_ON(!pmb_cache);
+       pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0,
+                                     SLAB_PANIC, pmb_cache_ctor,
+                                     pmb_cache_dtor);
 
        jump_to_P2();
 
index 8c8a76e180aabca423167cf247056590ded9fdce..4f91311236725cf0913d85262b53c388818e9221 100644 (file)
@@ -79,7 +79,7 @@ static struct console sh_console = {
        .name           = "scifcon",
        .write          = sh_console_write,
        .setup          = sh_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER | CON_BOOT,
        .index          = -1,
 };
 
@@ -97,9 +97,3 @@ void __init enable_early_printk(void)
 
        register_console(&sh_console);
 }
-
-void disable_early_printk(void)
-{
-       unregister_console(&sh_console);
-}
-
index e7e07f8749c9907567ff8a83053b45f2577eea61..f68b4f6c9b31a4dd8a6b07a65096476517c2c83f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/bitops.h>
index 9dae689b6a9b0da641a9283c3a7ad749dc9a28d3..49862e165c06eac7504a5b6a0f3f6895e57b35be 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/rwsem.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/errno.h>
index 7aa4b4f7bc5e05f8807d8b0bd8a35d53da98506e..461ea3de316fa7523bc9fadcacf31d53cdb095eb 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/sched.h>
 #include <linux/in6.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/screen_info.h>
 
 #include <asm/semaphore.h>
index 1666d3efb52e2fccbb56cca8808d40ab17512097..b76bdfa473d6840a0818b0c9429df0096e3c5cce 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index ad0fa4e003e79c082cfed7c0b5bf00d6a4726a36..19126daf9f4c86f7f5521c82fecc935eb4d9dbd0 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index c346d7ef9280f3452ec54b4edacba5698e58ce96..9d0d58fb29fae75f8bb45f73e5a2a22c044052ea 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
index f934f97f9f9c9f9cf0ac21010f77c7c0c67ae106..1214c78e35844799c4b5fd07ae2ef5c9032e5887 100644 (file)
@@ -46,15 +46,15 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
                      struct pt_regs *regs)
 {
        const char *sym;
-       char *modname, namebuf[128];
-       unsigned long offset, size;
+       char namebuf[128];
+       unsigned long offset;
        unsigned long prologue = 0;
        unsigned long fp_displacement = 0;
        unsigned long fp_prev = 0;
        unsigned long offset_r14 = 0, offset_r18 = 0;
        int i, found_prologue_end = 0;
 
-       sym = kallsyms_lookup(pc, &size, &offset, &modname, namebuf);
+       sym = kallsyms_lookup(pc, NULL, &offset, NULL, namebuf);
        if (!sym)
                return -EINVAL;
 
index 4f72ab33bb2b0a7cb9caae2b09a135f96c8a6ed9..4dd8ee8f01ce61e63558556cea363e7a250a210a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
index 4b455f61114670282914c7b6bf7354974d63864e..fa66daa2dfa9636895388eb20bb636fc31036b54 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 
index c8615954aaa98b425f9ff8f091ef70055a52cd63..d4c5334186d00217204b51344a5f32899e4a6e52 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
index 29d7cfd1c970b162adf4a13738c444e7048bd305..6773ed76e414bec7b851d94cebddf2fec48ff1e7 100644 (file)
@@ -28,7 +28,7 @@ int foo(void)
        DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid));
        DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid));
        DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid));
-       /* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */
+       /* DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); */
        DEFINE(ASIZ_task_uid,   sizeof(current->uid));
        DEFINE(ASIZ_task_gid,   sizeof(current->gid));
        DEFINE(ASIZ_task_euid,  sizeof(current->euid));
index 9a219e8b5ddb3edb8f6726764b7cff7cf43a8f86..97da13c525639acfec602ac841f03a3ed29566fc 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 #include <asm/page.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/winmacro.h>
 #include <asm/thread_info.h>   /* TI_UWINMASK */
 #include <asm/errno.h>
index 5b4841d067c16ccf906149fd3c73b87ea5d16325..bdbefa8a9742b2716432770c6cde5f6b5b8d3e97 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
index fc874e63a499818e5f32ff6517d1df361b6a1f3a..2940d2c1a77855dee8db638e54353418b0a1a3f0 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
index eccd8e87f529eac499bba338ffdeb86b3d9f9f48..64c0ed98820aa8870f7107e09c09c8df69fddd50 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -40,7 +41,6 @@
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 #include <asm/vaddrs.h>
-#include <asm/kdebug.h>
 #include <asm/mbus.h>
 #include <asm/idprom.h>
 #include <asm/machines.h>
index c9301b9143cab90d2bd577393b539694be09e4e1..9994cac950789a265d8c1db23b010c228adefa98 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/binfmts.h>     /* do_coredum */
 #include <linux/bitops.h>
 
index 6b5f26b0fb75c5e716574a70122a79b675b62708..4d9ad59031bb244f3df459338f9e5b9d6c9a6235 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
index 0e27e226e0e2e1a291f9a79fde94dd9a4511cc7c..116d6a241ca2298cb50e4b0fadd5e6abca1a8008 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
 
index c69de5d4863d69cff95df5cc1a16d21441dc83a0..098c94f1a322bffccbaa4c36e5e06b91208a9998 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
index 4e07bdbbfb5d233324b54fd12ed21eed2fa4e77c..63ed19bfd028f9b85ab5e631a9effd2021bdff61 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
index 32e8274e43574513c501fb8cd42940741f88aae7..e613cc6a10bae1916f353bb6b5c724229fa39455 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/file.h>
 
index 01b07bb440f0744a647075db676661f8bf13efd5..2226a59924840ac571326150f192ccac9e604ffa 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/ptrace.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 
 asmlinkage int
index 3a69778c836627576d9f28d4cd86c9e928fb42ba..e3f5b8ed4c52c2c3a12f857bd3a27ea8bc62a627 100644 (file)
@@ -80,6 +80,7 @@ sys_call_table:
 /*295*/        .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/        .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
 /*305*/        .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+/*310*/        .long sys_utimensat
 
 #ifdef CONFIG_SUNOS_EMUL
        /* Now the SunOS syscall table. */
@@ -196,5 +197,6 @@ sunos_sys_table:
        .long sunos_nosys, sunos_nosys, sunos_nosys
        .long sunos_nosys, sunos_nosys, sunos_nosys
        .long sunos_nosys
+/*310*/        .long sunos_nosys
 
 #endif
index 527687afc1c43adffb47785f33ebcb4703635189..dc9ffea2a4f7025d4e04908fc8123be881ae1f19 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/kdebug.h>
 
 #include <asm/delay.h>
 #include <asm/system.h>
@@ -22,7 +23,6 @@
 #include <asm/oplib.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/kdebug.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
 
index 2e168d16547f93234602de95762346a727b730d8..764b3eb7b604ebd7858d1ed02a4609a31f30537b 100644 (file)
@@ -9,7 +9,6 @@
  * fragmentation.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
 
index 9eeed3347df3297f4790ff8a7f39b73fa4a38f6e..c3483365db4bc678b8f06070910ad6a7a3a96425 100644 (file)
@@ -18,9 +18,9 @@
 #include <linux/signal.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
@@ -30,7 +30,6 @@
 #include <asm/oplib.h>
 #include <asm/smp.h>
 #include <asm/traps.h>
-#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 
 extern int prom_node_root;
index 0df7121cef07b768d8fe0090609f994edcca3ac5..e5eaa8072ae03277df2f0c1961fbb5700ff71135 100644 (file)
 #include <linux/bootmem.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/kdebug.h>
 
 #include <asm/bitext.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/kdebug.h>
 #include <asm/vaddrs.h>
 #include <asm/traps.h>
 #include <asm/smp.h>
index 0ace17bafba4e33c50168894596e87825ba9569b..ad55a9bb50ddedfe6febf63c54e7836b43c18b16 100644 (file)
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
-#include <asm/pbm.h>
 #include <asm/ebus.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
 #include <asm/of_device.h>
 #include <asm/bpp.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 
 /* EBUS dma library. */
 
index ae221f0d4a6f2171ad9e43d83f08ca1cc8d3fa09..c93a15b785fa28322b5c254040ceb510904e7113 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
 #include <linux/module.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/signal.h>
 #include <asm/cacheflush.h>
 #include <asm/uaccess.h>
@@ -313,7 +313,7 @@ out:
        return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -403,15 +403,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
                if (post_kprobe_handler(args->regs))
                        ret = NOTIFY_STOP;
                break;
-       case DIE_GPF:
-       case DIE_PAGE_FAULT:
-               /* kprobe_running() needs smp_processor_id() */
-               preempt_disable();
-               if (kprobe_running() &&
-                   kprobe_fault_handler(args->regs, args->trapnr))
-                       ret = NOTIFY_STOP;
-               preempt_enable();
-               break;
        default:
                break;
        }
index af2c7ff01eeb55ad62dcc92ed77afd5007f7ded7..d85e1ed7c3e438d3425ab96d103c3f427ca4a38a 100644 (file)
 #include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/pci.h>
 #include <linux/msi.h>
 #include <linux/irq.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
-#include <asm/pbm.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
@@ -49,10 +48,10 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 #else
 
 /* List of all PCI controllers found in the system. */
-struct pci_controller_info *pci_controller_root = NULL;
+struct pci_pbm_info *pci_pbm_root = NULL;
 
-/* Each PCI controller found gets a unique index. */
-int pci_num_controllers = 0;
+/* Each PBM found gets a unique index. */
+int pci_num_pbms = 0;
 
 volatile int pci_poke_in_progress;
 volatile int pci_poke_cpu = -1;
@@ -292,7 +291,7 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
 
 /* Find each controller in the system, attach and initialize
  * software state structure for each and link into the
- * pci_controller_root.  Setup the controller enough such
+ * pci_pbm_root.  Setup the controller enough such
  * that bus scanning can be done.
  */
 static void __init pci_controller_probe(void)
@@ -744,7 +743,6 @@ int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
 
 struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
 {
-       struct pci_controller_info *p = pbm->parent;
        struct device_node *node = pbm->prom_node;
        struct pci_dev *host_pdev;
        struct pci_bus *bus;
@@ -752,7 +750,7 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
        printk("PCI: Scanning PBM %s\n", node->full_name);
 
        /* XXX parent device? XXX */
-       bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm);
+       bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm);
        if (!bus) {
                printk(KERN_ERR "Failed to create bus for %s\n",
                       node->full_name);
@@ -777,10 +775,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
 
 static void __init pci_scan_each_controller_bus(void)
 {
-       struct pci_controller_info *p;
+       struct pci_pbm_info *pbm;
 
-       for (p = pci_controller_root; p; p = p->next)
-               p->scan_bus(p);
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next)
+               pbm->scan_bus(pbm);
 }
 
 extern void power_init(void);
@@ -788,7 +786,7 @@ extern void power_init(void);
 static int __init pcibios_init(void)
 {
        pci_controller_probe();
-       if (pci_controller_root == NULL)
+       if (pci_pbm_root == NULL)
                return 0;
 
        pci_scan_each_controller_bus();
@@ -923,10 +921,8 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
                                      enum pci_mmap_state mmap_state)
 {
        struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
-       struct pci_controller_info *p;
        unsigned long space_size, user_offset, user_size;
 
-       p = pbm->parent;
        if (mmap_state == pci_mmap_io) {
                space_size = (pbm->io_space.end -
                              pbm->io_space.start) + 1;
@@ -1079,11 +1075,7 @@ int pci_domain_nr(struct pci_bus *pbus)
        if (pbm == NULL || pbm->parent == NULL) {
                ret = -ENXIO;
        } else {
-               struct pci_controller_info *p = pbm->parent;
-
-               ret = p->index;
-               ret = ((ret << 1) +
-                      ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
+               ret = pbm->index;
        }
 
        return ret;
@@ -1094,17 +1086,12 @@ EXPORT_SYMBOL(pci_domain_nr);
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
        struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
-       struct pci_controller_info *p = pbm->parent;
-       int virt_irq, err;
+       int virt_irq;
 
-       if (!pbm->msi_num || !p->setup_msi_irq)
+       if (!pbm->setup_msi_irq)
                return -EINVAL;
 
-       err = p->setup_msi_irq(&virt_irq, pdev, desc);
-       if (err)
-               return err;
-
-       return 0;
+       return pbm->setup_msi_irq(&virt_irq, pdev, desc);
 }
 
 void arch_teardown_msi_irq(unsigned int virt_irq)
@@ -1112,12 +1099,11 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
        struct msi_desc *entry = get_irq_msi(virt_irq);
        struct pci_dev *pdev = entry->dev;
        struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
-       struct pci_controller_info *p = pbm->parent;
 
-       if (!pbm->msi_num || !p->setup_msi_irq)
+       if (!pbm->teardown_msi_irq)
                return;
 
-       return p->teardown_msi_irq(virt_irq, pdev);
+       return pbm->teardown_msi_irq(virt_irq, pdev);
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
index 1e6aeedf43c4201672e1f6ea61275f44f3dcd687..76faaa8135dd957b0e28ad53499cc47d766babb7 100644 (file)
@@ -9,12 +9,26 @@
 #include <linux/pci.h>
 #include <linux/device.h>
 
-#include <asm/pbm.h>
 #include <asm/prom.h>
 #include <asm/of_device.h>
+#include <asm/oplib.h>
 
 #include "pci_impl.h"
 
+void pci_get_pbm_props(struct pci_pbm_info *pbm)
+{
+       const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL);
+
+       pbm->pci_first_busno = val[0];
+       pbm->pci_last_busno = val[1];
+
+       val = of_get_property(pbm->prom_node, "ino-bitmap", NULL);
+       if (val) {
+               pbm->ino_bitmap = (((u64)val[1] << 32UL) |
+                                  ((u64)val[0] <<  0UL));
+       }
+}
+
 static void pci_register_legacy_regions(struct resource *io_res,
                                        struct resource *mem_res)
 {
@@ -149,8 +163,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
 }
 
 /* Generic helper routines for PCI error reporting. */
-void pci_scan_for_target_abort(struct pci_controller_info *p,
-                              struct pci_pbm_info *pbm,
+void pci_scan_for_target_abort(struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
        struct pci_dev *pdev;
@@ -165,18 +178,16 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
                                   PCI_STATUS_REC_TARGET_ABORT));
                if (error_bits) {
                        pci_write_config_word(pdev, PCI_STATUS, error_bits);
-                       printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n",
-                              p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
-                              pci_name(pdev), status);
+                       printk("%s: Device %s saw Target Abort [%016x]\n",
+                              pbm->name, pci_name(pdev), status);
                }
        }
 
        list_for_each_entry(bus, &pbus->children, node)
-               pci_scan_for_target_abort(p, pbm, bus);
+               pci_scan_for_target_abort(pbm, bus);
 }
 
-void pci_scan_for_master_abort(struct pci_controller_info *p,
-                              struct pci_pbm_info *pbm,
+void pci_scan_for_master_abort(struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
        struct pci_dev *pdev;
@@ -190,18 +201,16 @@ void pci_scan_for_master_abort(struct pci_controller_info *p,
                        (status & (PCI_STATUS_REC_MASTER_ABORT));
                if (error_bits) {
                        pci_write_config_word(pdev, PCI_STATUS, error_bits);
-                       printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n",
-                              p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
-                              pci_name(pdev), status);
+                       printk("%s: Device %s received Master Abort [%016x]\n",
+                              pbm->name, pci_name(pdev), status);
                }
        }
 
        list_for_each_entry(bus, &pbus->children, node)
-               pci_scan_for_master_abort(p, pbm, bus);
+               pci_scan_for_master_abort(pbm, bus);
 }
 
-void pci_scan_for_parity_error(struct pci_controller_info *p,
-                              struct pci_pbm_info *pbm,
+void pci_scan_for_parity_error(struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
        struct pci_dev *pdev;
@@ -216,12 +225,11 @@ void pci_scan_for_parity_error(struct pci_controller_info *p,
                                   PCI_STATUS_DETECTED_PARITY));
                if (error_bits) {
                        pci_write_config_word(pdev, PCI_STATUS, error_bits);
-                       printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n",
-                              p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
-                              pci_name(pdev), status);
+                       printk("%s: Device %s saw Parity Error [%016x]\n",
+                              pbm->name, pci_name(pdev), status);
                }
        }
 
        list_for_each_entry(bus, &pbus->children, node)
-               pci_scan_for_parity_error(p, pbm, bus);
+               pci_scan_for_parity_error(pbm, bus);
 }
index 0fe626631e12543bae2bd710d63bd885e63e3dc0..2e0eb4ee8f71a67176d370bfc8d19366d8aec1ad 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 
-#include <asm/pbm.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
 
@@ -160,21 +159,9 @@ static struct pci_ops pci_fire_ops = {
        .write  =       fire_write_pci_cfg,
 };
 
-static void pbm_scan_bus(struct pci_controller_info *p,
-                        struct pci_pbm_info *pbm)
+static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
 {
        pbm->pci_bus = pci_scan_one_pbm(pbm);
-}
-
-static void pci_fire_scan_bus(struct pci_controller_info *p)
-{
-       struct device_node *dp;
-
-       if ((dp = p->pbm_A.prom_node) != NULL)
-               pbm_scan_bus(p, &p->pbm_A);
-
-       if ((dp = p->pbm_B.prom_node) != NULL)
-               pbm_scan_bus(p, &p->pbm_B);
 
        /* XXX register error interrupt handlers XXX */
 }
@@ -313,18 +300,24 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
 }
 
 static void pci_fire_pbm_init(struct pci_controller_info *p,
-                               struct device_node *dp, u32 portid)
+                             struct device_node *dp, u32 portid)
 {
        const struct linux_prom64_registers *regs;
        struct pci_pbm_info *pbm;
-       const u32 *ino_bitmap;
-       const unsigned int *busrange;
 
        if ((portid & 1) == 0)
                pbm = &p->pbm_A;
        else
                pbm = &p->pbm_B;
 
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
+
+       pbm->scan_bus = pci_fire_scan_bus;
+       pbm->pci_ops = &pci_fire_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->portid = portid;
        pbm->parent = p;
        pbm->prom_node = dp;
@@ -338,13 +331,7 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
 
        pci_determine_mem_io_space(pbm);
 
-       ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
-       pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
-                          ((u64)ino_bitmap[0] <<  0UL));
-
-       busrange = of_get_property(dp, "bus-range", NULL);
-       pbm->pci_first_busno = busrange[0];
-       pbm->pci_last_busno = busrange[1];
+       pci_get_pbm_props(pbm);
 
        pci_fire_hw_init(pbm);
        pci_fire_pbm_iommu_init(pbm);
@@ -362,19 +349,11 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
        struct pci_controller_info *p;
        u32 portid = of_getintprop_default(dp, "portid", 0xff);
        struct iommu *iommu;
+       struct pci_pbm_info *pbm;
 
-       for (p = pci_controller_root; p; p = p->next) {
-               struct pci_pbm_info *pbm;
-
-               if (p->pbm_A.prom_node && p->pbm_B.prom_node)
-                       continue;
-
-               pbm = (p->pbm_A.prom_node ?
-                      &p->pbm_A :
-                      &p->pbm_B);
-
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
                if (portid_compare(pbm->portid, portid)) {
-                       pci_fire_pbm_init(p, dp, portid);
+                       pci_fire_pbm_init(pbm->parent, dp, portid);
                        return;
                }
        }
@@ -395,14 +374,7 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
 
        p->pbm_B.iommu = iommu;
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
-
-       p->index = pci_num_controllers++;
-
-       p->scan_bus = pci_fire_scan_bus;
        /* XXX MSI support XXX */
-       p->pci_ops = &pci_fire_ops;
 
        /* Like PSYCHO and SCHIZO we have a 2GB aligned area
         * for memory space.
index 1208583fcb83b433c2abc7b3a3a60a528f0c1fde..8e38023868aafd81a509c07194b76b84ccbee70b 100644 (file)
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
 #include <asm/io.h>
 #include <asm/prom.h>
+#include <asm/iommu.h>
 
-extern struct pci_controller_info *pci_controller_root;
+/* The abstraction used here is that there are PCI controllers,
+ * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
+ * underneath.  Each PCI bus module uses an IOMMU (shared by both
+ * PBMs of a controller, or per-PBM), and if a streaming buffer
+ * is present, each PCI bus module has it's own. (ie. the IOMMU
+ * might be shared between PBMs, the STC is never shared)
+ * Furthermore, each PCI bus module controls it's own autonomous
+ * PCI bus.
+ */
+
+#define PCI_STC_FLUSHFLAG_INIT(STC) \
+       (*((STC)->strbuf_flushflag) = 0UL)
+#define PCI_STC_FLUSHFLAG_SET(STC) \
+       (*((STC)->strbuf_flushflag) != 0UL)
+
+struct pci_controller_info;
+
+struct pci_pbm_info {
+       struct pci_pbm_info             *next;
+       int                             index;
+
+       /* PCI controller we sit under. */
+       struct pci_controller_info      *parent;
+
+       /* Physical address base of controller registers. */
+       unsigned long                   controller_regs;
+
+       /* Physical address base of PBM registers. */
+       unsigned long                   pbm_regs;
+
+       /* Physical address of DMA sync register, if any.  */
+       unsigned long                   sync_reg;
+
+       /* Opaque 32-bit system bus Port ID. */
+       u32                             portid;
+
+       /* Opaque 32-bit handle used for hypervisor calls.  */
+       u32                             devhandle;
+
+       /* Chipset version information. */
+       int                             chip_type;
+#define PBM_CHIP_TYPE_SABRE            1
+#define PBM_CHIP_TYPE_PSYCHO           2
+#define PBM_CHIP_TYPE_SCHIZO           3
+#define PBM_CHIP_TYPE_SCHIZO_PLUS      4
+#define PBM_CHIP_TYPE_TOMATILLO                5
+       int                             chip_version;
+       int                             chip_revision;
+
+       /* Name used for top-level resources. */
+       char                            *name;
+
+       /* OBP specific information. */
+       struct device_node              *prom_node;
+       u64                             ino_bitmap;
+
+       /* PBM I/O and Memory space resources. */
+       struct resource                 io_space;
+       struct resource                 mem_space;
+
+       /* Base of PCI Config space, can be per-PBM or shared. */
+       unsigned long                   config_space;
+
+       /* State of 66MHz capabilities on this PBM. */
+       int                             is_66mhz_capable;
+       int                             all_devs_66mhz;
+
+#ifdef CONFIG_PCI_MSI
+       /* MSI info.  */
+       u32                             msiq_num;
+       u32                             msiq_ent_count;
+       u32                             msiq_first;
+       u32                             msiq_first_devino;
+       u32                             msi_num;
+       u32                             msi_first;
+       u32                             msi_data_mask;
+       u32                             msix_data_width;
+       u64                             msi32_start;
+       u64                             msi64_start;
+       u32                             msi32_len;
+       u32                             msi64_len;
+       void                            *msi_queues;
+       unsigned long                   *msi_bitmap;
+       int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
+                            struct msi_desc *entry);
+       void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
+#endif /* !(CONFIG_PCI_MSI) */
+
+       /* This PBM's streaming buffer. */
+       struct strbuf                   stc;
+
+       /* IOMMU state, potentially shared by both PBM segments. */
+       struct iommu                    *iommu;
+
+       /* Now things for the actual PCI bus probes. */
+       unsigned int                    pci_first_busno;
+       unsigned int                    pci_last_busno;
+       struct pci_bus                  *pci_bus;
+       void (*scan_bus)(struct pci_pbm_info *);
+       struct pci_ops                  *pci_ops;
+};
+
+struct pci_controller_info {
+       /* The PCI bus modules controlled by us. */
+       struct pci_pbm_info             pbm_A;
+       struct pci_pbm_info             pbm_B;
+};
+
+extern struct pci_pbm_info *pci_pbm_root;
 extern unsigned long pci_memspace_mask;
 
-extern int pci_num_controllers;
+extern int pci_num_pbms;
 
 /* PCI bus scanning and fixup support. */
+extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize,
+                                u32 dma_offset, u32 dma_addr_mask);
+extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
 extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
 extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
 
@@ -30,9 +144,9 @@ extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
                                         u32 value);
 
 /* Error reporting support. */
-extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
-extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
-extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_target_abort(struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_master_abort(struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_parity_error(struct pci_pbm_info *, struct pci_bus *);
 
 /* Configuration space access. */
 extern void pci_config_read8(u8 *addr, u8 *ret);
index 9e405cbbcb0d244ca7cf81a2c57564b7aedfe0c0..dfd6f9f4790b852035a5143f77559163d7e587ad 100644 (file)
@@ -8,10 +8,12 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 
-#include <asm/pbm.h>
+#include <asm/oplib.h>
 
 #include "iommu_common.h"
+#include "pci_impl.h"
 
 #define PCI_STC_CTXMATCH_ADDR(STC, CTX)        \
        ((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
index 253d40ec2245209063ee16a971c0d02a7366a70f..2edcb1dd13c3744674c6e96cba7f39e1be12a477 100644 (file)
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
-#include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
 #include <asm/prom.h>
 #include <asm/of_device.h>
+#include <asm/oplib.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -98,13 +98,8 @@ static int psycho_out_of_range(struct pci_pbm_info *pbm,
                               unsigned char bus,
                               unsigned char devfn)
 {
-       return ((pbm->parent == 0) ||
-               ((pbm == &pbm->parent->pbm_B) &&
-                (bus == pbm->pci_first_busno) &&
-                PCI_SLOT(devfn) > 8) ||
-               ((pbm == &pbm->parent->pbm_A) &&
-                (bus == pbm->pci_first_busno) &&
-                PCI_SLOT(devfn) > 8));
+       return ((bus == pbm->pci_first_busno) &&
+               PCI_SLOT(devfn) > 8);
 }
 
 /* PSYCHO PCI configuration space accessors. */
@@ -265,12 +260,11 @@ static unsigned long stc_error_buf[128];
 static unsigned long stc_tag_buf[16];
 static unsigned long stc_line_buf[16];
 
-static void __psycho_check_one_stc(struct pci_controller_info *p,
-                                  struct pci_pbm_info *pbm,
+static void __psycho_check_one_stc(struct pci_pbm_info *pbm,
                                   int is_pbm_a)
 {
        struct strbuf *strbuf = &pbm->stc;
-       unsigned long regbase = p->pbm_A.controller_regs;
+       unsigned long regbase = pbm->controller_regs;
        unsigned long err_base, tag_base, line_base;
        u64 control;
        int i;
@@ -326,9 +320,8 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
                        unsigned long errval = stc_error_buf[j];
                        if (errval != 0) {
                                saw_error++;
-                               printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n",
-                                      p->index,
-                                      (is_pbm_a ? 'A' : 'B'),
+                               printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n",
+                                      pbm->name,
                                       j,
                                       (errval & PSYCHO_STCERR_WRITE) ? 1 : 0,
                                       (errval & PSYCHO_STCERR_READ) ? 1 : 0);
@@ -337,18 +330,16 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
                if (saw_error != 0) {
                        unsigned long tagval = stc_tag_buf[i];
                        unsigned long lineval = stc_line_buf[i];
-                       printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n",
-                              p->index,
-                              (is_pbm_a ? 'A' : 'B'),
+                       printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n",
+                              pbm->name,
                               i,
                               ((tagval & PSYCHO_STCTAG_PPN) >> 19UL),
                               (tagval & PSYCHO_STCTAG_VPN),
                               ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0),
                               ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0));
-                       printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
+                       printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
                               "V(%d)FOFN(%d)]\n",
-                              p->index,
-                              (is_pbm_a ? 'A' : 'B'),
+                              pbm->name,
                               i,
                               ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL),
                               ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL),
@@ -362,20 +353,13 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
        spin_unlock(&stc_buf_lock);
 }
 
-static void __psycho_check_stc_error(struct pci_controller_info *p,
+static void __psycho_check_stc_error(struct pci_pbm_info *pbm,
                                     unsigned long afsr,
                                     unsigned long afar,
                                     enum psycho_error_type type)
 {
-       struct pci_pbm_info *pbm;
-
-       pbm = &p->pbm_A;
-       if (pbm->stc.strbuf_enabled)
-               __psycho_check_one_stc(p, pbm, 1);
-
-       pbm = &p->pbm_B;
-       if (pbm->stc.strbuf_enabled)
-               __psycho_check_one_stc(p, pbm, 0);
+       __psycho_check_one_stc(pbm,
+                              (pbm == &pbm->parent->pbm_A));
 }
 
 /* When an Uncorrectable Error or a PCI Error happens, we
@@ -413,12 +397,12 @@ static void __psycho_check_stc_error(struct pci_controller_info *p,
 #define  PSYCHO_IOMMU_DATA_VALID (1UL << 30UL)
 #define  PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL)
 #define  PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL
-static void psycho_check_iommu_error(struct pci_controller_info *p,
+static void psycho_check_iommu_error(struct pci_pbm_info *pbm,
                                     unsigned long afsr,
                                     unsigned long afar,
                                     enum psycho_error_type type)
 {
-       struct iommu *iommu = p->pbm_A.iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long iommu_tag[16];
        unsigned long iommu_data[16];
        unsigned long flags;
@@ -449,8 +433,8 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
                        type_string = "ECC Error";
                        break;
                };
-               printk("PSYCHO%d: IOMMU Error, type[%s]\n",
-                      p->index, type_string);
+               printk("%s: IOMMU Error, type[%s]\n",
+                      pbm->name, type_string);
 
                /* Put the IOMMU into diagnostic mode and probe
                 * it's TLB for entries with error status.
@@ -465,7 +449,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
                psycho_write(iommu->iommu_control,
                             control | PSYCHO_IOMMU_CTRL_DENAB);
                for (i = 0; i < 16; i++) {
-                       unsigned long base = p->pbm_A.controller_regs;
+                       unsigned long base = pbm->controller_regs;
 
                        iommu_tag[i] =
                                psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
@@ -503,20 +487,20 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
                                type_string = "ECC Error";
                                break;
                        };
-                       printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n",
-                              p->index, i, type_string,
+                       printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n",
+                              pbm->name, i, type_string,
                               ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0),
                               ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0),
                               ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8),
                               (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT);
-                       printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
-                              p->index, i,
+                       printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
+                              pbm->name, i,
                               ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0),
                               ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0),
                               (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT);
                }
        }
-       __psycho_check_stc_error(p, afsr, afar, type);
+       __psycho_check_stc_error(pbm, afsr, afar, type);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -541,9 +525,10 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
 
 static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR;
-       unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       struct pci_controller_info *p = pbm->parent;
+       unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported;
 
@@ -560,22 +545,22 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
        psycho_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Uncorrectable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & PSYCHO_UEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & PSYCHO_UEAFSR_PDRD) ?
                  "DMA Read" :
                  ((error_bits & PSYCHO_UEAFSR_PDWR) ?
                   "DMA Write" : "???")))));
-       printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n",
-              p->index,
+       printk("%s: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n",
+              pbm->name,
               (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL,
               (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL,
               (afsr & PSYCHO_UEAFSR_MID) >> 24UL,
               ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0));
-       printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar);
-       printk("PSYCHO%d: UE Secondary errors [", p->index);
+       printk("%s: UE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: UE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & PSYCHO_UEAFSR_SPIO) {
                reported++;
@@ -593,8 +578,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
                printk("(none)");
        printk("]\n");
 
-       /* Interrogate IOMMU for error status. */
-       psycho_check_iommu_error(p, afsr, afar, UE_ERR);
+       /* Interrogate both IOMMUs for error status. */
+       psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR);
+       psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR);
 
        return IRQ_HANDLED;
 }
@@ -618,9 +604,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
 
 static irqreturn_t psycho_ce_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR;
-       unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       unsigned long afsr_reg = pbm->controller_regs + PSYCHO_CE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + PSYCHO_CE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported;
 
@@ -637,8 +623,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id)
        psycho_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PSYCHO%d: Correctable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Correctable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & PSYCHO_CEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & PSYCHO_CEAFSR_PDRD) ?
@@ -649,16 +635,16 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id)
        /* XXX Use syndrome and afar to print out module string just like
         * XXX UDB CE trap handler does... -DaveM
         */
-       printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+       printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
               "UPA_MID[%02lx] was_block(%d)\n",
-              p->index,
+              pbm->name,
               (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL,
               (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL,
               (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL,
               (afsr & PSYCHO_CEAFSR_MID) >> 24UL,
               ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0));
-       printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar);
-       printk("PSYCHO%d: CE Secondary errors [", p->index);
+       printk("%s: CE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: CE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & PSYCHO_CEAFSR_SPIO) {
                reported++;
@@ -773,8 +759,8 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
        psycho_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n",
-              p->index, (is_pbm_a ? 'A' : 'B'),
+       printk("%s: PCI Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & PSYCHO_PCIAFSR_PMA) ?
                 "Master Abort" :
                 ((error_bits & PSYCHO_PCIAFSR_PTA) ?
@@ -783,15 +769,13 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
                   "Excessive Retries" :
                   ((error_bits & PSYCHO_PCIAFSR_PPERR) ?
                    "Parity Error" : "???"))))));
-       printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n",
-              p->index, (is_pbm_a ? 'A' : 'B'),
+       printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n",
+              pbm->name,
               (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL,
               (afsr & PSYCHO_PCIAFSR_MID) >> 25UL,
               (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0);
-       printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n",
-              p->index, (is_pbm_a ? 'A' : 'B'), afar);
-       printk("PSYCHO%d(PBM%c): PCI Secondary errors [",
-              p->index, (is_pbm_a ? 'A' : 'B'));
+       printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: PCI Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & PSYCHO_PCIAFSR_SMA) {
                reported++;
@@ -823,11 +807,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
         * a bug in the IOMMU support code or a PCI device driver.
         */
        if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) {
-               psycho_check_iommu_error(p, afsr, afar, PCI_ERR);
-               pci_scan_for_target_abort(p, pbm, pbm->pci_bus);
+               psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR);
+               pci_scan_for_target_abort(pbm, pbm->pci_bus);
        }
        if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA))
-               pci_scan_for_master_abort(p, pbm, pbm->pci_bus);
+               pci_scan_for_master_abort(pbm, pbm->pci_bus);
 
        /* For excessive retries, PSYCHO/PBM will abort the device
         * and there is no way to specifically check for excessive
@@ -837,7 +821,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
         */
 
        if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR))
-               pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
+               pci_scan_for_parity_error(pbm, pbm->pci_bus);
 
        return IRQ_HANDLED;
 }
@@ -847,34 +831,49 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
 #define  PSYCHO_ECCCTRL_EE      0x8000000000000000UL /* Enable ECC Checking */
 #define  PSYCHO_ECCCTRL_UE      0x4000000000000000UL /* Enable UE Interrupts */
 #define  PSYCHO_ECCCTRL_CE      0x2000000000000000UL /* Enable CE INterrupts */
-static void psycho_register_error_handlers(struct pci_controller_info *p)
+static void psycho_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
        struct of_device *op = of_find_device_by_node(pbm->prom_node);
-       unsigned long base = p->pbm_A.controller_regs;
+       unsigned long base = pbm->controller_regs;
        u64 tmp;
+       int err;
 
        if (!op)
                return;
 
        /* Psycho interrupt property order is:
-        * 0: PCIERR PBM B INO
+        * 0: PCIERR INO for this PBM
         * 1: UE ERR
         * 2: CE ERR
         * 3: POWER FAIL
         * 4: SPARE HARDWARE
-        * 5: PCIERR PBM A INO
+        * 5: POWER MANAGEMENT
         */
 
        if (op->num_irqs < 6)
                return;
 
-       request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO UE", p);
-       request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO CE", p);
-       request_irq(op->irqs[5], psycho_pcierr_intr, IRQF_SHARED,
-                   "PSYCHO PCIERR-A", &p->pbm_A);
-       request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED,
-                   "PSYCHO PCIERR-B", &p->pbm_B);
+       /* We really mean to ignore the return result here.  Two
+        * PCI controller share the same interrupt numbers and
+        * drive the same front-end hardware.  Whichever of the
+        * two get in here first will register the IRQ handler
+        * the second will just error out since we do not pass in
+        * IRQF_SHARED.
+        */
+       err = request_irq(op->irqs[1], psycho_ue_intr, 0,
+                         "PSYCHO_UE", pbm);
+       err = request_irq(op->irqs[2], psycho_ce_intr, 0,
+                         "PSYCHO_CE", pbm);
+
+       /* This one, however, ought not to fail.  We can just warn
+        * about it since the system can still operate properly even
+        * if this fails.
+        */
+       err = request_irq(op->irqs[0], psycho_pcierr_intr, 0,
+                         "PSYCHO_PCIERR", pbm);
+       if (err)
+               printk(KERN_WARNING "%s: Could not register PCIERR, "
+                      "err=%d\n", pbm->name, err);
 
        /* Enable UE and CE interrupts for controller. */
        psycho_write(base + PSYCHO_ECC_CTRL,
@@ -918,54 +917,45 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void pbm_scan_bus(struct pci_controller_info *p,
-                        struct pci_pbm_info *pbm)
+static void psycho_scan_bus(struct pci_pbm_info *pbm)
 {
+       pbm_config_busmastering(pbm);
+       pbm->is_66mhz_capable = 0;
        pbm->pci_bus = pci_scan_one_pbm(pbm);
-}
-
-static void psycho_scan_bus(struct pci_controller_info *p)
-{
-       pbm_config_busmastering(&p->pbm_B);
-       p->pbm_B.is_66mhz_capable = 0;
-       pbm_config_busmastering(&p->pbm_A);
-       p->pbm_A.is_66mhz_capable = 1;
-       pbm_scan_bus(p, &p->pbm_B);
-       pbm_scan_bus(p, &p->pbm_A);
 
        /* After the PCI bus scan is complete, we can register
         * the error interrupt handlers.
         */
-       psycho_register_error_handlers(p);
+       psycho_register_error_handlers(pbm);
 }
 
-static void psycho_iommu_init(struct pci_controller_info *p)
+static void psycho_iommu_init(struct pci_pbm_info *pbm)
 {
-       struct iommu *iommu = p->pbm_A.iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long i;
        u64 control;
 
        /* Register addresses. */
-       iommu->iommu_control  = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
-       iommu->iommu_tsbbase  = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
-       iommu->iommu_flush    = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH;
+       iommu->iommu_control  = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
+       iommu->iommu_tsbbase  = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
+       iommu->iommu_flush    = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
        /* PSYCHO's IOMMU lacks ctx flushing. */
        iommu->iommu_ctxflush = 0;
 
        /* We use the main control register of PSYCHO as the write
         * completion register.
         */
-       iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL;
+       iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL;
 
        /*
         * Invalidate TLB Entries.
         */
-       control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
+       control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL);
        control |= PSYCHO_IOMMU_CTRL_DENAB;
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
+       psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control);
        for(i = 0; i < 16; i++) {
-               psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
-               psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+               psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
+               psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
        }
 
        /* Leave diag mode enabled for full-flushing done
@@ -973,17 +963,17 @@ static void psycho_iommu_init(struct pci_controller_info *p)
         */
        pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
 
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE,
+       psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE,
                     __pa(iommu->page_table));
 
-       control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
+       control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL);
        control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
        control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
+       psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control);
 
        /* If necessary, hook us up for starfire IRQ translations. */
        if (this_is_starfire)
-               starfire_hookup(p->pbm_A.portid);
+               starfire_hookup(pbm->portid);
 }
 
 #define PSYCHO_IRQ_RETRY       0x1a00UL
@@ -998,36 +988,35 @@ static void psycho_iommu_init(struct pci_controller_info *p)
 #define  PSYCHO_PCIDIAG_IPAPAR  0x0000000000000002UL /* Invert PIO address parity    */
 #define  PSYCHO_PCIDIAG_LPBACK  0x0000000000000001UL /* Enable loopback mode         */
 
-static void psycho_controller_hwinit(struct pci_controller_info *p)
+static void psycho_controller_hwinit(struct pci_pbm_info *pbm)
 {
        u64 tmp;
 
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5);
+       psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5);
 
        /* Enable arbiter for all PCI slots. */
-       tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL);
+       tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL);
        tmp |= PSYCHO_PCICTRL_AEN;
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp);
+       psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp);
 
-       tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL);
+       tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL);
        tmp |= PSYCHO_PCICTRL_AEN;
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp);
+       psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp);
 
        /* Disable DMA write / PIO read synchronization on
         * both PCI bus segments.
         * [ U2P Erratum 1243770, STP2223BGA data sheet ]
         */
-       tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG);
+       tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG);
        tmp |= PSYCHO_PCIDIAG_DDWSYNC;
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp);
+       psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp);
 
-       tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG);
+       tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG);
        tmp |= PSYCHO_PCIDIAG_DDWSYNC;
-       psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp);
+       psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp);
 }
 
-static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
-                                  struct pci_pbm_info *pbm,
+static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm,
                                   int is_pbm_a)
 {
        unsigned long base = pbm->controller_regs;
@@ -1088,7 +1077,6 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
 static void psycho_pbm_init(struct pci_controller_info *p,
                            struct device_node *dp, int is_pbm_a)
 {
-       unsigned int *busrange;
        struct property *prop;
        struct pci_pbm_info *pbm;
 
@@ -1097,6 +1085,14 @@ static void psycho_pbm_init(struct pci_controller_info *p,
        else
                pbm = &p->pbm_B;
 
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
+
+       pbm->scan_bus = psycho_scan_bus;
+       pbm->pci_ops = &psycho_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
        pbm->chip_version = 0;
        prop = of_find_property(dp, "version#", NULL);
@@ -1117,12 +1113,9 @@ static void psycho_pbm_init(struct pci_controller_info *p,
 
        pci_determine_mem_io_space(pbm);
 
-       prop = of_find_property(dp, "bus-range", NULL);
-       busrange = prop->value;
-       pbm->pci_first_busno = busrange[0];
-       pbm->pci_last_busno = busrange[1];
+       pci_get_pbm_props(pbm);
 
-       psycho_pbm_strbuf_init(p, pbm, is_pbm_a);
+       psycho_pbm_strbuf_init(pbm, is_pbm_a);
 }
 
 #define PSYCHO_CONFIGSPACE     0x001000000UL
@@ -1131,6 +1124,7 @@ void psycho_init(struct device_node *dp, char *model_name)
 {
        struct linux_prom64_registers *pr_regs;
        struct pci_controller_info *p;
+       struct pci_pbm_info *pbm;
        struct iommu *iommu;
        struct property *prop;
        u32 upa_portid;
@@ -1141,7 +1135,9 @@ void psycho_init(struct device_node *dp, char *model_name)
        if (prop)
                upa_portid = *(u32 *) prop->value;
 
-       for(p = pci_controller_root; p; p = p->next) {
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
+               struct pci_controller_info *p = pbm->parent;
+
                if (p->pbm_A.portid == upa_portid) {
                        is_pbm_a = (p->pbm_A.prom_node == NULL);
                        psycho_pbm_init(p, dp, is_pbm_a);
@@ -1161,14 +1157,8 @@ void psycho_init(struct device_node *dp, char *model_name)
        }
        p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
-
        p->pbm_A.portid = upa_portid;
        p->pbm_B.portid = upa_portid;
-       p->index = pci_num_controllers++;
-       p->scan_bus = psycho_scan_bus;
-       p->pci_ops = &psycho_ops;
 
        prop = of_find_property(dp, "reg", NULL);
        pr_regs = prop->value;
@@ -1185,9 +1175,9 @@ void psycho_init(struct device_node *dp, char *model_name)
         */
        pci_memspace_mask = 0x7fffffffUL;
 
-       psycho_controller_hwinit(p);
+       psycho_controller_hwinit(&p->pbm_A);
 
-       psycho_iommu_init(p);
+       psycho_iommu_init(&p->pbm_A);
 
        is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
        psycho_pbm_init(p, dp, is_pbm_a);
index 397862fbd9e1d0f46b7129471ace28ea58ae1a25..4cefe6e83b24cfc02783a21b5dc0a80c4721f558 100644 (file)
 #include <linux/interrupt.h>
 
 #include <asm/apb.h>
-#include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/smp.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
+#include <asm/of_device.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -494,11 +494,11 @@ static struct pci_ops sabre_ops = {
 };
 
 /* SABRE error handling support. */
-static void sabre_check_iommu_error(struct pci_controller_info *p,
+static void sabre_check_iommu_error(struct pci_pbm_info *pbm,
                                    unsigned long afsr,
                                    unsigned long afar)
 {
-       struct iommu *iommu = p->pbm_A.iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long iommu_tag[16];
        unsigned long iommu_data[16];
        unsigned long flags;
@@ -526,8 +526,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
                        type_string = "Unknown";
                        break;
                };
-               printk("SABRE%d: IOMMU Error, type[%s]\n",
-                      p->index, type_string);
+               printk("%s: IOMMU Error, type[%s]\n",
+                      pbm->name, type_string);
 
                /* Enter diagnostic mode and probe for error'd
                 * entries in the IOTLB.
@@ -536,7 +536,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
                sabre_write(iommu->iommu_control,
                            (control | SABRE_IOMMUCTRL_DENAB));
                for (i = 0; i < 16; i++) {
-                       unsigned long base = p->pbm_A.controller_regs;
+                       unsigned long base = pbm->controller_regs;
 
                        iommu_tag[i] =
                                sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
@@ -566,13 +566,13 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
                                type_string = "Unknown";
                                break;
                        };
-                       printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
-                              p->index, i, tag, type_string,
+                       printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
+                              pbm->name, i, tag, type_string,
                               ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0),
                               ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8),
                               ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT));
-                       printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n",
-                              p->index, i, data,
+                       printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n",
+                              pbm->name, i, data,
                               ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0),
                               ((data & SABRE_IOMMUDATA_USED) ? 1 : 0),
                               ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0),
@@ -584,9 +584,9 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
 
 static irqreturn_t sabre_ue_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
-       unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       unsigned long afsr_reg = pbm->controller_regs + SABRE_UE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported;
 
@@ -604,21 +604,21 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id)
        sabre_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n",
-              p->index,
+       printk("%s: Uncorrectable Error, primary error type[%s%s]\n",
+              pbm->name,
               ((error_bits & SABRE_UEAFSR_PDRD) ?
                "DMA Read" :
                ((error_bits & SABRE_UEAFSR_PDWR) ?
                 "DMA Write" : "???")),
               ((error_bits & SABRE_UEAFSR_PDTE) ?
                ":Translation Error" : ""));
-       printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n",
-              p->index,
+       printk("%s: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n",
+              pbm->name,
               (afsr & SABRE_UEAFSR_BMSK) >> 32UL,
               (afsr & SABRE_UEAFSR_OFF) >> 29UL,
               ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0));
-       printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar);
-       printk("SABRE%d: UE Secondary errors [", p->index);
+       printk("%s: UE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: UE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SABRE_UEAFSR_SDRD) {
                reported++;
@@ -637,16 +637,16 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id)
        printk("]\n");
 
        /* Interrogate IOMMU for error status. */
-       sabre_check_iommu_error(p, afsr, afar);
+       sabre_check_iommu_error(pbm, afsr, afar);
 
        return IRQ_HANDLED;
 }
 
 static irqreturn_t sabre_ce_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
-       unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       unsigned long afsr_reg = pbm->controller_regs + SABRE_CE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported;
 
@@ -663,8 +663,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id)
        sabre_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("SABRE%d: Correctable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Correctable Error, primary error type[%s]\n",
+              pbm->name,
               ((error_bits & SABRE_CEAFSR_PDRD) ?
                "DMA Read" :
                ((error_bits & SABRE_CEAFSR_PDWR) ?
@@ -673,15 +673,15 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id)
        /* XXX Use syndrome and afar to print out module string just like
         * XXX UDB CE trap handler does... -DaveM
         */
-       printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+       printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
               "was_block(%d)\n",
-              p->index,
+              pbm->name,
               (afsr & SABRE_CEAFSR_ESYND) >> 48UL,
               (afsr & SABRE_CEAFSR_BMSK) >> 32UL,
               (afsr & SABRE_CEAFSR_OFF) >> 29UL,
               ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0));
-       printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar);
-       printk("SABRE%d: CE Secondary errors [", p->index);
+       printk("%s: CE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: CE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SABRE_CEAFSR_SDRD) {
                reported++;
@@ -698,13 +698,13 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
+static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm)
 {
        unsigned long csr_reg, csr, csr_error_bits;
        irqreturn_t ret = IRQ_NONE;
        u16 stat;
 
-       csr_reg = p->pbm_A.controller_regs + SABRE_PCICTRL;
+       csr_reg = pbm->controller_regs + SABRE_PCICTRL;
        csr = sabre_read(csr_reg);
        csr_error_bits =
                csr & SABRE_PCICTRL_SERR;
@@ -714,8 +714,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
 
                /* Log 'em.  */
                if (csr_error_bits & SABRE_PCICTRL_SERR)
-                       printk("SABRE%d: PCI SERR signal asserted.\n",
-                              p->index);
+                       printk("%s: PCI SERR signal asserted.\n",
+                              pbm->name);
                ret = IRQ_HANDLED;
        }
        pci_bus_read_config_word(sabre_root_bus, 0,
@@ -725,8 +725,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
                    PCI_STATUS_REC_TARGET_ABORT |
                    PCI_STATUS_REC_MASTER_ABORT |
                    PCI_STATUS_SIG_SYSTEM_ERROR)) {
-               printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n",
-                      p->index, stat);
+               printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
+                      pbm->name, stat);
                pci_bus_write_config_word(sabre_root_bus, 0,
                                          PCI_STATUS, 0xffff);
                ret = IRQ_HANDLED;
@@ -736,13 +736,13 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
 
 static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
+       struct pci_pbm_info *pbm = dev_id;
        unsigned long afsr_reg, afar_reg;
        unsigned long afsr, afar, error_bits;
        int reported;
 
-       afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR;
-       afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR;
+       afsr_reg = pbm->controller_regs + SABRE_PIOAFSR;
+       afar_reg = pbm->controller_regs + SABRE_PIOAFAR;
 
        /* Latch error status. */
        afar = sabre_read(afar_reg);
@@ -755,12 +755,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
                 SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |
                 SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);
        if (!error_bits)
-               return sabre_pcierr_intr_other(p);
+               return sabre_pcierr_intr_other(pbm);
        sabre_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("SABRE%d: PCI Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: PCI Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & SABRE_PIOAFSR_PMA) ?
                 "Master Abort" :
                 ((error_bits & SABRE_PIOAFSR_PTA) ?
@@ -769,12 +769,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
                   "Excessive Retries" :
                   ((error_bits & SABRE_PIOAFSR_PPERR) ?
                    "Parity Error" : "???"))))));
-       printk("SABRE%d: bytemask[%04lx] was_block(%d)\n",
-              p->index,
+       printk("%s: bytemask[%04lx] was_block(%d)\n",
+              pbm->name,
               (afsr & SABRE_PIOAFSR_BMSK) >> 32UL,
               (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0);
-       printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar);
-       printk("SABRE%d: PCI Secondary errors [", p->index);
+       printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: PCI Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SABRE_PIOAFSR_SMA) {
                reported++;
@@ -806,11 +806,11 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
         * a bug in the IOMMU support code or a PCI device driver.
         */
        if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {
-               sabre_check_iommu_error(p, afsr, afar);
-               pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+               sabre_check_iommu_error(pbm, afsr, afar);
+               pci_scan_for_target_abort(pbm, pbm->pci_bus);
        }
        if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA))
-               pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+               pci_scan_for_master_abort(pbm, pbm->pci_bus);
 
        /* For excessive retries, SABRE/PBM will abort the device
         * and there is no way to specifically check for excessive
@@ -820,18 +820,18 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
         */
 
        if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR))
-               pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus);
+               pci_scan_for_parity_error(pbm, pbm->pci_bus);
 
        return IRQ_HANDLED;
 }
 
-static void sabre_register_error_handlers(struct pci_controller_info *p)
+static void sabre_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
        struct device_node *dp = pbm->prom_node;
        struct of_device *op;
        unsigned long base = pbm->controller_regs;
        u64 tmp;
+       int err;
 
        if (pbm->chip_type == PBM_CHIP_TYPE_SABRE)
                dp = dp->parent;
@@ -858,22 +858,31 @@ static void sabre_register_error_handlers(struct pci_controller_info *p)
                     SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
                     SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE));
 
-       request_irq(op->irqs[1], sabre_ue_intr, IRQF_SHARED, "SABRE UE", p);
+       err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm);
+       if (err)
+               printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n",
+                      pbm->name, err);
 
        sabre_write(base + SABRE_CE_AFSR,
                    (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
                     SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR));
 
-       request_irq(op->irqs[2], sabre_ce_intr, IRQF_SHARED, "SABRE CE", p);
-       request_irq(op->irqs[0], sabre_pcierr_intr, IRQF_SHARED,
-                   "SABRE PCIERR", p);
+       err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm);
+       if (err)
+               printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n",
+                      pbm->name, err);
+       err = request_irq(op->irqs[0], sabre_pcierr_intr, 0,
+                         "SABRE_PCIERR", pbm);
+       if (err)
+               printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n",
+                      pbm->name, err);
 
        tmp = sabre_read(base + SABRE_PCICTRL);
        tmp |= SABRE_PCICTRL_ERREN;
        sabre_write(base + SABRE_PCICTRL, tmp);
 }
 
-static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
+static void apb_init(struct pci_bus *sabre_bus)
 {
        struct pci_dev *pdev;
 
@@ -909,7 +918,7 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
        }
 }
 
-static void sabre_scan_bus(struct pci_controller_info *p)
+static void sabre_scan_bus(struct pci_pbm_info *pbm)
 {
        static int once;
        struct pci_bus *pbus;
@@ -918,7 +927,7 @@ static void sabre_scan_bus(struct pci_controller_info *p)
         * at 66Mhz, but the front side of APB runs at 33Mhz
         * for both segments.
         */
-       p->pbm_A.is_66mhz_capable = 0;
+       pbm->is_66mhz_capable = 0;
 
        /* This driver has not been verified to handle
         * multiple SABREs yet, so trap this.
@@ -932,41 +941,41 @@ static void sabre_scan_bus(struct pci_controller_info *p)
        }
        once++;
 
-       pbus = pci_scan_one_pbm(&p->pbm_A);
+       pbus = pci_scan_one_pbm(pbm);
        if (!pbus)
                return;
 
        sabre_root_bus = pbus;
 
-       apb_init(p, pbus);
+       apb_init(pbus);
 
-       sabre_register_error_handlers(p);
+       sabre_register_error_handlers(pbm);
 }
 
-static void sabre_iommu_init(struct pci_controller_info *p,
+static void sabre_iommu_init(struct pci_pbm_info *pbm,
                             int tsbsize, unsigned long dvma_offset,
                             u32 dma_mask)
 {
-       struct iommu *iommu = p->pbm_A.iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long i;
        u64 control;
 
        /* Register addresses. */
-       iommu->iommu_control  = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
-       iommu->iommu_tsbbase  = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
-       iommu->iommu_flush    = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH;
-       iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC;
+       iommu->iommu_control  = pbm->controller_regs + SABRE_IOMMU_CONTROL;
+       iommu->iommu_tsbbase  = pbm->controller_regs + SABRE_IOMMU_TSBBASE;
+       iommu->iommu_flush    = pbm->controller_regs + SABRE_IOMMU_FLUSH;
+       iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC;
        /* Sabre's IOMMU lacks ctx flushing. */
        iommu->iommu_ctxflush = 0;
                                         
        /* Invalidate TLB Entries. */
-       control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
+       control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL);
        control |= SABRE_IOMMUCTRL_DENAB;
-       sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
+       sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
 
        for(i = 0; i < 16; i++) {
-               sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
-               sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+               sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
+               sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
        }
 
        /* Leave diag mode enabled for full-flushing done
@@ -974,10 +983,10 @@ static void sabre_iommu_init(struct pci_controller_info *p,
         */
        pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask);
 
-       sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE,
+       sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE,
                    __pa(iommu->page_table));
 
-       control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
+       control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL);
        control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
        control |= SABRE_IOMMUCTRL_ENAB;
        switch(tsbsize) {
@@ -992,22 +1001,23 @@ static void sabre_iommu_init(struct pci_controller_info *p,
                prom_halt();
                break;
        }
-       sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
+       sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
 }
 
-static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp)
+static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp)
 {
-       struct pci_pbm_info *pbm;
-
-       pbm = &p->pbm_A;
        pbm->name = dp->full_name;
        printk("%s: SABRE PCI Bus Module\n", pbm->name);
 
+       pbm->scan_bus = sabre_scan_bus;
+       pbm->pci_ops = &sabre_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->chip_type = PBM_CHIP_TYPE_SABRE;
        pbm->parent = p;
        pbm->prom_node = dp;
-       pbm->pci_first_busno = p->pci_first_busno;
-       pbm->pci_last_busno = p->pci_last_busno;
+       pci_get_pbm_props(pbm);
 
        pci_determine_mem_io_space(pbm);
 }
@@ -1016,9 +1026,9 @@ void sabre_init(struct device_node *dp, char *model_name)
 {
        const struct linux_prom64_registers *pr_regs;
        struct pci_controller_info *p;
+       struct pci_pbm_info *pbm;
        struct iommu *iommu;
        int tsbsize;
-       const u32 *busrange;
        const u32 *vdma;
        u32 upa_portid, dma_mask;
        u64 clear_irq;
@@ -1053,17 +1063,15 @@ void sabre_init(struct device_node *dp, char *model_name)
                prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
                prom_halt();
        }
-       p->pbm_A.iommu = iommu;
+       pbm = &p->pbm_A;
+       pbm->iommu = iommu;
 
        upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
 
-       p->pbm_A.portid = upa_portid;
-       p->index = pci_num_controllers++;
-       p->scan_bus = sabre_scan_bus;
-       p->pci_ops = &sabre_ops;
+       pbm->portid = upa_portid;
 
        /*
         * Map in SABRE register set and report the presence of this SABRE.
@@ -1074,26 +1082,26 @@ void sabre_init(struct device_node *dp, char *model_name)
        /*
         * First REG in property is base of entire SABRE register space.
         */
-       p->pbm_A.controller_regs = pr_regs[0].phys_addr;
+       pbm->controller_regs = pr_regs[0].phys_addr;
 
        /* Clear interrupts */
 
        /* PCI first */
        for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8)
-               sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
+               sabre_write(pbm->controller_regs + clear_irq, 0x0UL);
 
        /* Then OBIO */
        for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8)
-               sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
+               sabre_write(pbm->controller_regs + clear_irq, 0x0UL);
 
        /* Error interrupts are enabled later after the bus scan. */
-       sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL,
+       sabre_write(pbm->controller_regs + SABRE_PCICTRL,
                    (SABRE_PCICTRL_MRLEN   | SABRE_PCICTRL_SERR |
                     SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
 
        /* Now map in PCI config space for entire SABRE. */
-       p->pbm_A.config_space =
-               (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
+       pbm->config_space =
+               (pbm->controller_regs + SABRE_CONFIGSPACE);
 
        vdma = of_get_property(dp, "virtual-dma", NULL);
 
@@ -1117,14 +1125,10 @@ void sabre_init(struct device_node *dp, char *model_name)
                        prom_halt();
        }
 
-       sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
-
-       busrange = of_get_property(dp, "bus-range", NULL);
-       p->pci_first_busno = busrange[0];
-       p->pci_last_busno = busrange[1];
+       sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask);
 
        /*
         * Look for APB underneath.
         */
-       sabre_pbm_init(p, dp);
+       sabre_pbm_init(p, pbm, dp);
 }
index 91a7385e5d32798652fc8c9f74727275909a8fc8..e375d72b8eed0acf1ab8b46a7038008325512c33 100644 (file)
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
-#include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/upa.h>
 #include <asm/pstate.h>
 #include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/oplib.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -238,25 +239,6 @@ static unsigned long stc_line_buf[16];
 #define SCHIZO_PCIERR_B_INO    0x33 /* PBM B PCI bus error */
 #define SCHIZO_SERR_INO                0x34 /* Safari interface error */
 
-struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
-{
-       ino &= IMAP_INO;
-       if (p->pbm_A.ino_bitmap & (1UL << ino))
-               return &p->pbm_A;
-       if (p->pbm_B.ino_bitmap & (1UL << ino))
-               return &p->pbm_B;
-
-       printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps "
-              "PBM_A[%016lx] PBM_B[%016lx]",
-              p->index, ino,
-              p->pbm_A.ino_bitmap,
-              p->pbm_B.ino_bitmap);
-       printk("PCI%d: Using PBM_A, report this problem immediately.\n",
-              p->index);
-
-       return &p->pbm_A;
-}
-
 #define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */
 #define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */
 #define SCHIZO_STC_LINE        0xbb00UL /* --> 0xbb80 */
@@ -522,9 +504,10 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
 
 static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
-       unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       struct pci_controller_info *p = pbm->parent;
+       unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported, limit;
 
@@ -549,28 +532,28 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
        schizo_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PCI%d: Uncorrectable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Uncorrectable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & SCHIZO_UEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & SCHIZO_UEAFSR_PDRD) ?
                  "DMA Read" :
                  ((error_bits & SCHIZO_UEAFSR_PDWR) ?
                   "DMA Write" : "???")))));
-       printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
-              p->index,
+       printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
               (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
               (afsr & SCHIZO_UEAFSR_AID) >> 24UL);
-       printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
-              p->index,
+       printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
               (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
               (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
-       printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar);
-       printk("PCI%d: UE Secondary errors [", p->index);
+       printk("%s: UE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: UE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SCHIZO_UEAFSR_SPIO) {
                reported++;
@@ -610,9 +593,9 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
 
 static irqreturn_t schizo_ce_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
-       unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       unsigned long afsr_reg = pbm->controller_regs + SCHIZO_CE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SCHIZO_CE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported, limit;
 
@@ -637,8 +620,8 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id)
        schizo_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PCI%d: Correctable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Correctable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & SCHIZO_CEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & SCHIZO_CEAFSR_PDRD) ?
@@ -649,20 +632,20 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id)
        /* XXX Use syndrome and afar to print out module string just like
         * XXX UDB CE trap handler does... -DaveM
         */
-       printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
-              p->index,
+       printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
               (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
               (afsr & SCHIZO_UEAFSR_AID) >> 24UL);
-       printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
-              p->index,
+       printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
               (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
               (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
-       printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar);
-       printk("PCI%d: CE Secondary errors [", p->index);
+       printk("%s: CE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: CE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SCHIZO_CEAFSR_SPIO) {
                reported++;
@@ -881,10 +864,10 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
         */
        if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) {
                schizo_check_iommu_error(p, PCI_ERR);
-               pci_scan_for_target_abort(p, pbm, pbm->pci_bus);
+               pci_scan_for_target_abort(pbm, pbm->pci_bus);
        }
        if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA))
-               pci_scan_for_master_abort(p, pbm, pbm->pci_bus);
+               pci_scan_for_master_abort(pbm, pbm->pci_bus);
 
        /* For excessive retries, PSYCHO/PBM will abort the device
         * and there is no way to specifically check for excessive
@@ -894,7 +877,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
         */
 
        if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR))
-               pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
+               pci_scan_for_parity_error(pbm, pbm->pci_bus);
 
        return IRQ_HANDLED;
 }
@@ -940,22 +923,23 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
  */
 static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
+       struct pci_pbm_info *pbm = dev_id;
+       struct pci_controller_info *p = pbm->parent;
        u64 errlog;
 
-       errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG);
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG,
+       errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG);
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG,
                     errlog & ~(SAFARI_ERRLOG_ERROUT));
 
        if (!(errlog & BUS_ERROR_UNMAP)) {
-               printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
-                      p->index, errlog);
+               printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
+                      pbm->name, errlog);
 
                return IRQ_HANDLED;
        }
 
-       printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
-              p->index);
+       printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
+              pbm->name);
        schizo_check_iommu_error(p, SAFARI_ERR);
 
        return IRQ_HANDLED;
@@ -972,6 +956,16 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
 #define SCHIZO_SAFARI_IRQCTRL  0x10010UL
 #define  SCHIZO_SAFIRQCTRL_EN   0x8000000000000000UL
 
+static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino)
+{
+       ino &= IMAP_INO;
+
+       if (pbm->ino_bitmap & (1UL << ino))
+               return 1;
+
+       return 0;
+}
+
 /* How the Tomatillo IRQs are routed around is pure guesswork here.
  *
  * All the Tomatillo devices I see in prtconf dumps seem to have only
@@ -986,11 +980,11 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
  * PCI bus units of the same Tomatillo.  I still have not really
  * figured this out...
  */
-static void tomatillo_register_error_handlers(struct pci_controller_info *p)
+static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm;
-       struct of_device *op;
+       struct of_device *op = of_find_device_by_node(pbm->prom_node);
        u64 tmp, err_mask, err_no_mask;
+       int err;
 
        /* Tomatillo IRQ property layout is:
         * 0: PCIERR
@@ -1000,44 +994,42 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
         * 4: POWER FAIL?
         */
 
-       pbm = pbm_for_ino(p, SCHIZO_UE_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED,
-                           "TOMATILLO_UE", p);
-
-       pbm = pbm_for_ino(p, SCHIZO_CE_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED,
-                           "TOMATILLO CE", p);
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED,
-                           "TOMATILLO PCIERR-A", pbm);
-
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED,
-                           "TOMATILLO PCIERR-B", pbm);
-
-       pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED,
-                           "TOMATILLO SERR", p);
+       if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) {
+               err = request_irq(op->irqs[1], schizo_ue_intr, 0,
+                                 "TOMATILLO_UE", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register UE, "
+                              "err=%d\n", pbm->name, err);
+       }
+       if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) {
+               err = request_irq(op->irqs[2], schizo_ce_intr, 0,
+                                 "TOMATILLO_CE", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register CE, "
+                              "err=%d\n", pbm->name, err);
+       }
+       err = 0;
+       if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) {
+               err = request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                                 "TOMATILLO_PCIERR", pbm);
+       } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) {
+               err = request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                                 "TOMATILLO_PCIERR", pbm);
+       }
+       if (err)
+               printk(KERN_WARNING "%s: Could not register PCIERR, "
+                      "err=%d\n", pbm->name, err);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) {
+               err = request_irq(op->irqs[3], schizo_safarierr_intr, 0,
+                                 "TOMATILLO_SERR", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register SERR, "
+                              "err=%d\n", pbm->name, err);
+       }
 
        /* Enable UE and CE interrupts for controller. */
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
-                    (SCHIZO_ECCCTRL_EE |
-                     SCHIZO_ECCCTRL_UE |
-                     SCHIZO_ECCCTRL_CE));
-
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL,
                     (SCHIZO_ECCCTRL_EE |
                      SCHIZO_ECCCTRL_UE |
                      SCHIZO_ECCCTRL_CE));
@@ -1053,15 +1045,10 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 
        err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
 
-       tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
-       tmp |= err_mask;
-       tmp &= ~err_no_mask;
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
-
-       tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
+       tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
        tmp |= err_mask;
        tmp &= ~err_no_mask;
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
 
        err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
                    SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
@@ -1070,8 +1057,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
                    SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
                    SCHIZO_PCIAFSR_STTO);
 
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask);
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask);
 
        err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR |
                    BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD |
@@ -1083,22 +1069,18 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
                    BUS_ERROR_APERR | BUS_ERROR_UNMAP |
                    BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT);
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
-                    (SCHIZO_SAFERRCTRL_EN | err_mask));
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL,
                     (SCHIZO_SAFERRCTRL_EN | err_mask));
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
-                    (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL,
                     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
-static void schizo_register_error_handlers(struct pci_controller_info *p)
+static void schizo_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm;
-       struct of_device *op;
+       struct of_device *op = of_find_device_by_node(pbm->prom_node);
        u64 tmp, err_mask, err_no_mask;
+       int err;
 
        /* Schizo IRQ property layout is:
         * 0: PCIERR
@@ -1108,39 +1090,42 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
         * 4: POWER FAIL?
         */
 
-       pbm = pbm_for_ino(p, SCHIZO_UE_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED,
-                           "SCHIZO_UE", p);
-
-       pbm = pbm_for_ino(p, SCHIZO_CE_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED,
-                           "SCHIZO CE", p);
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED,
-                           "SCHIZO PCIERR-A", pbm);
-
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED,
-                           "SCHIZO PCIERR-B", pbm);
-
-       pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
-       op = of_find_device_by_node(pbm->prom_node);
-       if (op)
-               request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED,
-                           "SCHIZO SERR", p);
+       if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) {
+               err = request_irq(op->irqs[1], schizo_ue_intr, 0,
+                                 "SCHIZO_UE", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register UE, "
+                              "err=%d\n", pbm->name, err);
+       }
+       if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) {
+               err = request_irq(op->irqs[2], schizo_ce_intr, 0,
+                                 "SCHIZO_CE", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register CE, "
+                              "err=%d\n", pbm->name, err);
+       }
+       err = 0;
+       if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) {
+               err = request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                                 "SCHIZO_PCIERR", pbm);
+       } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) {
+               err = request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                                 "SCHIZO_PCIERR", pbm);
+       }
+       if (err)
+               printk(KERN_WARNING "%s: Could not register PCIERR, "
+                      "err=%d\n", pbm->name, err);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) {
+               err = request_irq(op->irqs[3], schizo_safarierr_intr, 0,
+                                 "SCHIZO_SERR", pbm);
+               if (err)
+                       printk(KERN_WARNING "%s: Could not register SERR, "
+                              "err=%d\n", pbm->name, err);
+       }
 
        /* Enable UE and CE interrupts for controller. */
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL,
                     (SCHIZO_ECCCTRL_EE |
                      SCHIZO_ECCCTRL_UE |
                      SCHIZO_ECCCTRL_CE));
@@ -1159,25 +1144,12 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
        /* Enable PCI Error interrupts and clear error
         * bits for each PBM.
         */
-       tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
-       tmp |= err_mask;
-       tmp &= ~err_no_mask;
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
-
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR,
-                    (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
-                     SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
-                     SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
-                     SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |
-                     SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
-                     SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));
-
-       tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
+       tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
        tmp |= err_mask;
        tmp &= ~err_no_mask;
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
 
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR,
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR,
                     (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
                      SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
                      SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
@@ -1210,11 +1182,8 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
                      BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
 #endif
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL,
                     (SCHIZO_SAFERRCTRL_EN | err_mask));
-
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
-                    (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
 static void pbm_config_busmastering(struct pci_pbm_info *pbm)
@@ -1234,27 +1203,19 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void schizo_scan_bus(struct pci_controller_info *p)
+static void schizo_scan_bus(struct pci_pbm_info *pbm)
 {
-       pbm_config_busmastering(&p->pbm_B);
-       p->pbm_B.is_66mhz_capable =
-               (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
-                != NULL);
-       pbm_config_busmastering(&p->pbm_A);
-       p->pbm_A.is_66mhz_capable =
-               (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
+       pbm_config_busmastering(pbm);
+       pbm->is_66mhz_capable =
+               (of_find_property(pbm->prom_node, "66mhz-capable", NULL)
                 != NULL);
 
-       p->pbm_B.pci_bus = pci_scan_one_pbm(&p->pbm_B);
-       p->pbm_A.pci_bus = pci_scan_one_pbm(&p->pbm_A);
+       pbm->pci_bus = pci_scan_one_pbm(pbm);
 
-       /* After the PCI bus scan is complete, we can register
-        * the error interrupt handlers.
-        */
-       if (p->pbm_B.chip_type == PBM_CHIP_TYPE_TOMATILLO)
-               tomatillo_register_error_handlers(p);
+       if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
+               tomatillo_register_error_handlers(pbm);
        else
-               schizo_register_error_handlers(p);
+               schizo_register_error_handlers(pbm);
 }
 
 #define SCHIZO_STRBUF_CONTROL          (0x02800UL)
@@ -1491,10 +1452,8 @@ static void schizo_pbm_init(struct pci_controller_info *p,
                            int chip_type)
 {
        const struct linux_prom64_registers *regs;
-       const unsigned int *busrange;
        struct pci_pbm_info *pbm;
        const char *chipset_name;
-       const u32 *ino_bitmap;
        int is_pbm_a;
 
        switch (chip_type) {
@@ -1531,6 +1490,14 @@ static void schizo_pbm_init(struct pci_controller_info *p,
        else
                pbm = &p->pbm_B;
 
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
+
+       pbm->scan_bus = schizo_scan_bus;
+       pbm->pci_ops = &schizo_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->portid = portid;
        pbm->parent = p;
        pbm->prom_node = dp;
@@ -1555,13 +1522,7 @@ static void schizo_pbm_init(struct pci_controller_info *p,
 
        pci_determine_mem_io_space(pbm);
 
-       ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
-       pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
-                          ((u64)ino_bitmap[0] <<  0UL));
-
-       busrange = of_get_property(dp, "bus-range", NULL);
-       pbm->pci_first_busno = busrange[0];
-       pbm->pci_last_busno = busrange[1];
+       pci_get_pbm_props(pbm);
 
        schizo_pbm_iommu_init(pbm);
        schizo_pbm_strbuf_init(pbm);
@@ -1580,23 +1541,15 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
 static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
 {
        struct pci_controller_info *p;
+       struct pci_pbm_info *pbm;
        struct iommu *iommu;
        u32 portid;
 
        portid = of_getintprop_default(dp, "portid", 0xff);
 
-       for (p = pci_controller_root; p; p = p->next) {
-               struct pci_pbm_info *pbm;
-
-               if (p->pbm_A.prom_node && p->pbm_B.prom_node)
-                       continue;
-
-               pbm = (p->pbm_A.prom_node ?
-                      &p->pbm_A :
-                      &p->pbm_B);
-
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
                if (portid_compare(pbm->portid, portid, chip_type)) {
-                       schizo_pbm_init(p, dp, portid, chip_type);
+                       schizo_pbm_init(pbm->parent, dp, portid, chip_type);
                        return;
                }
        }
@@ -1617,13 +1570,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
 
        p->pbm_B.iommu = iommu;
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
-
-       p->index = pci_num_controllers++;
-       p->scan_bus = schizo_scan_bus;
-       p->pci_ops = &schizo_ops;
-
        /* Like PSYCHO we have a 2GB aligned area for memory space. */
        pci_memspace_mask = 0x7fffffffUL;
 
index 1ccf4c9a9a4330b4b40cfd21bb50e116ebf744af..0c76a8891a96b270bd8e5ff279134333fbf70823 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/irq.h>
 #include <linux/msi.h>
 
-#include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/upa.h>
@@ -677,29 +676,15 @@ static struct pci_ops pci_sun4v_ops = {
 };
 
 
-static void pbm_scan_bus(struct pci_controller_info *p,
-                        struct pci_pbm_info *pbm)
-{
-       pbm->pci_bus = pci_scan_one_pbm(pbm);
-}
-
-static void pci_sun4v_scan_bus(struct pci_controller_info *p)
+static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
 {
        struct property *prop;
        struct device_node *dp;
 
-       if ((dp = p->pbm_A.prom_node) != NULL) {
-               prop = of_find_property(dp, "66mhz-capable", NULL);
-               p->pbm_A.is_66mhz_capable = (prop != NULL);
-
-               pbm_scan_bus(p, &p->pbm_A);
-       }
-       if ((dp = p->pbm_B.prom_node) != NULL) {
-               prop = of_find_property(dp, "66mhz-capable", NULL);
-               p->pbm_B.is_66mhz_capable = (prop != NULL);
-
-               pbm_scan_bus(p, &p->pbm_B);
-       }
+       dp = pbm->prom_node;
+       prop = of_find_property(dp, "66mhz-capable", NULL);
+       pbm->is_66mhz_capable = (prop != NULL);
+       pbm->pci_bus = pci_scan_one_pbm(pbm);
 
        /* XXX register error interrupt handlers XXX */
 }
@@ -802,20 +787,6 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
                       pbm->name, sz);
 }
 
-static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
-{
-       struct property *prop;
-       unsigned int *busrange;
-
-       prop = of_find_property(pbm->prom_node, "bus-range", NULL);
-
-       busrange = prop->value;
-
-       pbm->pci_first_busno = busrange[0];
-       pbm->pci_last_busno = busrange[1];
-
-}
-
 #ifdef CONFIG_PCI_MSI
 struct pci_sun4v_msiq_entry {
        u64             version_type;
@@ -1019,114 +990,6 @@ h_error:
        return -EINVAL;
 }
 
-static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
-{
-       const u32 *val;
-       int len;
-
-       val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
-       if (!val || len != 4)
-               goto no_msi;
-       pbm->msiq_num = *val;
-       if (pbm->msiq_num) {
-               const struct msiq_prop {
-                       u32 first_msiq;
-                       u32 num_msiq;
-                       u32 first_devino;
-               } *mqp;
-               const struct msi_range_prop {
-                       u32 first_msi;
-                       u32 num_msi;
-               } *mrng;
-               const struct addr_range_prop {
-                       u32 msi32_high;
-                       u32 msi32_low;
-                       u32 msi32_len;
-                       u32 msi64_high;
-                       u32 msi64_low;
-                       u32 msi64_len;
-               } *arng;
-
-               val = of_get_property(pbm->prom_node, "msi-eq-size", &len);
-               if (!val || len != 4)
-                       goto no_msi;
-
-               pbm->msiq_ent_count = *val;
-
-               mqp = of_get_property(pbm->prom_node,
-                                     "msi-eq-to-devino", &len);
-               if (!mqp || len != sizeof(struct msiq_prop))
-                       goto no_msi;
-
-               pbm->msiq_first = mqp->first_msiq;
-               pbm->msiq_first_devino = mqp->first_devino;
-
-               val = of_get_property(pbm->prom_node, "#msi", &len);
-               if (!val || len != 4)
-                       goto no_msi;
-               pbm->msi_num = *val;
-
-               mrng = of_get_property(pbm->prom_node, "msi-ranges", &len);
-               if (!mrng || len != sizeof(struct msi_range_prop))
-                       goto no_msi;
-               pbm->msi_first = mrng->first_msi;
-
-               val = of_get_property(pbm->prom_node, "msi-data-mask", &len);
-               if (!val || len != 4)
-                       goto no_msi;
-               pbm->msi_data_mask = *val;
-
-               val = of_get_property(pbm->prom_node, "msix-data-width", &len);
-               if (!val || len != 4)
-                       goto no_msi;
-               pbm->msix_data_width = *val;
-
-               arng = of_get_property(pbm->prom_node, "msi-address-ranges",
-                                      &len);
-               if (!arng || len != sizeof(struct addr_range_prop))
-                       goto no_msi;
-               pbm->msi32_start = ((u64)arng->msi32_high << 32) |
-                       (u64) arng->msi32_low;
-               pbm->msi64_start = ((u64)arng->msi64_high << 32) |
-                       (u64) arng->msi64_low;
-               pbm->msi32_len = arng->msi32_len;
-               pbm->msi64_len = arng->msi64_len;
-
-               if (msi_bitmap_alloc(pbm))
-                       goto no_msi;
-
-               if (msi_queue_alloc(pbm)) {
-                       msi_bitmap_free(pbm);
-                       goto no_msi;
-               }
-
-               printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] "
-                      "devino[0x%x]\n",
-                      pbm->name,
-                      pbm->msiq_first, pbm->msiq_num,
-                      pbm->msiq_ent_count,
-                      pbm->msiq_first_devino);
-               printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] "
-                      "width[%u]\n",
-                      pbm->name,
-                      pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
-                      pbm->msix_data_width);
-               printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
-                      "addr64[0x%lx:0x%x]\n",
-                      pbm->name,
-                      pbm->msi32_start, pbm->msi32_len,
-                      pbm->msi64_start, pbm->msi64_len);
-               printk(KERN_INFO "%s: MSI queues at RA [%p]\n",
-                      pbm->name,
-                      pbm->msi_queues);
-       }
-
-       return;
-
-no_msi:
-       pbm->msiq_num = 0;
-       printk(KERN_INFO "%s: No MSI support.\n", pbm->name);
-}
 
 static int alloc_msi(struct pci_pbm_info *pbm)
 {
@@ -1245,6 +1108,117 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq,
         */
        sun4v_destroy_msi(virt_irq);
 }
+
+static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
+{
+       const u32 *val;
+       int len;
+
+       val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
+       if (!val || len != 4)
+               goto no_msi;
+       pbm->msiq_num = *val;
+       if (pbm->msiq_num) {
+               const struct msiq_prop {
+                       u32 first_msiq;
+                       u32 num_msiq;
+                       u32 first_devino;
+               } *mqp;
+               const struct msi_range_prop {
+                       u32 first_msi;
+                       u32 num_msi;
+               } *mrng;
+               const struct addr_range_prop {
+                       u32 msi32_high;
+                       u32 msi32_low;
+                       u32 msi32_len;
+                       u32 msi64_high;
+                       u32 msi64_low;
+                       u32 msi64_len;
+               } *arng;
+
+               val = of_get_property(pbm->prom_node, "msi-eq-size", &len);
+               if (!val || len != 4)
+                       goto no_msi;
+
+               pbm->msiq_ent_count = *val;
+
+               mqp = of_get_property(pbm->prom_node,
+                                     "msi-eq-to-devino", &len);
+               if (!mqp || len != sizeof(struct msiq_prop))
+                       goto no_msi;
+
+               pbm->msiq_first = mqp->first_msiq;
+               pbm->msiq_first_devino = mqp->first_devino;
+
+               val = of_get_property(pbm->prom_node, "#msi", &len);
+               if (!val || len != 4)
+                       goto no_msi;
+               pbm->msi_num = *val;
+
+               mrng = of_get_property(pbm->prom_node, "msi-ranges", &len);
+               if (!mrng || len != sizeof(struct msi_range_prop))
+                       goto no_msi;
+               pbm->msi_first = mrng->first_msi;
+
+               val = of_get_property(pbm->prom_node, "msi-data-mask", &len);
+               if (!val || len != 4)
+                       goto no_msi;
+               pbm->msi_data_mask = *val;
+
+               val = of_get_property(pbm->prom_node, "msix-data-width", &len);
+               if (!val || len != 4)
+                       goto no_msi;
+               pbm->msix_data_width = *val;
+
+               arng = of_get_property(pbm->prom_node, "msi-address-ranges",
+                                      &len);
+               if (!arng || len != sizeof(struct addr_range_prop))
+                       goto no_msi;
+               pbm->msi32_start = ((u64)arng->msi32_high << 32) |
+                       (u64) arng->msi32_low;
+               pbm->msi64_start = ((u64)arng->msi64_high << 32) |
+                       (u64) arng->msi64_low;
+               pbm->msi32_len = arng->msi32_len;
+               pbm->msi64_len = arng->msi64_len;
+
+               if (msi_bitmap_alloc(pbm))
+                       goto no_msi;
+
+               if (msi_queue_alloc(pbm)) {
+                       msi_bitmap_free(pbm);
+                       goto no_msi;
+               }
+
+               printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] "
+                      "devino[0x%x]\n",
+                      pbm->name,
+                      pbm->msiq_first, pbm->msiq_num,
+                      pbm->msiq_ent_count,
+                      pbm->msiq_first_devino);
+               printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] "
+                      "width[%u]\n",
+                      pbm->name,
+                      pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
+                      pbm->msix_data_width);
+               printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
+                      "addr64[0x%lx:0x%x]\n",
+                      pbm->name,
+                      pbm->msi32_start, pbm->msi32_len,
+                      pbm->msi64_start, pbm->msi64_len);
+               printk(KERN_INFO "%s: MSI queues at RA [%p]\n",
+                      pbm->name,
+                      pbm->msi_queues);
+       }
+       pbm->setup_msi_irq = pci_sun4v_setup_msi_irq;
+       pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq;
+
+       return;
+
+no_msi:
+       pbm->msiq_num = 0;
+       printk(KERN_INFO "%s: No MSI support.\n", pbm->name);
+}
 #else /* CONFIG_PCI_MSI */
 static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
 {
@@ -1260,6 +1234,14 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
        else
                pbm = &p->pbm_A;
 
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
+
+       pbm->scan_bus = pci_sun4v_scan_bus;
+       pbm->pci_ops = &pci_sun4v_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->parent = p;
        pbm->prom_node = dp;
 
@@ -1271,7 +1253,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
 
        pci_determine_mem_io_space(pbm);
 
-       pci_sun4v_get_bus_range(pbm);
+       pci_get_pbm_props(pbm);
        pci_sun4v_iommu_init(pbm);
        pci_sun4v_msi_init(pbm);
 }
@@ -1279,6 +1261,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
 void sun4v_pci_init(struct device_node *dp, char *model_name)
 {
        struct pci_controller_info *p;
+       struct pci_pbm_info *pbm;
        struct iommu *iommu;
        struct property *prop;
        struct linux_prom64_registers *regs;
@@ -1290,18 +1273,9 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
 
        devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
 
-       for (p = pci_controller_root; p; p = p->next) {
-               struct pci_pbm_info *pbm;
-
-               if (p->pbm_A.prom_node && p->pbm_B.prom_node)
-                       continue;
-
-               pbm = (p->pbm_A.prom_node ?
-                      &p->pbm_A :
-                      &p->pbm_B);
-
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
                if (pbm->devhandle == (devhandle ^ 0x40)) {
-                       pci_sun4v_pbm_init(p, dp, devhandle);
+                       pci_sun4v_pbm_init(pbm->parent, dp, devhandle);
                        return;
                }
        }
@@ -1331,18 +1305,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
 
        p->pbm_B.iommu = iommu;
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
-
-       p->index = pci_num_controllers++;
-
-       p->scan_bus = pci_sun4v_scan_bus;
-#ifdef CONFIG_PCI_MSI
-       p->setup_msi_irq = pci_sun4v_setup_msi_irq;
-       p->teardown_msi_irq = pci_sun4v_teardown_msi_irq;
-#endif
-       p->pci_ops = &pci_sun4v_ops;
-
        /* Like PSYCHO and SCHIZO we have a 2GB aligned area
         * for memory space.
         */
index a114151f9fbe586547f4f7e9a78c9ef1e7092bd0..8e3c6e435110a2ae186f5d02bb5fbe720487e96a 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kallsyms.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
index 3b05428cc9091e00dd2d7f588af3b5082b952e17..91f6e2a74ad5fdc263c94fec5dd41dfb06ea254c 100644 (file)
@@ -1002,24 +1002,24 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
        u64 control;
 
        irq = sbus_build_irq(sbus, SYSIO_UE_INO);
-       if (request_irq(irq, sysio_ue_handler,
-                       IRQF_SHARED, "SYSIO UE", sbus) < 0) {
+       if (request_irq(irq, sysio_ue_handler, 0,
+                       "SYSIO_UE", sbus) < 0) {
                prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n",
                            sbus->portid);
                prom_halt();
        }
 
        irq = sbus_build_irq(sbus, SYSIO_CE_INO);
-       if (request_irq(irq, sysio_ce_handler,
-                       IRQF_SHARED, "SYSIO CE", sbus) < 0) {
+       if (request_irq(irq, sysio_ce_handler, 0,
+                       "SYSIO_CE", sbus) < 0) {
                prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n",
                            sbus->portid);
                prom_halt();
        }
 
        irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO);
-       if (request_irq(irq, sysio_sbus_error_handler,
-                       IRQF_SHARED, "SYSIO SBUS Error", sbus) < 0) {
+       if (request_irq(irq, sysio_sbus_error_handler, 0,
+                       "SYSIO_SBERR", sbus) < 0) {
                prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n",
                            sbus->portid);
                prom_halt();
index 96d56a8410ad23d9ac85389a63783e65aedbffa8..203e87301005c985a95d08208c94def7222d47a2 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/smp_lock.h>
 #include <linux/binfmts.h>
 #include <linux/bitops.h>
 
index c45f21b881d5faffd15afed4cd14a81acfca5e3d..8c1c121330fba5b57687e5e3deca87c9d39ed1d7 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/smp_lock.h>
 #include <linux/binfmts.h>
 #include <linux/compat.h>
 #include <linux/bitops.h>
index 1fac215252e403bc25af1fbc3a58fe88e22e3994..8087d67a0cf8a31f155ae0dd39237e767b62305c 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/pagemap.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
index c4d15f2762b9e37579b73bc3e11e6219682b65b8..47f92a59be18ad41904891f3888974a9df9b08b1 100644 (file)
@@ -3,22 +3,16 @@
 #include <linux/thread_info.h>
 #include <asm/ptrace.h>
 
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
        unsigned long ksp, fp, thread_base;
-       struct thread_info *tp;
+       struct thread_info *tp = task_thread_info(current);
 
-       if (!task)
-               task = current;
-       tp = task_thread_info(task);
-       if (task == current) {
-               flushw_all();
-               __asm__ __volatile__(
-                       "mov    %%fp, %0"
-                       : "=r" (ksp)
-               );
-       } else
-               ksp = tp->ksp;
+       flushw_all();
+       __asm__ __volatile__(
+               "mov    %%fp, %0"
+               : "=r" (ksp)
+       );
 
        fp = ksp + STACK_BIAS;
        thread_base = (unsigned long) tp;
index a05e43d517554b5a81befdef2f074e05283270f4..75d2bad49839284f47600065fc782a149f132d88 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 
index a53d4abb4b49de1193b6a21d1d7e10a96c8eba51..d108eeb0734fe2fe3586d01a8c2e2fdf5aaf25e4 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mman.h>
 #include <linux/utsname.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 #include <linux/ipc.h>
index 7876a02262852399ee3c27efa1d135d366feb528..abd83129b2e73480031791032ea6a698eac26af8 100644 (file)
@@ -775,15 +775,25 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
 asmlinkage long sys32_utimes(char __user *filename,
                             struct compat_timeval __user *tvs)
 {
-       struct timeval ktvs[2];
+       struct timespec tv[2];
 
        if (tvs) {
+               struct timeval ktvs[2];
                if (get_tv32(&ktvs[0], tvs) ||
                    get_tv32(&ktvs[1], 1+tvs))
                        return -EFAULT;
+
+               if (ktvs[0].tv_usec < 0 || ktvs[0].tv_usec >= 1000000 ||
+                   ktvs[1].tv_usec < 0 || ktvs[1].tv_usec >= 1000000)
+                       return -EINVAL;
+
+               tv[0].tv_sec = ktvs[0].tv_sec;
+               tv[0].tv_nsec = 1000 * ktvs[0].tv_usec;
+               tv[1].tv_sec = ktvs[1].tv_sec;
+               tv[1].tv_nsec = 1000 * ktvs[1].tv_usec;
        }
 
-       return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL));
+       return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
 }
 
 /* These are here just in case some old sparc32 binary calls it. */
index 48c36fe6dc624f91a4e85fdbf6129f2da85e4a92..5fe7f9ad4a92c35a92d75c314636a3fbb968a52d 100644 (file)
@@ -81,6 +81,7 @@ sys_call_table32:
        .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
 /*300*/        .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
        .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
+/*310*/        .word compat_sys_utimensat
 
 #endif /* CONFIG_COMPAT */
 
@@ -152,6 +153,7 @@ sys_call_table:
        .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/        .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
        .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+/*310*/        .word sys_utimensat
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -269,5 +271,6 @@ sunos_sys_table:
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys
+/*310*/        .long sunos_nosys
 
 #endif
index ad67784292db6aafe26aedc02e9deb130007da3e..d0fde36395b4a07e9dfa7586b8cc90d8a69bb782 100644 (file)
 #include <linux/kallsyms.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/kdebug.h>
 
+#include <asm/smp.h>
 #include <asm/delay.h>
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/psrcompat.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
-#include <asm/kdebug.h>
 #include <asm/head.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
 #include <asm/prom.h>
 
-ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&sparc64die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&sparc64die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
 
 /* When an irrecoverable trap occurs at tl > 0, the trap entry
  * code logs the trap state registers at every level in the trap
index bc18d480dd1cb958fe4010acef75aa8e8a43a766..953be816fa2564b6692a7f3a25d884337958f017 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/bitops.h>
 #include <linux/kallsyms.h>
 #include <asm/fpumacro.h>
index 55ae802dc0ad6ffd6c06b9bd12e860f9a777267b..b582024d21994498b7959270d5c265e7eac65cdf 100644 (file)
 #include <linux/signal.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kprobes.h>
 #include <linux/kallsyms.h>
+#include <linux/kdebug.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/asi.h>
 #include <asm/lsu.h>
 #include <asm/sections.h>
-#include <asm/kdebug.h>
 #include <asm/mmu_context.h>
 
 #ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
+static inline int notify_page_fault(struct pt_regs *regs)
 {
-       return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
-
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .str = str,
-               .err = err,
-               .trapnr = trap,
-               .signr = sig
-       };
-       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+       int ret = 0;
+
+       /* kprobe_running() needs smp_processor_id() */
+       if (!user_mode(regs)) {
+               preempt_disable();
+               if (kprobe_running() && kprobe_fault_handler(regs, 0))
+                       ret = 1;
+               preempt_enable();
+       }
+       return ret;
 }
 #else
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs)
 {
-       return NOTIFY_DONE;
+       return 0;
 }
 #endif
 
@@ -121,9 +107,6 @@ static void __kprobes unhandled_fault(unsigned long address,
        printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
               (tsk->mm ? (unsigned long) tsk->mm->pgd :
                          (unsigned long) tsk->active_mm->pgd));
-       if (notify_die(DIE_GPF, "general protection fault", regs,
-                      0, 0, SIGSEGV) == NOTIFY_STOP)
-               return;
        die_if_kernel("Oops", regs);
 }
 
@@ -300,8 +283,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 
        fault_code = get_thread_fault_code();
 
-       if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs,
-                      fault_code, 0, SIGSEGV) == NOTIFY_STOP)
+       if (notify_page_fault(regs))
                return;
 
        si_code = SEGV_MAPERR;
index e224a94e6a1b609916f4ad3aa589f7a934f4fff1..eaba9b70b184ef67d47fbf76bdc9d92ea4314754 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 
index 8cef5fd57b2e7a26c2350eeef67d7c3a7477f818..a531a2cdb381e49f15804ce704bc94102bf87ba3 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/shm.h>
index 542c808ec2c83c7b411982610f6e793358105de5..3b67de7455f15c45f53524cc03269e18fa987521 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <linux/module.h> 
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/utsname.h>
 #include <linux/limits.h>
 #include <linux/mm.h>
index 7fa2634e208528bb38eb19dff1176a7228a53e0c..de10c9716cfbd2c369edd7a2dd1dae24ceda5c81 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 
 #include <asm/uaccess.h>
index d3a66ea74a7f1e75a9223c8a5812d6ac6898073e..cc69847cf24071035b28cdd349dd771503f01a0b 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/socket.h>
index c2864447de821d7f52367cf8ef98b9a9caf7f070..e94f6e5d94559c1117f3cb74394f16820ade9a2f 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/ioctl.h>
 #include <linux/fs.h>
 #include <linux/file.h>
index 354cc6b70530c3873e51698845e4a799d437c826..b9c0f307a8fa7ee9b8e866b0416c0764b88d7630 100644 (file)
@@ -320,21 +320,7 @@ source "crypto/Kconfig"
 
 source "lib/Kconfig"
 
-menu "SCSI support"
-depends on BROKEN
-
-config SCSI
-       tristate "SCSI support"
-
-# This gives us free_dma, which scsi.c wants.
-config GENERIC_ISA_DMA
-       bool
-       depends on SCSI
-       default y
-
-source "arch/um/Kconfig.scsi"
-
-endmenu
+source "drivers/scsi/Kconfig"
 
 source "drivers/md/Kconfig"
 
diff --git a/arch/um/Kconfig.scsi b/arch/um/Kconfig.scsi
deleted file mode 100644 (file)
index c291c94..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-comment "SCSI support type (disk, tape, CD-ROM)"
-       depends on SCSI
-
-config BLK_DEV_SD
-       tristate "SCSI disk support"
-       depends on SCSI
-
-config SD_EXTRA_DEVS
-       int "Maximum number of SCSI disks that can be loaded as modules"
-       depends on BLK_DEV_SD
-       default "40"
-
-config CHR_DEV_ST
-       tristate "SCSI tape support"
-       depends on SCSI
-
-config BLK_DEV_SR
-       tristate "SCSI CD-ROM support"
-       depends on SCSI
-
-config BLK_DEV_SR_VENDOR
-       bool "Enable vendor-specific extensions (for SCSI CDROM)"
-       depends on BLK_DEV_SR
-
-config SR_EXTRA_DEVS
-       int "Maximum number of CDROM devices that can be loaded as modules"
-       depends on BLK_DEV_SR
-       default "2"
-
-config CHR_DEV_SG
-       tristate "SCSI generic support"
-       depends on SCSI
-
-comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
-       depends on SCSI
-
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-config SCSI_DEBUG_QUEUES
-       bool "Enable extra checks in new queueing code"
-       depends on SCSI
-
-#fi
-config SCSI_MULTI_LUN
-       bool "Probe all LUNs on each SCSI device"
-       depends on SCSI
-
-config SCSI_CONSTANTS
-       bool "Verbose SCSI error reporting (kernel size +=12K)"
-       depends on SCSI
-
-config SCSI_LOGGING
-       bool "SCSI logging facility"
-       depends on SCSI
-
-config SCSI_DEBUG
-       tristate "SCSI debugging host simulator (EXPERIMENTAL)"
-       depends on SCSI
-
index baac4ad5e68eda7916ead4c014e5872226e803fd..72773dd5442570071a5185405411b9f39cdf35be 100644 (file)
@@ -316,12 +316,14 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
        }
        if (!is_local_ether_addr(addr)) {
                printk(KERN_WARNING
-                      "Warning: attempt to assign a globally valid ethernet address to a "
-                      "device\n");
-               printk(KERN_WARNING "You should better enable the 2nd rightmost bit "
-                     "in the first byte of the MAC, i.e. "
-                     "%02x:%02x:%02x:%02x:%02x:%02x\n",
-                     addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]);
+                      "Warning: attempt to assign a globally valid ethernet "
+                      "address to a device\n");
+               printk(KERN_WARNING "You should better enable the 2nd "
+                      "rightmost bit in the first byte of the MAC,\n");
+               printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
+                      addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
+                      addr[5]);
+               goto random;
        }
        return;
 
@@ -478,6 +480,7 @@ out_undo_user_init:
                (*transport->user->remove)(&lp->user);
 out_unregister:
        platform_device_unregister(&device->pdev);
+       return; /* platform_device_unregister frees dev and device */
 out_free_netdev:
        free_netdev(dev);
 out_free_device:
index 948849343ca421f9ba81c5fc7c8c2e0c1e2bb461..c329931673d6a2ed8ebd68d3f438125bebc588f7 100644 (file)
@@ -29,21 +29,25 @@ void pcap_init(struct net_device *dev, void *data)
        ppri->promisc = init->promisc;
        ppri->optimize = init->optimize;
        ppri->filter = init->filter;
+
+       printk("pcap backend, host interface %s\n", ppri->host_if);
 }
 
-static int pcap_read(int fd, struct sk_buff **skb, 
+static int pcap_read(int fd, struct sk_buff **skb,
                       struct uml_net_private *lp)
 {
        *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-       if(*skb == NULL) return(-ENOMEM);
-       return(pcap_user_read(fd, skb_mac_header(*skb),
+       if(*skb == NULL)
+               return -ENOMEM;
+
+       return pcap_user_read(fd, skb_mac_header(*skb),
                              (*skb)->dev->mtu + ETH_HEADER_OTHER,
-                             (struct pcap_data *) &lp->user));
+                             (struct pcap_data *) &lp->user);
 }
 
 static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
 {
-       return(-EPERM);
+       return -EPERM;
 }
 
 static const struct net_kern_info pcap_kern_info = {
@@ -65,12 +69,12 @@ int pcap_setup(char *str, char **mac_out, void *data)
                  .optimize     = 0,
                  .filter       = NULL });
 
-       remain = split_if_spec(str, &host_if, &init->filter, 
-                              &options[0], &options[1], NULL);
+       remain = split_if_spec(str, &host_if, &init->filter,
+                              &options[0], &options[1], mac_out, NULL);
        if(remain != NULL){
                printk(KERN_ERR "pcap_setup - Extra garbage on "
                       "specification : '%s'\n", remain);
-               return(0);
+               return 0;
        }
 
        if(host_if != NULL)
@@ -87,10 +91,13 @@ int pcap_setup(char *str, char **mac_out, void *data)
                        init->optimize = 1;
                else if(!strcmp(options[i], "nooptimize"))
                        init->optimize = 0;
-               else printk("pcap_setup : bad option - '%s'\n", options[i]);
+               else {
+                       printk("pcap_setup : bad option - '%s'\n", options[i]);
+                       return 0;
+               }
        }
 
-       return(1);
+       return 1;
 }
 
 static struct transport pcap_transport = {
index dc0a903ef9a6fa547032bc1d7bbdfb70c7c3013f..483aa15222a4b71976c29358f0fb61ee6a90e65a 100644 (file)
@@ -13,6 +13,7 @@
 #include "pcap_user.h"
 #include "user.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
@@ -26,8 +27,8 @@ static int pcap_user_init(void *data, void *dev)
 
        p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
        if(p == NULL){
-               printk("pcap_user_init : pcap_open_live failed - '%s'\n", 
-                      errors);
+               printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - "
+                      "'%s'\n", errors);
                return -EINVAL;
        }
 
@@ -48,13 +49,13 @@ static int pcap_open(void *data)
        if(pri->filter != NULL){
                err = dev_netmask(pri->dev, &netmask);
                if(err < 0){
-                       printk("pcap_open : dev_netmask failed\n");
+                       printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
                        return -EIO;
                }
 
                pri->compiled = um_kmalloc(sizeof(struct bpf_program));
                if(pri->compiled == NULL){
-                       printk("pcap_open : kmalloc failed\n");
+                       printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
                        return -ENOMEM;
                }
 
@@ -62,15 +63,15 @@ static int pcap_open(void *data)
                                   (struct bpf_program *) pri->compiled, 
                                   pri->filter, pri->optimize, netmask);
                if(err < 0){
-                       printk("pcap_open : pcap_compile failed - '%s'\n", 
-                              pcap_geterr(pri->pcap));
+                       printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
+                              "'%s'\n", pcap_geterr(pri->pcap));
                        return -EIO;
                }
 
                err = pcap_setfilter(pri->pcap, pri->compiled);
                if(err < 0){
-                       printk("pcap_open : pcap_setfilter failed - '%s'\n", 
-                              pcap_geterr(pri->pcap));
+                       printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
+                              "failed - '%s'\n", pcap_geterr(pri->pcap));
                        return -EIO;
                }
        }
@@ -85,7 +86,8 @@ static void pcap_remove(void *data)
        if(pri->compiled != NULL)
                pcap_freecode(pri->compiled);
 
-       pcap_close(pri->pcap);
+       if(pri->pcap != NULL)
+               pcap_close(pri->pcap);
 }
 
 struct pcap_handler_data {
@@ -114,7 +116,8 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
 
        n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
        if(n < 0){
-               printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
+               printk(UM_KERN_ERR "pcap_dispatch failed - %s\n",
+                      pcap_geterr(pri->pcap));
                return -EIO;
        }
        else if(n == 0) 
index 11bafab669e942b517e403b13cb966eb2c9242b0..0f312085ce1d26ce7bec6b890d646f4f0194fc14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/i386/include/klibc/archsetjmp.h
+ * arch/um/include/sysdep-i386/archsetjmp.h
  */
 
 #ifndef _KLIBC_ARCHSETJMP_H
index 9a5e1a6ec80042095b5f3562d2c2107e85431508..2af8f12ca16169a8f78f2a1d0b138bd563f98334 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/x86_64/include/klibc/archsetjmp.h
+ * arch/um/include/sysdep-x86_64/archsetjmp.h
  */
 
 #ifndef _KLIBC_ARCHSETJMP_H
index ef36facd8fe9a7ff814c81dd1f3976ba3054e019..a96ae1a0610e169a20ae953a1ab070a4fa8eac0c 100644 (file)
@@ -178,20 +178,23 @@ int start_uml_skas(void)
 
 int external_pid_skas(struct task_struct *task)
 {
-#warning Need to look up userspace_pid by cpu
+       /* FIXME: Need to look up userspace_pid by cpu */
        return(userspace_pid[0]);
 }
 
 int thread_pid_skas(struct task_struct *task)
 {
-#warning Need to look up userspace_pid by cpu
+       /* FIXME: Need to look up userspace_pid by cpu */
        return(userspace_pid[0]);
 }
 
 void kill_off_processes_skas(void)
 {
        if(proc_mm)
-#warning need to loop over userspace_pids in kill_off_processes_skas
+               /*
+                * FIXME: need to loop over userspace_pids in
+                * kill_off_processes_skas
+                */
                os_kill_ptraced_process(userspace_pid[0], 1);
        else {
                struct task_struct *p;
index cd7349de8ca63b9f2435895bd3c71e7baf1cbbe6..259c49da7ff501fd4eca0761deb1b45277172a77 100644 (file)
@@ -177,6 +177,8 @@ int do_settimeofday(struct timespec *tv)
 
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
+       if(current_thread->cpu == 0)
+               timer_irq(regs);
        local_irq_disable();
        irq_enter();
        update_process_times(CHOOSE_MODE(
@@ -184,6 +186,4 @@ void timer_handler(int sig, union uml_pt_regs *regs)
                             (regs)->skas.is_user));
        irq_exit();
        local_irq_enable();
-       if(current_thread->cpu == 0)
-               timer_irq(regs);
 }
index 92a7b59120d616692021376bea33ff5226053b04..2d9d2ca39299f2e74ee2be3a47daf0d877d213e8 100644 (file)
@@ -239,6 +239,7 @@ out:
        return ok;
 }
 
+#ifdef UML_CONFIG_MODE_TT
 void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
 {
        int flags = 0, pages;
@@ -260,6 +261,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
                              "errno = %d\n", errno);
        }
 }
+#endif
 
 void init_new_thread_signals(void)
 {
index 8e490fff3d476a5c54fc49adc17e94b327d6f53e..5c89463207996a60e942366f561a7fb2f2273f82 100644 (file)
@@ -68,7 +68,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
        int err, pid = mm_idp->u.pid;
 
        if(proc_mm)
-#warning Need to look up userspace_pid by cpu
+               /* FIXME: Need to look up userspace_pid by cpu */
                pid = userspace_pid[0];
 
        multi_count++;
index 5c088a55396ce3a0b5fbe97f40499cdd9362c7d6..6a0e466d01e33052a2ba2b2a27ed8f9d42ac8cb2 100644 (file)
@@ -586,7 +586,7 @@ void switch_mm_skas(struct mm_id *mm_idp)
 {
        int err;
 
-#warning need cpu pid in switch_mm_skas
+       /* FIXME: need cpu pid in switch_mm_skas */
        if(proc_mm){
                err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
                             mm_idp->u.mm_fd);
index 24f291369070dc7511f011b10c813f337b8b7b7b..cee5c3142d41c41644341e62a5acb86f6247aa9b 100644 (file)
@@ -29,7 +29,7 @@ int main (void)
        DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
        DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
        DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
-       DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+       DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack));
        DEFINE (TASK_MM, offsetof (struct task_struct, mm));
        DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
        DEFINE (TASK_PID, offsetof (struct task_struct, pid));
index 8bc521ca081f9a32fec0d51d12e8ef4f1044f8c3..e4327a8d6bcd0eb28244097c24f14a98638239d5 100644 (file)
@@ -523,7 +523,7 @@ END(ret_from_trap)
 
 
 /* This the initial entry point for a new child thread, with an appropriate
-   stack in place that makes it look the the child is in the middle of an
+   stack in place that makes it look that the child is in the middle of an
    syscall.  This function is actually `returned to' from switch_thread
    (copy_thread makes ret_from_fork the return address in each new thread's
    saved context).  */
index c4f844c86e50eb3ed97fc72f8210d4639bd540f0..e4a4b8e7d5a3e3b664e99f9b4034c22b09c6204a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
index 67e057509664a89daa48936f1741ad711464f89c..a9b09343097d18442c511439737a69ca708280bf 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 
index 17c2d4359b048be7927410674074b623aed702f0..bf166e7e762cf505793b8cf13b170e3ab30c3ac2 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index d2b1fb19d24313d22896da6d72c710113ddaf9ef..f9f00ccf53245e4aa4e0fe36b833e3fc5b69fed4 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
index 359eacc385094f76e4cc7d6eff8c288bda6ff4f6..6ea19c25f90d46ce209c646382443c5a8ae0e46e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index c48087db6f7554de153344fca51acd453ec2ea07..f21068378272f0b8dbce0ce1d7f8b29ccfa0b286 100644 (file)
@@ -710,9 +710,10 @@ ia32_sys_call_table:
        .quad compat_sys_get_robust_list
        .quad sys_splice
        .quad sys_sync_file_range
-       .quad sys_tee
+       .quad sys_tee                   /* 315 */
        .quad compat_sys_vmsplice
        .quad compat_sys_move_pages
        .quad sys_getcpu
        .quad sys_epoll_pwait
+       .quad compat_sys_utimensat      /* 320 */
 ia32_syscall_end:              
index 4d94c51803d8051e6c3db0dc790ee51957b1f62c..de1de8a2fd84669e4643585e5119fa7d2e2db594 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
 obj-$(CONFIG_IOMMU)            += pci-gart.o aperture.o
 obj-$(CONFIG_CALGARY_IOMMU)    += pci-calgary.o tce.o
 obj-$(CONFIG_SWIOTLB)          += pci-swiotlb.o
+obj-$(CONFIG_SERIAL_8250)      += legacy_serial.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
 obj-$(CONFIG_X86_PM_TIMER)     += pmtimer.o
 obj-$(CONFIG_X86_VSMP)         += vsmp.o
@@ -49,6 +50,7 @@ CFLAGS_vsyscall.o             := $(PROFILING) -g0
 
 therm_throt-y                   += ../../i386/kernel/cpu/mcheck/therm_throt.o
 bootflag-y                     += ../../i386/kernel/bootflag.o
+legacy_serial-y                        += ../../i386/kernel/legacy_serial.o
 cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
 topology-y                     += ../../i386/kernel/topology.o
 microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
index d198f7d82e5a429710a98ed1e3e409534e1ecf60..1b0e07bb87289cc5248fd9ecb7cde2338fcf6887 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
index 95a7a2c13131d0f9c99818f8859fb792eabb57c6..13432a1ae904c465303ddc492f06d97577d749d6 100644 (file)
 #include <linux/delay.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
+#include <linux/kdebug.h>
 
 #include <asm/processor.h>
 #include <asm/hardirq.h>
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
 #include <asm/mach_apic.h>
-#include <asm/kdebug.h>
 
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
index 92213d2b7c110ef070edfdb14313e6fc2c9ad2cd..56eaa259782b9e19dd6d6a1cd2b8dae9aabde887 100644 (file)
@@ -243,22 +243,12 @@ static int __init setup_early_printk(char *buf)
                early_console = &simnow_console;
                keep_early = 1;
        }
+
+       if (keep_early)
+               early_console->flags &= ~CON_BOOT;
+       else
+               early_console->flags |= CON_BOOT;
        register_console(early_console);
        return 0;
 }
-
 early_param("earlyprintk", setup_early_printk);
-
-void __init disable_early_printk(void)
-{
-       if (!early_console_initialized || !early_console)
-               return;
-       if (!keep_early) {
-               printk("disabling early console\n");
-               unregister_console(early_console);
-               early_console_initialized = 0;
-       } else {
-               printk("keeping early console\n");
-       }
-}
-
index 48942668277291ec8d25e1f01284295cff313bf6..4b326655b2084a736272f1adb546ac5247d87863 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
index 2a2df14dab7eabaa9436e54da23643ffb7c9c4ad..d8bfe315471cfdf6d3a078fd4a72bd014f03acca 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
@@ -1414,7 +1413,7 @@ static void ack_apic_level(unsigned int irq)
 
        /*
         * We must acknowledge the irq before we move it or the acknowledge will
-        * not propogate properly.
+        * not propagate properly.
         */
        ack_APIC_irq();
 
index 387d347b0e07ec4f69c8d1bed894eaf5c9bc8b26..653efa30b0f4107dd1878dcf73a9e97af7e36724 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
index 3bc30d2c13d3289809cd538f07cef4fc8033c0dc..3eaceac3248140ae85d6643dae9f61cb3a01a8a0 100644 (file)
@@ -32,7 +32,7 @@ atomic_t irq_err_count;
  */
 static inline void stack_overflow_check(struct pt_regs *regs)
 {
-       u64 curbase = (u64) current->thread_info;
+       u64 curbase = (u64)task_stack_page(current);
        static unsigned long warned = -60*HZ;
 
        if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
index 209c8c0bec717c226f9338faced9ac243b7904c9..d4a0d0ac99351a8fd1b67ca9f65fa6aa01861b9b 100644 (file)
 #include <linux/slab.h>
 #include <linux/preempt.h>
 #include <linux/module.h>
+#include <linux/kdebug.h>
 
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
-#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 
 void jprobe_return_end(void);
@@ -266,23 +266,14 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 }
 
 /* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
        unsigned long *sara = (unsigned long *)regs->rsp;
-       struct kretprobe_instance *ri;
 
-       if ((ri = get_free_rp_inst(rp)) != NULL) {
-               ri->rp = rp;
-               ri->task = current;
-               ri->ret_addr = (kprobe_opcode_t *) *sara;
-
-               /* Replace the return addr with trampoline addr */
-               *sara = (unsigned long) &kretprobe_trampoline;
-               add_rp_inst(ri);
-       } else {
-               rp->nmissed++;
-       }
+       ri->ret_addr = (kprobe_opcode_t *) *sara;
+       /* Replace the return addr with trampoline addr */
+       *sara = (unsigned long) &kretprobe_trampoline;
 }
 
 int __kprobes kprobe_handler(struct pt_regs *regs)
@@ -447,7 +438,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
                        break;
        }
 
-       BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
        regs->rip = orig_ret_address;
 
        reset_current_kprobe();
@@ -752,3 +743,11 @@ int __init arch_init_kprobes(void)
 {
        return register_kprobe(&trampoline_p);
 }
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)
+               return 1;
+
+       return 0;
+}
index d7e5d0cf4285f0ce4326c139e526536a00af1ef6..bc9ffd5c19cc6d19f628cd8e70c8b0390da2a642 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 
index fa26726824775e774682476f072836e5a29cb691..a14375dd54252d1ca6405e1f28a4e7246ae3cbbe 100644 (file)
 #include <linux/percpu.h>
 #include <linux/ctype.h>
 #include <linux/kmod.h>
+#include <linux/kdebug.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
-#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 #include <asm/smp.h>
 
@@ -720,9 +720,11 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                mce_create_device(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                mce_remove_device(cpu);
                break;
        }
index d0bd5d66e103d8d491dc728cb06a82dec86425ba..03356e64f9c8cde580f27075e00451440d2751e3 100644 (file)
@@ -654,9 +654,11 @@ static int threshold_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                threshold_create_device(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                threshold_remove_device(cpu);
                break;
        default:
index d0dc4891599b8e6e0d25501f6abb7ab9de065120..61ae57eb9e4ca4a526bcb8e82db6cfa373b75022 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
index 6cd2b30e2ffc58b516d1de08634b930ae24113e1..931c64bad5e6453493d02eb30f591a3fad991384 100644 (file)
 #include <linux/sysctl.h>
 #include <linux/kprobes.h>
 #include <linux/cpumask.h>
+#include <linux/kdebug.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
 #include <asm/proto.h>
-#include <asm/kdebug.h>
 #include <asm/mce.h>
 
 int unknown_nmi_panic;
index 0a762e10f2be890b20c4350c11ebe53927df4b9b..373ef66ca1dcff5cb2a43ee19219189850695fba 100644 (file)
 #include <linux/topology.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/kdebug.h>
 #include <asm/atomic.h>
 #include <asm/io.h>
 #include <asm/mtrr.h>
 #include <asm/pgtable.h>
 #include <asm/proto.h>
 #include <asm/cacheflush.h>
-#include <asm/kdebug.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
 #include <asm/k8.h>
index 4f21765078b7a1520aceb07be78095e76b525f3e..5909039f37aa01132d9f752168be82078a540daf 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/random.h>
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -46,7 +47,6 @@
 #include <asm/mmu_context.h>
 #include <asm/pda.h>
 #include <asm/prctl.h>
-#include <asm/kdebug.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/ia32.h>
index 4326a690a509a14ae2c5c4d2980233a82864eebc..9409117b9f1901c357a1e47c75909e8fa146d34e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 2d67698474564cf70f43e6121fa8a7941cbf23f2..c116b54d422e3eb8c7d743c7d33a099b6b082808 100644 (file)
@@ -7,8 +7,8 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/pm.h>
+#include <linux/kdebug.h>
 #include <asm/io.h>
-#include <asm/kdebug.h>
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
 #include <asm/system.h>
index c819625f3316519f79dbca396a6ffe6bfa117035..290f5d8037cd804e6fedbc9e1b7b602e5db10b58 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index bd1d123947ce9662f363f5e6d551d468361db49e..2ff46859162516f99412d450034d9f2614621edd 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/smp.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
index 4d9dacfae5758eb4797d33df5af6e25346e06cac..32f50783edc812e4d5d6618bb754d2051d3cea38 100644 (file)
 
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
 #include <linux/smp.h>
+#include <linux/kdebug.h>
 
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
 #include <asm/desc.h>
-#include <asm/kdebug.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
index 65ac2c6b34a6a1f80c9be549572e1d2f2e1d102e..cb910911358407583ae5d2babf847f743f4a0882 100644 (file)
@@ -21,8 +21,7 @@ save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
 
 static int save_stack_stack(void *data, char *name)
 {
-       struct stack_trace *trace = (struct stack_trace *)data;
-       return trace->all_contexts ? 0 : -1;
+       return -1;
 }
 
 static void save_stack_address(void *data, unsigned long addr)
@@ -46,11 +45,10 @@ static struct stacktrace_ops save_stack_ops = {
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
-       dump_trace(task, NULL, NULL, &save_stack_ops, trace);
+       dump_trace(current, NULL, NULL, &save_stack_ops, trace);
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL(save_stack_trace);
-
index f891931eb753d74d6d8b563faf448fb0edd5e0ba..d067d9a2ad27bd27cf2fdc108bd64de77c26a8a6 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 0652e173813b82f6a7b99c4f1f8a41d5a6e085f3..4a0895bacf5166197b0054706c7830bfe2bdf522 100644 (file)
@@ -363,7 +363,10 @@ void stop_timer_interrupt(void)
 }
 
 static struct irqaction irq0 = {
-       timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_IRQPOLL,
+       .mask           = CPU_MASK_NONE,
+       .name           = "timer"
 };
 
 void __init time_init(void)
index d76fc32d45992f7a2fba66d7d607087190a644d6..8c2ac41187c126aeef9bc0535b3f58d5c3332b3b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/unwind.h>
 #include <linux/uaccess.h>
 #include <linux/bug.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -39,7 +40,6 @@
 #include <asm/debugreg.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
-#include <asm/kdebug.h>
 #include <asm/processor.h>
 #include <asm/unwind.h>
 #include <asm/smp.h>
@@ -71,22 +71,6 @@ asmlinkage void alignment_check(void);
 asmlinkage void machine_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 
-ATOMIC_NOTIFIER_HEAD(die_chain);
-EXPORT_SYMBOL(die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       vmalloc_sync_all();
-       return atomic_notifier_chain_register(&die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
-
 static inline void conditional_sti(struct pt_regs *regs)
 {
        if (regs->eflags & X86_EFLAGS_IF)
@@ -792,6 +776,8 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
                 */
                if (nmi_watchdog_tick(regs,reason))
                        return;
+               if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0)
+                                                               == NOTIFY_STOP)
                if (!do_nmi_callback(regs,cpu))
                        unknown_nmi_error(reason, regs);
 
index dc32cef961950915fbaa185e36ab802d5f7cea3b..51d4c6fa88c8785776354ae0ca115fc46176b7b4 100644 (file)
@@ -327,7 +327,7 @@ static int __cpuinit
 cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
 {
        long cpu = (long)arg;
-       if (action == CPU_ONLINE)
+       if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
                smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
        return NOTIFY_DONE;
 }
index de99dba2c515503f716501aafd9f0eab57ed0142..bfb62a13d7eee005f2b364b159b21096e811ae53 100644 (file)
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/compiler.h>
+#include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
-#include <asm/kdebug.h>
 #include <asm-generic/sections.h>
 
 /* Page fault error code bits */
index c0822683b916215e8fe14b4c544dc6f05870e5d9..1336da8bdee125f5b0ba227360d89c4709264323 100644 (file)
@@ -172,7 +172,7 @@ __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
        set_pte_phys(address, phys, prot);
 }
 
-unsigned long __initdata table_start, table_end; 
+unsigned long __meminitdata table_start, table_end;
 
 static __meminit void *alloc_low_page(unsigned long *phys)
 { 
@@ -204,7 +204,7 @@ static __meminit void unmap_low_page(void *adr)
 } 
 
 /* Must run before zap_low_mappings */
-__init void *early_ioremap(unsigned long addr, unsigned long size)
+__meminit void *early_ioremap(unsigned long addr, unsigned long size)
 {
        unsigned long vaddr;
        pmd_t *pmd, *last_pmd;
@@ -233,7 +233,7 @@ __init void *early_ioremap(unsigned long addr, unsigned long size)
 }
 
 /* To avoid virtual aliases later */
-__init void early_iounmap(void *addr, unsigned long size)
+__meminit void early_iounmap(void *addr, unsigned long size)
 {
        unsigned long vaddr;
        pmd_t *pmd;
index b256cfbef3447bfcc647904e7ccc1c6cdd123f21..698079b3a3368f86735a584daa26384456d11dc1 100644 (file)
@@ -70,7 +70,7 @@ int main(void)
        DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
        DEFINE(TASK_PID, offsetof (struct task_struct, pid));
        DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+       DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack));
        DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
        BLANK();
 
index ca76f071666e895aea125f3927d07bcb385fdcd7..f5319d78c876135326374c530f7f85f13f961d72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/xtensa/pci-dma.c
+ * arch/xtensa/kernel/pci-dma.c
  *
  * DMA coherent memory allocation.
  *
index 795bd5ac6f4cf02f047a3971524685dd98224b33..ce758bab95b121982e45034f0dc2094ab11c74e3 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
index 8b6d3d0623b6f56d4570d9d866c33e38c8f65896..14104ff630930a2f098017818bee98fbbc92069a 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/signal.h>
 
index c6d9880a4cdbf75fcd6c813a92b68ad9c2531d2d..58107672a619eeebf783b8249658bfc6396274ed 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index ef126277b4b334a551929ad27116290fc5b5d22f..109e91b91ffaa403dcb56e828798d923ebec0a50 100644 (file)
@@ -569,7 +569,7 @@ static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
 static int as_close_req(struct as_data *ad, struct as_io_context *aic,
                        struct request *rq)
 {
-       unsigned long delay;    /* milliseconds */
+       unsigned long delay;    /* jiffies */
        sector_t last = ad->last_sector[ad->batch_data_dir];
        sector_t next = rq->sector;
        sector_t delta; /* acceptable close offset (in sectors) */
@@ -578,11 +578,11 @@ static int as_close_req(struct as_data *ad, struct as_io_context *aic,
        if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished)
                delay = 0;
        else
-               delay = ((jiffies - ad->antic_start) * 1000) / HZ;
+               delay = jiffies - ad->antic_start;
 
        if (delay == 0)
                delta = 8192;
-       else if (delay <= 20 && delay <= ad->antic_expire)
+       else if (delay <= (20 * HZ / 1000) && delay <= ad->antic_expire)
                delta = 8192 << delay;
        else
                return 1;
@@ -1306,7 +1306,7 @@ static void as_exit_queue(elevator_t *e)
        struct as_data *ad = e->elevator_data;
 
        del_timer_sync(&ad->antic_timer);
-       kblockd_flush();
+       kblockd_flush_work(&ad->antic_work);
 
        BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC]));
        BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC]));
index b5664440896c654f848c524409f5ba8a4255cae7..93a2cf654597c25502da7fb128745c11c01581c9 100644 (file)
@@ -213,6 +213,59 @@ struct gendisk *get_gendisk(dev_t dev, int *part)
        return  kobj ? to_disk(kobj) : NULL;
 }
 
+/*
+ * print a full list of all partitions - intended for places where the root
+ * filesystem can't be mounted and thus to give the victim some idea of what
+ * went wrong
+ */
+void __init printk_all_partitions(void)
+{
+       int n;
+       struct gendisk *sgp;
+
+       mutex_lock(&block_subsys_lock);
+       /* For each block device... */
+       list_for_each_entry(sgp, &block_subsys.list, kobj.entry) {
+               char buf[BDEVNAME_SIZE];
+               /*
+                * Don't show empty devices or things that have been surpressed
+                */
+               if (get_capacity(sgp) == 0 ||
+                   (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
+                       continue;
+
+               /*
+                * Note, unlike /proc/partitions, I am showing the numbers in
+                * hex - the same format as the root= option takes.
+                */
+               printk("%02x%02x %10llu %s",
+                       sgp->major, sgp->first_minor,
+                       (unsigned long long)get_capacity(sgp) >> 1,
+                       disk_name(sgp, 0, buf));
+               if (sgp->driverfs_dev != NULL &&
+                   sgp->driverfs_dev->driver != NULL)
+                       printk(" driver: %s\n",
+                               sgp->driverfs_dev->driver->name);
+               else
+                       printk(" (driver?)\n");
+
+               /* now show the partitions */
+               for (n = 0; n < sgp->minors - 1; ++n) {
+                       if (sgp->part[n] == NULL)
+                               continue;
+                       if (sgp->part[n]->nr_sects == 0)
+                               continue;
+                       printk("  %02x%02x %10llu %s\n",
+                               sgp->major, n + 1 + sgp->first_minor,
+                               (unsigned long long)sgp->part[n]->nr_sects >> 1,
+                               disk_name(sgp, n + 1, buf));
+               } /* partition subloop */
+       } /* Block device loop */
+
+       mutex_unlock(&block_subsys_lock);
+       return;
+}
+
 #ifdef CONFIG_PROC_FS
 /* iterator */
 static void *part_start(struct seq_file *part, loff_t *pos)
index 5873861e1dbbfa6eb5b808a77f0d4c2771ed0c33..17e18897342841887ec25b45585cfe49478bf77a 100644 (file)
@@ -1704,7 +1704,7 @@ EXPORT_SYMBOL(blk_stop_queue);
  *     on a queue, such as calling the unplug function after a timeout.
  *     A block device may call blk_sync_queue to ensure that any
  *     such activity is cancelled, thus allowing it to release resources
- *     the the callbacks might use. The caller must already have made sure
+ *     that the callbacks might use. The caller must already have made sure
  *     that its ->make_request_fn will not re-add plugging prior to calling
  *     this function.
  *
@@ -1712,7 +1712,6 @@ EXPORT_SYMBOL(blk_stop_queue);
 void blk_sync_queue(struct request_queue *q)
 {
        del_timer_sync(&q->unplug_timer);
-       kblockd_flush();
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
@@ -2558,6 +2557,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
                bio->bi_rw |= (1 << BIO_RW);
 
        blk_rq_bio_prep(q, rq, bio);
+       blk_queue_bounce(q, &rq->bio);
        rq->buffer = rq->data = NULL;
        return 0;
 }
@@ -3507,7 +3507,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
         * If a CPU goes away, splice its entries to the current CPU
         * and trigger a run of the softirq
         */
-       if (action == CPU_DEAD) {
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
                int cpu = (unsigned long) hcpu;
 
                local_irq_disable();
@@ -3631,11 +3631,11 @@ int kblockd_schedule_work(struct work_struct *work)
 
 EXPORT_SYMBOL(kblockd_schedule_work);
 
-void kblockd_flush(void)
+void kblockd_flush_work(struct work_struct *work)
 {
-       flush_workqueue(kblockd_workqueue);
+       cancel_work_sync(work);
 }
-EXPORT_SYMBOL(kblockd_flush);
+EXPORT_SYMBOL(kblockd_flush_work);
 
 int __init blk_dev_init(void)
 {
index 620e14cabdc605ab0bfb9167758dbd2ca1b09ce6..4ca0ab3448d9f3887cd3c64594f0006c71194dfd 100644 (file)
@@ -271,7 +271,7 @@ config CRYPTO_SERPENT
 
          Keys are allowed to be from 0 to 256 bits in length, in steps
          of 8 bits.  Also includes the 'Tnepres' algorithm, a reversed
-         variant of Serpent for compatibility with old kerneli code.
+         variant of Serpent for compatibility with old kerneli.org code.
 
          See also:
          <http://www.cl.cam.ac.uk/~rja14/serpent.html>
index 6958ea83ee440e9f3425fd2aa0ff301f24ff1866..e5fb7cca5107d742ccd999bc87eaaf024a204f07 100644 (file)
@@ -24,8 +24,6 @@
 #include "internal.h"
 
 struct cryptomgr_param {
-       struct task_struct *thread;
-
        struct rtattr *tb[CRYPTOA_MAX];
 
        struct {
@@ -81,6 +79,7 @@ err:
 
 static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 {
+       struct task_struct *thread;
        struct cryptomgr_param *param;
        const char *name = larval->alg.cra_name;
        const char *p;
@@ -130,8 +129,8 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 
        memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
 
-       param->thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
-       if (IS_ERR(param->thread))
+       thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
+       if (IS_ERR(thread))
                goto err_free_param;
 
        return NOTIFY_STOP;
index 4334c208841a3f06586ba3693b10d8437fff5b12..41427a41f6201fbcad4c8b7bcbaaa62228e21ed3 100644 (file)
@@ -245,6 +245,35 @@ arch_initcall(init_acpi_device_notify);
 
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 
+#ifdef CONFIG_PM
+static u32 rtc_handler(void *context)
+{
+       acpi_clear_event(ACPI_EVENT_RTC);
+       acpi_disable_event(ACPI_EVENT_RTC, 0);
+       return ACPI_INTERRUPT_HANDLED;
+}
+
+static inline void rtc_wake_setup(void)
+{
+       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+}
+
+static void rtc_wake_on(struct device *dev)
+{
+       acpi_clear_event(ACPI_EVENT_RTC);
+       acpi_enable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+       acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+#else
+#define rtc_wake_setup()       do{}while(0)
+#define rtc_wake_on            NULL
+#define rtc_wake_off           NULL
+#endif
+
 /* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
  * its device node and pass extra config data.  This helps its driver use
  * capabilities that the now-obsolete mc146818 didn't have, and informs it
@@ -283,11 +312,24 @@ static int __init acpi_rtc_init(void)
        struct device *dev = get_rtc_dev();
 
        if (dev) {
+               rtc_wake_setup();
+               rtc_info.wake_on = rtc_wake_on;
+               rtc_info.wake_off = rtc_wake_off;
+
+               /* workaround bug in some ACPI tables */
+               if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
+                       DBG("bogus FADT month_alarm\n");
+                       acpi_gbl_FADT.month_alarm = 0;
+               }
+
                rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
                rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
                rtc_info.rtc_century = acpi_gbl_FADT.century;
 
-               /* NOTE:  acpi_gbl_FADT->rtcs4 is NOT currently useful */
+               /* NOTE:  S4_RTC_WAKE is NOT currently useful to Linux */
+               if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
+                       printk(PREFIX "RTC can wake from S4\n");
+
 
                dev->platform_data = &rtc_info;
 
@@ -296,7 +338,7 @@ static int __init acpi_rtc_init(void)
 
                put_device(dev);
        } else
-               pr_debug("ACPI: RTC unavailable?\n");
+               DBG("RTC unavailable?\n");
        return 0;
 }
 /* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
index 971eca4864fab3223bc68d97cd032a56d428f4ea..c2bed56915e1eafe1559d906ba06661764990d45 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
index d80dd84e5bfdaab0713177c5cb21db15aac07996..6b3b8a522476f463ffb4d0df5c77fa799ad76b1b 100644 (file)
@@ -302,7 +302,7 @@ static void acpi_device_shutdown(struct device *dev)
        return ;
 }
 
-static struct bus_type acpi_bus_type = {
+struct bus_type acpi_bus_type = {
        .name           = "acpi",
        .suspend        = acpi_device_suspend,
        .resume         = acpi_device_resume,
index f8c63410bcbf55eb285e88f2d156ec95634d390f..52b23471dd69b08e01b868db425f2390ed5631b9 100644 (file)
@@ -29,7 +29,6 @@ static u32 acpi_suspend_states[] = {
        [PM_SUSPEND_ON] = ACPI_STATE_S0,
        [PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
        [PM_SUSPEND_MEM] = ACPI_STATE_S3,
-       [PM_SUSPEND_DISK] = ACPI_STATE_S4,
        [PM_SUSPEND_MAX] = ACPI_STATE_S5
 };
 
@@ -94,14 +93,6 @@ static int acpi_pm_enter(suspend_state_t pm_state)
                do_suspend_lowlevel();
                break;
 
-       case PM_SUSPEND_DISK:
-               if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM)
-                       status = acpi_enter_sleep_state(acpi_state);
-               break;
-       case PM_SUSPEND_MAX:
-               acpi_power_off();
-               break;
-
        default:
                return -EINVAL;
        }
@@ -157,12 +148,13 @@ int acpi_suspend(u32 acpi_state)
        suspend_state_t states[] = {
                [1] = PM_SUSPEND_STANDBY,
                [3] = PM_SUSPEND_MEM,
-               [4] = PM_SUSPEND_DISK,
                [5] = PM_SUSPEND_MAX
        };
 
        if (acpi_state < 6 && states[acpi_state])
                return pm_suspend(states[acpi_state]);
+       if (acpi_state == 4)
+               return hibernate();
        return -EINVAL;
 }
 
@@ -189,6 +181,49 @@ static struct pm_ops acpi_pm_ops = {
        .finish = acpi_pm_finish,
 };
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+static int acpi_hibernation_prepare(void)
+{
+       return acpi_sleep_prepare(ACPI_STATE_S4);
+}
+
+static int acpi_hibernation_enter(void)
+{
+       acpi_status status = AE_OK;
+       unsigned long flags = 0;
+
+       ACPI_FLUSH_CPU_CACHE();
+
+       local_irq_save(flags);
+       acpi_enable_wakeup_device(ACPI_STATE_S4);
+       /* This shouldn't return.  If it returns, we have a problem */
+       status = acpi_enter_sleep_state(ACPI_STATE_S4);
+       local_irq_restore(flags);
+
+       return ACPI_SUCCESS(status) ? 0 : -EFAULT;
+}
+
+static void acpi_hibernation_finish(void)
+{
+       acpi_leave_sleep_state(ACPI_STATE_S4);
+       acpi_disable_wakeup_device(ACPI_STATE_S4);
+
+       /* reset firmware waking vector */
+       acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+
+       if (init_8259A_after_S1) {
+               printk("Broken toshiba laptop -> kicking interrupts\n");
+               init_8259A(0);
+       }
+}
+
+static struct hibernation_ops acpi_hibernation_ops = {
+       .prepare = acpi_hibernation_prepare,
+       .enter = acpi_hibernation_enter,
+       .finish = acpi_hibernation_finish,
+};
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
 /*
  * Toshiba fails to preserve interrupts over S1, reinitialization
  * of 8259 is needed after S1 resume.
@@ -227,14 +262,18 @@ int __init acpi_sleep_init(void)
                        sleep_states[i] = 1;
                        printk(" S%d", i);
                }
-               if (i == ACPI_STATE_S4) {
-                       if (sleep_states[i])
-                               acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
-               }
        }
        printk(")\n");
 
        pm_set_ops(&acpi_pm_ops);
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+       if (sleep_states[ACPI_STATE_S4])
+               hibernation_set_ops(&acpi_hibernation_ops);
+#else
+       sleep_states[ACPI_STATE_S4] = 0;
+#endif
+
        return 0;
 }
 
index dcde9ddd105ae358a35c041e839cdace01a12baa..76b45f0b8341c3c0979659cad0623cfb79bcb4e4 100644 (file)
@@ -60,7 +60,7 @@ acpi_system_write_sleep(struct file *file,
        state = simple_strtoul(str, NULL, 0);
 #ifdef CONFIG_SOFTWARE_SUSPEND
        if (state == 4) {
-               error = pm_suspend(PM_SUSPEND_DISK);
+               error = hibernate();
                goto Done;
        }
 #endif
@@ -70,6 +70,14 @@ acpi_system_write_sleep(struct file *file,
 }
 #endif                         /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
 
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */
+#else
+#define        HAVE_ACPI_LEGACY_ALARM
+#endif
+
+#ifdef HAVE_ACPI_LEGACY_ALARM
+
 static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
 {
        u32 sec, min, hr;
@@ -341,6 +349,8 @@ acpi_system_write_alarm(struct file *file,
       end:
        return_VALUE(result ? result : count);
 }
+#endif /* HAVE_ACPI_LEGACY_ALARM */
+
 
 extern struct list_head acpi_wakeup_device_list;
 extern spinlock_t acpi_device_lock;
@@ -464,6 +474,7 @@ static const struct file_operations acpi_system_sleep_fops = {
 };
 #endif                         /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
 
+#ifdef HAVE_ACPI_LEGACY_ALARM
 static const struct file_operations acpi_system_alarm_fops = {
        .open = acpi_system_alarm_open_fs,
        .read = seq_read,
@@ -479,8 +490,9 @@ static u32 rtc_handler(void *context)
 
        return ACPI_INTERRUPT_HANDLED;
 }
+#endif /* HAVE_ACPI_LEGACY_ALARM */
 
-static int acpi_sleep_proc_init(void)
+static int __init acpi_sleep_proc_init(void)
 {
        struct proc_dir_entry *entry = NULL;
 
@@ -496,6 +508,7 @@ static int acpi_sleep_proc_init(void)
                entry->proc_fops = &acpi_system_sleep_fops;
 #endif
 
+#ifdef HAVE_ACPI_LEGACY_ALARM
        /* 'alarm' [R/W] */
        entry =
            create_proc_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
@@ -503,6 +516,9 @@ static int acpi_sleep_proc_init(void)
        if (entry)
                entry->proc_fops = &acpi_system_alarm_fops;
 
+       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+#endif /* HAVE_ACPI_LEGACY_ALARM */
+
        /* 'wakeup device' [R/W] */
        entry =
            create_proc_entry("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
@@ -510,7 +526,6 @@ static int acpi_sleep_proc_init(void)
        if (entry)
                entry->proc_fops = &acpi_system_wakeup_device_fops;
 
-       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
        return 0;
 }
 
index 45dbdc14915fc428c9ed58bc0c4381c63e4ec76f..c7219663f2b9e01fa4c04912557b7637c0ee9732 100644 (file)
@@ -435,7 +435,7 @@ config PATA_OPTIDMA
        help
          This option enables DMA/PIO support for the later OPTi
          controllers found on some old motherboards and in some
-         latops
+         laptops.
 
          If unsure, say N.
 
index 34c5534ed64c22c65779b418a57793739b98f16f..d9617892fc23806d0f8ffdebb200d74c513f8511 100644 (file)
@@ -874,7 +874,8 @@ static int ahci_clo(struct ata_port *ap)
        return 0;
 }
 
-static int ahci_softreset(struct ata_port *ap, unsigned int *class)
+static int ahci_softreset(struct ata_port *ap, unsigned int *class,
+                         unsigned long deadline)
 {
        struct ahci_port_priv *pp = ap->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
@@ -959,15 +960,13 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
         */
        msleep(150);
 
-       *class = ATA_DEV_NONE;
-       if (ata_port_online(ap)) {
-               if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-                       rc = -EIO;
-                       reason = "device not ready";
-                       goto fail;
-               }
-               *class = ahci_dev_classify(ap);
+       rc = ata_wait_ready(ap, deadline);
+       /* link occupied, -ENODEV too is an error */
+       if (rc) {
+               reason = "device not ready";
+               goto fail;
        }
+       *class = ahci_dev_classify(ap);
 
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
@@ -979,7 +978,8 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
        return rc;
 }
 
-static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
+static int ahci_hardreset(struct ata_port *ap, unsigned int *class,
+                         unsigned long deadline)
 {
        struct ahci_port_priv *pp = ap->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
@@ -995,7 +995,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
        tf.command = 0x80;
        ata_tf_to_fis(&tf, d2h_fis, 0);
 
-       rc = sata_std_hardreset(ap, class);
+       rc = sata_std_hardreset(ap, class, deadline);
 
        ahci_start_engine(ap);
 
@@ -1008,7 +1008,8 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
        return rc;
 }
 
-static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
+static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class,
+                                unsigned long deadline)
 {
        int rc;
 
@@ -1016,7 +1017,8 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
 
        ahci_stop_engine(ap);
 
-       rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
+       rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context),
+                                deadline);
 
        /* vt8251 needs SError cleared for the port to operate */
        ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
index 55d306a3e5386e779e12d040a9156040d93a5c69..4a795fdb6a02fa0bf37b150dca27d2d9cd460e88 100644 (file)
@@ -625,17 +625,18 @@ static int ich_pata_cable_detect(struct ata_port *ap)
 /**
  *     piix_pata_prereset - prereset for PATA host controller
  *     @ap: Target port
+ *     @deadline: deadline jiffies for the operation
  *
  *     LOCKING:
  *     None (inherited from caller).
  */
-static int piix_pata_prereset(struct ata_port *ap)
+static int piix_pata_prereset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
        if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 static void piix_pata_error_handler(struct ata_port *ap)
@@ -644,7 +645,6 @@ static void piix_pata_error_handler(struct ata_port *ap)
                           ata_std_postreset);
 }
 
-
 static void piix_sata_error_handler(struct ata_port *ap)
 {
        ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
index ca67484af1ebe2259164f5b3531d6ee8056ac89f..fef87dd70d1774e8b70ef397b21098b7b98b0233 100644 (file)
@@ -1316,7 +1316,7 @@ void ata_port_flush_task(struct ata_port *ap)
        spin_unlock_irqrestore(ap->lock, flags);
 
        DPRINTK("flush #1\n");
-       flush_workqueue(ata_wq);
+       cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */
 
        /*
         * At this point, if a task is running, it's guaranteed to see
@@ -1327,7 +1327,7 @@ void ata_port_flush_task(struct ata_port *ap)
                if (ata_msg_ctl(ap))
                        ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
                                        __FUNCTION__);
-               flush_workqueue(ata_wq);
+               cancel_work_sync(&ap->port_task.work);
        }
 
        spin_lock_irqsave(ap->lock, flags);
@@ -2979,23 +2979,71 @@ int ata_busy_sleep(struct ata_port *ap,
        return 0;
 }
 
-static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+/**
+ *     ata_wait_ready - sleep until BSY clears, or timeout
+ *     @ap: port containing status register to be polled
+ *     @deadline: deadline jiffies for the operation
+ *
+ *     Sleep until ATA Status register bit BSY clears, or timeout
+ *     occurs.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
+{
+       unsigned long start = jiffies;
+       int warned = 0;
+
+       while (1) {
+               u8 status = ata_chk_status(ap);
+               unsigned long now = jiffies;
+
+               if (!(status & ATA_BUSY))
+                       return 0;
+               if (status == 0xff)
+                       return -ENODEV;
+               if (time_after(now, deadline))
+                       return -EBUSY;
+
+               if (!warned && time_after(now, start + 5 * HZ) &&
+                   (deadline - now > 3 * HZ)) {
+                       ata_port_printk(ap, KERN_WARNING,
+                               "port is slow to respond, please be patient "
+                               "(Status 0x%x)\n", status);
+                       warned = 1;
+               }
+
+               msleep(50);
+       }
+}
+
+static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+                             unsigned long deadline)
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
        unsigned int dev0 = devmask & (1 << 0);
        unsigned int dev1 = devmask & (1 << 1);
-       unsigned long timeout;
+       int rc, ret = 0;
 
        /* if device 0 was found in ata_devchk, wait for its
         * BSY bit to clear
         */
-       if (dev0)
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       if (dev0) {
+               rc = ata_wait_ready(ap, deadline);
+               if (rc) {
+                       if (rc != -ENODEV)
+                               return rc;
+                       ret = rc;
+               }
+       }
 
        /* if device 1 was found in ata_devchk, wait for
         * register access, then wait for BSY to clear
         */
-       timeout = jiffies + ATA_TMOUT_BOOT;
        while (dev1) {
                u8 nsect, lbal;
 
@@ -3004,14 +3052,18 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
                lbal = ioread8(ioaddr->lbal_addr);
                if ((nsect == 1) && (lbal == 1))
                        break;
-               if (time_after(jiffies, timeout)) {
-                       dev1 = 0;
-                       break;
-               }
+               if (time_after(jiffies, deadline))
+                       return -EBUSY;
                msleep(50);     /* give drive a breather */
        }
-       if (dev1)
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       if (dev1) {
+               rc = ata_wait_ready(ap, deadline);
+               if (rc) {
+                       if (rc != -ENODEV)
+                               return rc;
+                       ret = rc;
+               }
+       }
 
        /* is all this really necessary? */
        ap->ops->dev_select(ap, 0);
@@ -3019,10 +3071,12 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
                ap->ops->dev_select(ap, 1);
        if (dev0)
                ap->ops->dev_select(ap, 0);
+
+       return ret;
 }
 
-static unsigned int ata_bus_softreset(struct ata_port *ap,
-                                     unsigned int devmask)
+static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+                            unsigned long deadline)
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -3052,11 +3106,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
         * pulldown resistor.
         */
        if (ata_check_status(ap) == 0xFF)
-               return 0;
-
-       ata_bus_post_reset(ap, devmask);
+               return -ENODEV;
 
-       return 0;
+       return ata_bus_post_reset(ap, devmask, deadline);
 }
 
 /**
@@ -3085,6 +3137,7 @@ void ata_bus_reset(struct ata_port *ap)
        unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
        u8 err;
        unsigned int dev0, dev1 = 0, devmask = 0;
+       int rc;
 
        DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
 
@@ -3106,9 +3159,11 @@ void ata_bus_reset(struct ata_port *ap)
        ap->ops->dev_select(ap, 0);
 
        /* issue bus reset */
-       if (ap->flags & ATA_FLAG_SRST)
-               if (ata_bus_softreset(ap, devmask))
+       if (ap->flags & ATA_FLAG_SRST) {
+               rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
+               if (rc && rc != -ENODEV)
                        goto err_out;
+       }
 
        /*
         * determine by signature whether we have ATA or ATAPI devices
@@ -3150,29 +3205,37 @@ err_out:
  *     sata_phy_debounce - debounce SATA phy status
  *     @ap: ATA port to debounce SATA phy status for
  *     @params: timing parameters { interval, duratinon, timeout } in msec
+ *     @deadline: deadline jiffies for the operation
  *
  *     Make sure SStatus of @ap reaches stable state, determined by
  *     holding the same value where DET is not 1 for @duration polled
  *     every @interval, before @timeout.  Timeout constraints the
- *     beginning of the stable state.  Because, after hot unplugging,
- *     DET gets stuck at 1 on some controllers, this functions waits
+ *     beginning of the stable state.  Because DET gets stuck at 1 on
+ *     some controllers after hot unplugging, this functions waits
  *     until timeout then returns 0 if DET is stable at 1.
  *
+ *     @timeout is further limited by @deadline.  The sooner of the
+ *     two is used.
+ *
  *     LOCKING:
  *     Kernel thread context (may sleep)
  *
  *     RETURNS:
  *     0 on success, -errno on failure.
  */
-int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
+int sata_phy_debounce(struct ata_port *ap, const unsigned long *params,
+                     unsigned long deadline)
 {
        unsigned long interval_msec = params[0];
-       unsigned long duration = params[1] * HZ / 1000;
-       unsigned long timeout = jiffies + params[2] * HZ / 1000;
-       unsigned long last_jiffies;
+       unsigned long duration = msecs_to_jiffies(params[1]);
+       unsigned long last_jiffies, t;
        u32 last, cur;
        int rc;
 
+       t = jiffies + msecs_to_jiffies(params[2]);
+       if (time_before(t, deadline))
+               deadline = t;
+
        if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
                return rc;
        cur &= 0xf;
@@ -3188,7 +3251,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
 
                /* DET stable? */
                if (cur == last) {
-                       if (cur == 1 && time_before(jiffies, timeout))
+                       if (cur == 1 && time_before(jiffies, deadline))
                                continue;
                        if (time_after(jiffies, last_jiffies + duration))
                                return 0;
@@ -3199,8 +3262,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
                last = cur;
                last_jiffies = jiffies;
 
-               /* check timeout */
-               if (time_after(jiffies, timeout))
+               /* check deadline */
+               if (time_after(jiffies, deadline))
                        return -EBUSY;
        }
 }
@@ -3209,6 +3272,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
  *     sata_phy_resume - resume SATA phy
  *     @ap: ATA port to resume SATA phy for
  *     @params: timing parameters { interval, duratinon, timeout } in msec
+ *     @deadline: deadline jiffies for the operation
  *
  *     Resume SATA phy of @ap and debounce it.
  *
@@ -3218,7 +3282,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
  *     RETURNS:
  *     0 on success, -errno on failure.
  */
-int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
+int sata_phy_resume(struct ata_port *ap, const unsigned long *params,
+                   unsigned long deadline)
 {
        u32 scontrol;
        int rc;
@@ -3236,43 +3301,19 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
         */
        msleep(200);
 
-       return sata_phy_debounce(ap, params);
-}
-
-static void ata_wait_spinup(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       unsigned long end, secs;
-       int rc;
-
-       /* first, debounce phy if SATA */
-       if (ap->cbl == ATA_CBL_SATA) {
-               rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
-
-               /* if debounced successfully and offline, no need to wait */
-               if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
-                       return;
-       }
-
-       /* okay, let's give the drive time to spin up */
-       end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
-       secs = ((end - jiffies) + HZ - 1) / HZ;
-
-       if (time_after(jiffies, end))
-               return;
-
-       if (secs > 5)
-               ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
-                               "(%lu secs)\n", secs);
-
-       schedule_timeout_uninterruptible(end - jiffies);
+       return sata_phy_debounce(ap, params, deadline);
 }
 
 /**
  *     ata_std_prereset - prepare for reset
  *     @ap: ATA port to be reset
+ *     @deadline: deadline jiffies for the operation
  *
- *     @ap is about to be reset.  Initialize it.
+ *     @ap is about to be reset.  Initialize it.  Failure from
+ *     prereset makes libata abort whole reset sequence and give up
+ *     that port, so prereset should be best-effort.  It does its
+ *     best to prepare for reset sequence but if things go wrong, it
+ *     should just whine, not fail.
  *
  *     LOCKING:
  *     Kernel thread context (may sleep)
@@ -3280,41 +3321,41 @@ static void ata_wait_spinup(struct ata_port *ap)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int ata_std_prereset(struct ata_port *ap)
+int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
 {
        struct ata_eh_context *ehc = &ap->eh_context;
        const unsigned long *timing = sata_ehc_deb_timing(ehc);
        int rc;
 
-       /* handle link resume & hotplug spinup */
+       /* handle link resume */
        if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
            (ap->flags & ATA_FLAG_HRST_TO_RESUME))
                ehc->i.action |= ATA_EH_HARDRESET;
 
-       if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
-           (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
-               ata_wait_spinup(ap);
-
        /* if we're about to do hardreset, nothing more to do */
        if (ehc->i.action & ATA_EH_HARDRESET)
                return 0;
 
        /* if SATA, resume phy */
        if (ap->cbl == ATA_CBL_SATA) {
-               rc = sata_phy_resume(ap, timing);
-               if (rc && rc != -EOPNOTSUPP) {
-                       /* phy resume failed */
+               rc = sata_phy_resume(ap, timing, deadline);
+               /* whine about phy resume failure but proceed */
+               if (rc && rc != -EOPNOTSUPP)
                        ata_port_printk(ap, KERN_WARNING, "failed to resume "
                                        "link for reset (errno=%d)\n", rc);
-                       return rc;
-               }
        }
 
        /* Wait for !BSY if the controller can wait for the first D2H
         * Reg FIS and we don't know that no device is attached.
         */
-       if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) {
+               rc = ata_wait_ready(ap, deadline);
+               if (rc) {
+                       ata_port_printk(ap, KERN_WARNING, "device not ready "
+                                       "(errno=%d), forcing hardreset\n", rc);
+                       ehc->i.action |= ATA_EH_HARDRESET;
+               }
+       }
 
        return 0;
 }
@@ -3323,6 +3364,7 @@ int ata_std_prereset(struct ata_port *ap)
  *     ata_std_softreset - reset host port via ATA SRST
  *     @ap: port to reset
  *     @classes: resulting classes of attached devices
+ *     @deadline: deadline jiffies for the operation
  *
  *     Reset host port using ATA SRST.
  *
@@ -3332,10 +3374,12 @@ int ata_std_prereset(struct ata_port *ap)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
+int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
+                     unsigned long deadline)
 {
        unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
-       unsigned int devmask = 0, err_mask;
+       unsigned int devmask = 0;
+       int rc;
        u8 err;
 
        DPRINTK("ENTER\n");
@@ -3356,11 +3400,11 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 
        /* issue bus reset */
        DPRINTK("about to softreset, devmask=%x\n", devmask);
-       err_mask = ata_bus_softreset(ap, devmask);
-       if (err_mask) {
-               ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
-                               err_mask);
-               return -EIO;
+       rc = ata_bus_softreset(ap, devmask, deadline);
+       /* if link is occupied, -ENODEV too is an error */
+       if (rc && (rc != -ENODEV || sata_scr_valid(ap))) {
+               ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+               return rc;
        }
 
        /* determine by signature whether we have ATA or ATAPI devices */
@@ -3377,6 +3421,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
  *     sata_port_hardreset - reset port via SATA phy reset
  *     @ap: port to reset
  *     @timing: timing parameters { interval, duratinon, timeout } in msec
+ *     @deadline: deadline jiffies for the operation
  *
  *     SATA phy-reset host port using DET bits of SControl register.
  *
@@ -3386,7 +3431,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
+int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing,
+                       unsigned long deadline)
 {
        u32 scontrol;
        int rc;
@@ -3425,7 +3471,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
        msleep(1);
 
        /* bring phy back */
-       rc = sata_phy_resume(ap, timing);
+       rc = sata_phy_resume(ap, timing, deadline);
  out:
        DPRINTK("EXIT, rc=%d\n", rc);
        return rc;
@@ -3435,6 +3481,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
  *     sata_std_hardreset - reset host port via SATA phy reset
  *     @ap: port to reset
  *     @class: resulting class of attached device
+ *     @deadline: deadline jiffies for the operation
  *
  *     SATA phy-reset host port using DET bits of SControl register,
  *     wait for !BSY and classify the attached device.
@@ -3445,7 +3492,8 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
+                      unsigned long deadline)
 {
        const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
        int rc;
@@ -3453,7 +3501,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
        DPRINTK("ENTER\n");
 
        /* do hardreset */
-       rc = sata_port_hardreset(ap, timing);
+       rc = sata_port_hardreset(ap, timing, deadline);
        if (rc) {
                ata_port_printk(ap, KERN_ERR,
                                "COMRESET failed (errno=%d)\n", rc);
@@ -3470,10 +3518,12 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
        /* wait a while before checking status, see SRST for more info */
        msleep(150);
 
-       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+       rc = ata_wait_ready(ap, deadline);
+       /* link occupied, -ENODEV too is an error */
+       if (rc) {
                ata_port_printk(ap, KERN_ERR,
-                               "COMRESET failed (device not ready)\n");
-               return -EIO;
+                               "COMRESET failed (errno=%d)\n", rc);
+               return rc;
        }
 
        ap->ops->dev_select(ap, 0);     /* probably unnecessary */
@@ -6425,9 +6475,9 @@ void ata_port_detach(struct ata_port *ap)
        /* Flush hotplug task.  The sequence is similar to
         * ata_port_flush_task().
         */
-       flush_workqueue(ata_aux_wq);
+       cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
        cancel_delayed_work(&ap->hotplug_task);
-       flush_workqueue(ata_aux_wq);
+       cancel_work_sync(&ap->hotplug_task.work);
 
  skip_eh:
        /* remove the associated SCSI host */
@@ -6793,6 +6843,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
 EXPORT_SYMBOL_GPL(ata_wait_register);
 EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_wait_ready);
 EXPORT_SYMBOL_GPL(ata_port_queue_task);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
index 2bff9adcacf15de02b7f0f6c35f83116410df606..8256655ce7d9ea3e50dd26fa4a00973b7958cf25 100644 (file)
@@ -50,6 +50,28 @@ enum {
        ATA_EH_SPDN_FALLBACK_TO_PIO     = (1 << 2),
 };
 
+/* Waiting in ->prereset can never be reliable.  It's sometimes nice
+ * to wait there but it can't be depended upon; otherwise, we wouldn't
+ * be resetting.  Just give it enough time for most drives to spin up.
+ */
+enum {
+       ATA_EH_PRERESET_TIMEOUT         = 10 * HZ,
+};
+
+/* The following table determines how we sequence resets.  Each entry
+ * represents timeout for that try.  The first try can be soft or
+ * hardreset.  All others are hardreset if available.  In most cases
+ * the first reset w/ 10sec timeout should succeed.  Following entries
+ * are mostly for error handling, hotplug and retarded devices.
+ */
+static const unsigned long ata_eh_reset_timeouts[] = {
+       10 * HZ,        /* most drives spin up by 10sec */
+       10 * HZ,        /* > 99% working drives spin up before 20sec */
+       35 * HZ,        /* give > 30 secs of idleness for retarded devices */
+       5 * HZ,         /* and sweet one last chance */
+       /* > 1 min has elapsed, give up */
+};
+
 static void __ata_port_freeze(struct ata_port *ap);
 static void ata_eh_finish(struct ata_port *ap);
 #ifdef CONFIG_PM
@@ -1558,14 +1580,14 @@ static void ata_eh_report(struct ata_port *ap)
 }
 
 static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
-                       unsigned int *classes)
+                       unsigned int *classes, unsigned long deadline)
 {
        int i, rc;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                classes[i] = ATA_DEV_UNKNOWN;
 
-       rc = reset(ap, classes);
+       rc = reset(ap, classes, deadline);
        if (rc)
                return rc;
 
@@ -1603,8 +1625,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
 {
        struct ata_eh_context *ehc = &ap->eh_context;
        unsigned int *classes = ehc->classes;
-       int tries = ATA_EH_RESET_TRIES;
        int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
+       int try = 0;
+       unsigned long deadline;
        unsigned int action;
        ata_reset_fn_t reset;
        int i, did_followup_srst, rc;
@@ -1624,7 +1647,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
                ehc->i.action |= ATA_EH_HARDRESET;
 
        if (prereset) {
-               rc = prereset(ap);
+               rc = prereset(ap, jiffies + ATA_EH_PRERESET_TIMEOUT);
                if (rc) {
                        if (rc == -ENOENT) {
                                ata_port_printk(ap, KERN_DEBUG,
@@ -1665,6 +1688,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
        }
 
  retry:
+       deadline = jiffies + ata_eh_reset_timeouts[try++];
+
        /* shut up during boot probing */
        if (verbose)
                ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
@@ -1676,7 +1701,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
        else
                ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
 
-       rc = ata_do_reset(ap, reset, classes);
+       rc = ata_do_reset(ap, reset, classes, deadline);
 
        did_followup_srst = 0;
        if (reset == hardreset &&
@@ -1693,7 +1718,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
                }
 
                ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
-               rc = ata_do_reset(ap, reset, classes);
+               rc = ata_do_reset(ap, reset, classes, deadline);
 
                if (rc == 0 && classify &&
                    classes[0] == ATA_DEV_UNKNOWN) {
@@ -1703,22 +1728,21 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
                }
        }
 
-       if (rc && --tries) {
-               const char *type;
+       if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
+               unsigned long now = jiffies;
 
-               if (reset == softreset) {
-                       if (did_followup_srst)
-                               type = "follow-up soft";
-                       else
-                               type = "soft";
-               } else
-                       type = "hard";
+               if (time_before(now, deadline)) {
+                       unsigned long delta = deadline - jiffies;
 
-               ata_port_printk(ap, KERN_WARNING,
-                               "%sreset failed, retrying in 5 secs\n", type);
-               ssleep(5);
+                       ata_port_printk(ap, KERN_WARNING, "reset failed "
+                               "(errno=%d), retrying in %u secs\n",
+                               rc, (jiffies_to_msecs(delta) + 999) / 1000);
+
+                       schedule_timeout_uninterruptible(delta);
+               }
 
-               if (reset == hardreset)
+               if (reset == hardreset &&
+                   try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
                        sata_down_spd_limit(ap);
                if (hardreset)
                        reset = hardreset;
index 536ee892ab72da7aa2b789010c1bf60381de893d..67c7e87dec042417bf33e426091216570012d075 100644 (file)
@@ -121,12 +121,13 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 /**
  *     amd_probe_init          -       perform reset handling
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Reset sequence checking enable bits to see which ports are
  *     active.
  */
 
-static int amd_pre_reset(struct ata_port *ap)
+static int amd_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits amd_enable_bits[] = {
                { 0x40, 1, 0x02, 0x02 },
@@ -138,8 +139,7 @@ static int amd_pre_reset(struct ata_port *ap)
        if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
-
+       return ata_std_prereset(ap, deadline);
 }
 
 static void amd_error_handler(struct ata_port *ap)
@@ -227,7 +227,8 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  *     space for us.
  */
 
-static int nv_pre_reset(struct ata_port *ap) {
+static int nv_pre_reset(struct ata_port *ap, unsigned long deadline)
+{
        static const struct pci_bits nv_enable_bits[] = {
                { 0x50, 1, 0x02, 0x02 },
                { 0x50, 1, 0x01, 0x01 }
@@ -238,7 +239,7 @@ static int nv_pre_reset(struct ata_port *ap) {
        if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 static void nv_error_handler(struct ata_port *ap)
index 00e9ec342db001cda8e2ff32e9e29435f10fb92e..ef51940c3adb36e7f2a8c4f9d80aec185ddc8567 100644 (file)
@@ -39,7 +39,7 @@
 
 static int clock = 0;
 
-static int artop6210_pre_reset(struct ata_port *ap)
+static int artop6210_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        const struct pci_bits artop_enable_bits[] = {
@@ -49,7 +49,8 @@ static int artop6210_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
@@ -70,12 +71,13 @@ static void artop6210_error_handler(struct ata_port *ap)
 /**
  *     artop6260_pre_reset     -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     The ARTOP hardware reports the cable detect bits in register 0x49.
  *     Nothing complicated needed here.
  */
 
-static int artop6260_pre_reset(struct ata_port *ap)
+static int artop6260_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits artop_enable_bits[] = {
                { 0x4AU, 1U, 0x02UL, 0x02UL },  /* port 0 */
@@ -87,7 +89,8 @@ static int artop6260_pre_reset(struct ata_port *ap)
        /* Odd numbered device ids are the units with enable bits (the -R cards) */
        if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 39c871a3ddac9578fb8a3be5437eb2ecc69667b4..21515381b5b34759479053b9c0d51edcb106ddca 100644 (file)
@@ -33,7 +33,7 @@ enum {
        ATIIXP_IDE_UDMA_MODE    = 0x56
 };
 
-static int atiixp_pre_reset(struct ata_port *ap)
+static int atiixp_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits atiixp_enable_bits[] = {
                { 0x48, 1, 0x01, 0x00 },
@@ -44,7 +44,7 @@ static int atiixp_pre_reset(struct ata_port *ap)
        if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 static void atiixp_error_handler(struct ata_port *ap)
index 08cccc9c659b9cebbbe7ff13fe2c1a1cdd292d2c..22006ae719411a52218bcfb96a161d702fdce39e 100644 (file)
@@ -72,6 +72,7 @@
 /**
  *     cs5535_cable_detect     -       detect cable type
  *     @ap: Port to detect on
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform cable detection for ATA66 capable cable. Return a libata
  *     cable type.
index a3216850bba15e10938da4f2335f50e863b516e5..d0f52e0349061779747fd622ce439a9a420463ca 100644 (file)
 /**
  *     efar_pre_reset  -       Enable bits
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform cable detection for the EFAR ATA interface. This is
  *     different to the PIIX arrangement
  */
 
-static int efar_pre_reset(struct ata_port *ap)
+static int efar_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits efar_enable_bits[] = {
                { 0x41U, 1U, 0x80UL, 0x80UL },  /* port 0 */
@@ -43,7 +44,7 @@ static int efar_pre_reset(struct ata_port *ap)
        if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 93cfa6d300a5a08196d789817a4c93938b7b1da6..e64e05e5c7fe26414ebbb3b7480ea764e95c985a 100644 (file)
@@ -220,7 +220,7 @@ static int hpt36x_cable_detect(struct ata_port *ap)
        return ATA_CBL_PATA80;
 }
 
-static int hpt36x_pre_reset(struct ata_port *ap)
+static int hpt36x_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits hpt36x_enable_bits[] = {
                { 0x50, 1, 0x04, 0x04 },
@@ -231,7 +231,7 @@ static int hpt36x_pre_reset(struct ata_port *ap)
        if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 41d8312963474447feb7faf6284a80efaa00cc53..1614e8c822a4ed7285f891b5353ea0cacbf95a9e 100644 (file)
@@ -307,11 +307,12 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
 /**
  *     hpt37x_pre_reset        -       reset the hpt37x bus
  *     @ap: ATA port to reset
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform the initial reset handling for the 370/372 and 374 func 0
  */
 
-static int hpt37x_pre_reset(struct ata_port *ap)
+static int hpt37x_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        u8 scr2, ata66;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -338,7 +339,7 @@ static int hpt37x_pre_reset(struct ata_port *ap)
        pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
@@ -353,7 +354,7 @@ static void hpt37x_error_handler(struct ata_port *ap)
        ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
 }
 
-static int hpt374_pre_reset(struct ata_port *ap)
+static int hpt374_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits hpt37x_enable_bits[] = {
                { 0x50, 1, 0x04, 0x04 },
@@ -388,7 +389,7 @@ static int hpt374_pre_reset(struct ata_port *ap)
        pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 6a34521b9e01a7ded70309d3b528c0d7b4f1410e..ea1037d6786028bbaaf1312a504ee407b66148e6 100644 (file)
@@ -148,13 +148,14 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
  *     Reset the hardware and state machine,
  */
 
-static int hpt3xn_pre_reset(struct ata_port *ap)
+static int hpt3xn_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        /* Reset the state machine */
        pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 011306ef8334f8d7b701d6748190cb858fd79602..17bf9f3ed013b5c03fb1eaf15bc03bf3a143def9 100644 (file)
 /**
  *     it8213_pre_reset        -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Filter out ports by the enable bits before doing the normal reset
  *     and probe.
  */
 
-static int it8213_pre_reset(struct ata_port *ap)
+static int it8213_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits it8213_enable_bits[] = {
                { 0x41U, 1U, 0x80UL, 0x80UL },  /* port 0 */
@@ -37,7 +38,8 @@ static int it8213_pre_reset(struct ata_port *ap)
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 43763c99ea02a601b96ff8be1f943fab49d5b839..1daf78ac6efbb6c17b083231c1d7e95958a0361e 100644 (file)
@@ -30,16 +30,17 @@ typedef enum {
 /**
  *     jmicron_pre_reset       -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform the PATA port setup we need.
-
+ *
  *     On the Jmicron 361/363 there is a single PATA port that can be mapped
  *     either as primary or secondary (or neither). We don't do any policy
  *     and setup here. We assume that has been done by init_one and the
  *     BIOS.
  */
 
-static int jmicron_pre_reset(struct ata_port *ap)
+static int jmicron_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u32 control;
@@ -102,7 +103,7 @@ static int jmicron_pre_reset(struct ata_port *ap)
                ap->cbl = ATA_CBL_SATA;
                break;
        }
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index d9b94a1b6954ed384b3d351858cd91f4a7baed70..837b7fe77dc7ff1e4a97b6265e91a22d28afa1c1 100644 (file)
 /**
  *     marvell_pre_reset       -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform the PATA port setup we need.
  */
 
-static int marvell_pre_reset(struct ata_port *ap)
+static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u32 devices;
@@ -52,7 +53,8 @@ static int marvell_pre_reset(struct ata_port *ap)
        if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
            (!(devices & 0x10)))        /* PATA enable ? */
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 static int marvell_cable_detect(struct ata_port *ap)
@@ -67,6 +69,7 @@ static int marvell_cable_detect(struct ata_port *ap)
        case 1: /* Legacy SATA port */
                return ATA_CBL_SATA;
        }
+
        BUG();
        return 0;       /* Our BUG macro needs the right markup */
 }
index 987c5fafab087e72b1490c30ca9983d0bb506f3b..3bfbd495f6434425e6d5cdb2b82c7618e6c9ce27 100644 (file)
@@ -46,14 +46,15 @@ enum {
        SECONDARY = (1 << 14)
 };
 
-static int mpiix_pre_reset(struct ata_port *ap)
+static int mpiix_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 };
 
        if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 078aeda9cf8d81eacea9e824adec6f199d683a52..ebc58a907d26f3f8365961152a66fb9677182d54 100644 (file)
 /**
  *     ns87410_pre_reset               -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Check enabled ports
  */
 
-static int ns87410_pre_reset(struct ata_port *ap)
+static int ns87410_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        static const struct pci_bits ns87410_enable_bits[] = {
@@ -47,7 +48,8 @@ static int ns87410_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index dea4690340d1ed291cfd58c011d4f40ab55c11a1..4d75d32e5826e1a45b7f6188224edbcdf6b19b3c 100644 (file)
 /**
  *     oldpiix_pre_reset               -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int oldpiix_pre_reset(struct ata_port *ap)
+static int oldpiix_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        static const struct pci_bits oldpiix_enable_bits[] = {
@@ -44,7 +45,8 @@ static int oldpiix_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 13b63e21838d9ff94c0be60051c5a6e1190e78ee..0af8a2c77cc970baea6733735639e85393cd35c6 100644 (file)
@@ -47,11 +47,12 @@ enum {
 /**
  *     opti_pre_reset          -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int opti_pre_reset(struct ata_port *ap)
+static int opti_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        static const struct pci_bits opti_enable_bits[] = {
@@ -61,7 +62,8 @@ static int opti_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index b70e04c144dfa591ec6afe925b9b9acaa756b118..2843e480f2167a2d0fdd7937ce132b609c39260d 100644 (file)
@@ -48,11 +48,12 @@ static int pci_clock;       /* 0 = 33 1 = 25 */
 /**
  *     optidma_pre_reset               -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int optidma_pre_reset(struct ata_port *ap)
+static int optidma_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        static const struct pci_bits optidma_enable_bits = {
@@ -62,7 +63,7 @@ static int optidma_pre_reset(struct ata_port *ap)
        if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
                return -ENOENT;
 
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index a61cbc110688d1bf97859666aaa5fc7462cf7d2c..0d2cc49fde4b6a884e7c73e047b4f05c12cdf642 100644 (file)
@@ -301,6 +301,7 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
 /**
  *     pdc2027x_prereset - prereset for PATA host controller
  *     @ap: Target port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Probeinit including cable detection.
  *
@@ -308,12 +309,12 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
  *     None (inherited from caller).
  */
 
-static int pdc2027x_prereset(struct ata_port *ap)
+static int pdc2027x_prereset(struct ata_port *ap, unsigned long deadline)
 {
        /* Check whether port enabled */
        if (!pdc2027x_port_enabled(ap))
                return -ENOENT;
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 /**
index 3956ef26936d3005d601f9ad231effb3be89b83a..b6e020383dd960280ee3f28cc4c3bfe74a5ccc72 100644 (file)
@@ -139,12 +139,14 @@ static struct sv_cable_table cable_detect[] = {
 /**
  *     serverworks_cable_detect        -       cable detection
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform cable detection according to the device and subvendor
  *     identifications
  */
 
-static int serverworks_cable_detect(struct ata_port *ap) {
+static int serverworks_cable_detect(struct ata_port *ap)
+{
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        struct sv_cable_table *cb = cable_detect;
 
index 6770820cfca9c74c08f8e7e9eb8759429be6b624..a5886f061c0b424dd01d7c0eb33fec7440743e31 100644 (file)
@@ -94,11 +94,13 @@ static int sil680_cable_detect(struct ata_port *ap) {
 /**
  *     sil680_bus_reset        -       reset the SIL680 bus
  *     @ap: ATA port to reset
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform the SIL680 housekeeping when doing an ATA bus reset
  */
 
-static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes)
+static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes,
+                           unsigned long deadline)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        unsigned long addr = sil680_selreg(ap, 0);
@@ -108,7 +110,7 @@ static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes)
        pci_write_config_byte(pdev, addr, reset | 0x03);
        udelay(25);
        pci_write_config_byte(pdev, addr, reset);
-       return ata_std_softreset(ap, classes);
+       return ata_std_softreset(ap, classes, deadline);
 }
 
 static void sil680_error_handler(struct ata_port *ap)
index a3fbcee6fb330185ebf97ba10ecf9cb711862530..f5838cc11728602e8445ba126499b821d12cbab4 100644 (file)
@@ -88,6 +88,7 @@ static int sis_port_base(struct ata_device *adev)
 /**
  *     sis_133_cable_detect    -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform cable detection for the later UDMA133 capable
  *     SiS chipset.
@@ -108,6 +109,7 @@ static int sis_133_cable_detect(struct ata_port *ap)
 /**
  *     sis_66_cable_detect     -       check for 40/80 pin
  *     @ap: Port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Perform cable detection on the UDMA66, UDMA100 and early UDMA133
  *     SiS IDE controllers.
@@ -130,11 +132,12 @@ static int sis_66_cable_detect(struct ata_port *ap)
 /**
  *     sis_pre_reset           -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int sis_pre_reset(struct ata_port *ap)
+static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits sis_enable_bits[] = {
                { 0x4aU, 1U, 0x02UL, 0x02UL },  /* port 0 */
@@ -145,7 +148,8 @@ static int sis_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 
index da9e22b257532f10fb7e930117b379426b956fea..9aeffdbe28293e72df734f5c0b72953f9051cdf1 100644 (file)
@@ -44,11 +44,12 @@ enum {
 /**
  *     sl82c105_pre_reset              -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int sl82c105_pre_reset(struct ata_port *ap)
+static int sl82c105_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits sl82c105_enable_bits[] = {
                { 0x40, 1, 0x01, 0x01 },
@@ -58,7 +59,7 @@ static int sl82c105_pre_reset(struct ata_port *ap)
 
        if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+       return ata_std_prereset(ap, deadline);
 }
 
 
index e618ffd6e944b392ac35458ee5cd3dc7c73fc264..349887bf5b934d1f6f4f8ea5c63d57ef0bd073e1 100644 (file)
 /**
  *     triflex_prereset                -       probe begin
  *     @ap: ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     Set up cable type and use generic probe init
  */
 
-static int triflex_prereset(struct ata_port *ap)
+static int triflex_prereset(struct ata_port *ap, unsigned long deadline)
 {
        static const struct pci_bits triflex_enable_bits[] = {
                { 0x80, 1, 0x01, 0x01 },
@@ -63,7 +64,8 @@ static int triflex_prereset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
                return -ENOENT;
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 
index 96b71791d2f48edc8109d606a7a7d76c074df51b..362beb2f489c1e67e80274101442b32e0d25fc4b 100644 (file)
@@ -154,7 +154,7 @@ static int via_cable_detect(struct ata_port *ap) {
        return ATA_CBL_PATA40;
 }
 
-static int via_pre_reset(struct ata_port *ap)
+static int via_pre_reset(struct ata_port *ap, unsigned long deadline)
 {
        const struct via_isa_bridge *config = ap->host->private_data;
 
@@ -167,7 +167,8 @@ static int via_pre_reset(struct ata_port *ap)
                if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no]))
                        return -ENOENT;
        }
-       return ata_std_prereset(ap);
+
+       return ata_std_prereset(ap, deadline);
 }
 
 
index f099a1d83a000b7bb02dacc145259c59334c765e..b3b62e985f19e6dc1195b6a5890a94252a360f6d 100644 (file)
@@ -420,7 +420,8 @@ static void inic_thaw(struct ata_port *ap)
  * SRST and SControl hardreset don't give valid signature on this
  * controller.  Only controller specific hardreset mechanism works.
  */
-static int inic_hardreset(struct ata_port *ap, unsigned int *class)
+static int inic_hardreset(struct ata_port *ap, unsigned int *class,
+                         unsigned long deadline)
 {
        void __iomem *port_base = inic_port_base(ap);
        void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
@@ -437,7 +438,7 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class)
        msleep(1);
        writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);
 
-       rc = sata_phy_resume(ap, timing);
+       rc = sata_phy_resume(ap, timing, deadline);
        if (rc) {
                ata_port_printk(ap, KERN_WARNING, "failed to resume "
                                "link after reset (errno=%d)\n", rc);
@@ -451,10 +452,12 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class)
                /* wait a while before checking status */
                msleep(150);
 
-               if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-                       ata_port_printk(ap, KERN_WARNING,
-                                       "device busy after hardreset\n");
-                       return -EIO;
+               rc = ata_wait_ready(ap, deadline);
+               /* link occupied, -ENODEV too is an error */
+               if (rc) {
+                       ata_port_printk(ap, KERN_WARNING, "device not ready "
+                                       "after hardreset (errno=%d)\n", rc);
+                       return rc;
                }
 
                ata_tf_read(ap, &tf);
index 02169740ed245dd2bddc51f9297edf790b07768e..e2e795e5823671732947df073389dc54d814ed6b 100644 (file)
@@ -1405,7 +1405,8 @@ static void nv_ck804_thaw(struct ata_port *ap)
        writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
 }
 
-static int nv_hardreset(struct ata_port *ap, unsigned int *class)
+static int nv_hardreset(struct ata_port *ap, unsigned int *class,
+                       unsigned long deadline)
 {
        unsigned int dummy;
 
@@ -1413,7 +1414,7 @@ static int nv_hardreset(struct ata_port *ap, unsigned int *class)
         * some controllers.  Don't classify on hardreset.  For more
         * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
         */
-       return sata_std_hardreset(ap, &dummy);
+       return sata_std_hardreset(ap, &dummy, deadline);
 }
 
 static void nv_error_handler(struct ata_port *ap)
index e6223ba667daca271a19e1c541470d80463c2a9a..b97ee9f31aece7c8959f82c26b4a754af6e650ce 100644 (file)
@@ -534,7 +534,8 @@ static int sil24_init_port(struct ata_port *ap)
        return 0;
 }
 
-static int sil24_softreset(struct ata_port *ap, unsigned int *class)
+static int sil24_softreset(struct ata_port *ap, unsigned int *class,
+                          unsigned long deadline)
 {
        void __iomem *port = ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
@@ -566,7 +567,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
 
        mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
        irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
-                                    100, ATA_TMOUT_BOOT / HZ * 1000);
+                                    100, jiffies_to_msecs(deadline - jiffies));
 
        writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
        irq_stat >>= PORT_IRQ_RAW_SHIFT;
@@ -594,7 +595,8 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
        return -EIO;
 }
 
-static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
+static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
+                          unsigned long deadline)
 {
        void __iomem *port = ap->ioaddr.cmd_addr;
        const char *reason;
@@ -615,7 +617,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
        /* SStatus oscillates between zero and valid status after
         * DEV_RST, debounce it.
         */
-       rc = sata_phy_debounce(ap, sata_deb_timing_long);
+       rc = sata_phy_debounce(ap, sata_deb_timing_long, deadline);
        if (rc) {
                reason = "PHY debouncing failed";
                goto err;
index cc07aac10e8ce37a0ee818f5ec982b3fc602c509..17246734fe76951a415279148fd2e88f39627621 100644 (file)
@@ -288,7 +288,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
        /* Match it to a port node */
        index = (ap == ap->host->ports[0]) ? 0 : 1;
        for (np = np->child; np != NULL; np = np->sibling) {
-               const u32 *reg = get_property(np, "reg", NULL);
+               const u32 *reg = of_get_property(np, "reg", NULL);
                if (!reg)
                        continue;
                if (index == *reg)
index 1d855f55f5f710edd378110740b76042afe37005..305ab7c68ca529743409f827b426f0c8c276017f 100644 (file)
@@ -268,6 +268,7 @@ static void svia_noop_freeze(struct ata_port *ap)
 /**
  *     vt6420_prereset - prereset for vt6420
  *     @ap: target ATA port
+ *     @deadline: deadline jiffies for the operation
  *
  *     SCR registers on vt6420 are pieces of shit and may hang the
  *     whole machine completely if accessed with the wrong timing.
@@ -284,7 +285,7 @@ static void svia_noop_freeze(struct ata_port *ap)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-static int vt6420_prereset(struct ata_port *ap)
+static int vt6420_prereset(struct ata_port *ap, unsigned long deadline)
 {
        struct ata_eh_context *ehc = &ap->eh_context;
        unsigned long timeout = jiffies + (HZ * 5);
@@ -329,7 +330,7 @@ static int vt6420_prereset(struct ata_port *ap)
 
  skip_scr:
        /* wait for !BSY */
-       ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       ata_wait_ready(ap, deadline);
 
        return 0;
 }
index e177c9533b6cc6654e2c8afd3567021672d0c51a..e1c0730a3b995d246ad965330854e768f746ab65 100644 (file)
@@ -101,19 +101,6 @@ static void add_dr(struct device *dev, struct devres_node *node)
        list_add_tail(&node->entry, &dev->devres_head);
 }
 
-/**
- * devres_alloc - Allocate device resource data
- * @release: Release function devres will be associated with
- * @size: Allocation size
- * @gfp: Allocation flags
- *
- * allocate devres of @size bytes.  The allocated area is zeroed, then
- * associated with @release.  The returned pointer can be passed to
- * other devres_*() functions.
- *
- * RETURNS:
- * Pointer to allocated devres on success, NULL on failure.
- */
 #ifdef CONFIG_DEBUG_DEVRES
 void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
                      const char *name)
@@ -128,6 +115,19 @@ void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
 }
 EXPORT_SYMBOL_GPL(__devres_alloc);
 #else
+/**
+ * devres_alloc - Allocate device resource data
+ * @release: Release function devres will be associated with
+ * @size: Allocation size
+ * @gfp: Allocation flags
+ *
+ * Allocate devres of @size bytes.  The allocated area is zeroed, then
+ * associated with @release.  The returned pointer can be passed to
+ * other devres_*() functions.
+ *
+ * RETURNS:
+ * Pointer to allocated devres on success, NULL on failure.
+ */
 void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
 {
        struct devres *dr;
@@ -416,7 +416,7 @@ static int release_nodes(struct device *dev, struct list_head *first,
 }
 
 /**
- * devres_release_all - Release all resources
+ * devres_release_all - Release all managed resources
  * @dev: Device to release resources for
  *
  * Release all resources associated with @dev.  This function is
@@ -600,7 +600,7 @@ static int devm_kzalloc_match(struct device *dev, void *res, void *data)
 }
 
 /**
- * devm_kzalloc - Managed kzalloc
+ * devm_kzalloc - Resource-managed kzalloc
  * @dev: Device to allocate memory for
  * @size: Allocation size
  * @gfp: Allocation gfp flags
@@ -628,7 +628,7 @@ void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
 EXPORT_SYMBOL_GPL(devm_kzalloc);
 
 /**
- * devm_kfree - Managed kfree
+ * devm_kfree - Resource-managed kfree
  * @dev: Device this memory belongs to
  * @p: Memory to free
  *
index 17b5ece8f82cf647c8bf4fad6b632bbb9ab33a3e..869ff8c001460929a6b5721129b434c9cd50ef4f 100644 (file)
@@ -160,6 +160,11 @@ static void platform_device_release(struct device *dev)
  *
  *     Create a platform device object which can have other objects attached
  *     to it, and which will have attached objects freed when it is released.
+ *
+ *     This device will be marked as not supporting hotpluggable drivers; no
+ *     device add/remove uevents will be generated.  In the unusual case that
+ *     the device isn't being dynamically allocated as a legacy "probe the
+ *     hardware" driver, infrastructure code should reverse this marking.
  */
 struct platform_device *platform_device_alloc(const char *name, unsigned int id)
 {
@@ -172,6 +177,12 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
                pa->pdev.id = id;
                device_initialize(&pa->pdev.dev);
                pa->pdev.dev.release = platform_device_release;
+
+               /* prevent hotplug "modprobe $(MODALIAS)" from causing trouble in
+                * legacy probe-the-hardware drivers, which don't properly split
+                * out device enumeration logic from drivers.
+                */
+               pa->pdev.dev.uevent_suppress = 1;
        }
 
        return pa ? &pa->pdev : NULL;
@@ -349,8 +360,15 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
  *     This function creates a simple platform device that requires minimal
  *     resource and memory management. Canned release function freeing
  *     memory allocated for the device allows drivers using such devices
- *     to be unloaded iwithout waiting for the last reference to the device
+ *     to be unloaded without waiting for the last reference to the device
  *     to be dropped.
+ *
+ *     This interface is primarily intended for use with legacy drivers
+ *     which probe hardware directly.  Because such drivers create sysfs
+ *     device nodes themselves, rather than letting system infrastructure
+ *     handle such device enumeration tasks, they don't fully conform to
+ *     the Linux driver model.  In particular, when such drivers are built
+ *     as modules, they can't be "hotplugged".
  */
 struct platform_device *platform_device_register_simple(char *name, unsigned int id,
                                                        struct resource *res, unsigned int num)
index 067a9e8bc377f2cdfe670112bb493714f0faaeaf..8d8cdfec6529e683a194cd49547b81aa8c3680f6 100644 (file)
@@ -126,10 +126,13 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                rc = topology_add_dev(cpu);
                break;
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                topology_remove_dev(cpu);
                break;
        }
index e2e04329096385d3d9d34f08a933cbaa22f837d8..1d9d9b4f48ccca9070e02fb6bcacbdc465ad9700 100644 (file)
@@ -65,7 +65,6 @@ not be guaranteed. There are several ways to assure this:
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
index 65a725cd3422ec565d9508de378d32cb9c52ffd5..370dfe1c422ea8a4b3ce6c8c9ba49f8001667cd3 100644 (file)
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
 #include <linux/completion.h>
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <scsi/scsi_ioctl.h>
+#include <linux/cdrom.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 #define DRIVER_NAME "HP CISS Driver (v 3.6.14)"
@@ -1152,6 +1156,30 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                        kfree(ioc);
                        return status;
                }
+
+       /* scsi_cmd_ioctl handles these, below, though some are not */
+       /* very meaningful for cciss.  SG_IO is the main one people want. */
+
+       case SG_GET_VERSION_NUM:
+       case SG_SET_TIMEOUT:
+       case SG_GET_TIMEOUT:
+       case SG_GET_RESERVED_SIZE:
+       case SG_SET_RESERVED_SIZE:
+       case SG_EMULATED_HOST:
+       case SG_IO:
+       case SCSI_IOCTL_SEND_COMMAND:
+               return scsi_cmd_ioctl(filep, disk, cmd, argp);
+
+       /* scsi_cmd_ioctl would normally handle these, below, but */
+       /* they aren't a good fit for cciss, as CD-ROMs are */
+       /* not supported, and we don't have any bus/target/lun */
+       /* which we present to the kernel. */
+
+       case CDROM_SEND_PACKET:
+       case CDROMCLOSETRAY:
+       case CDROMEJECT:
+       case SCSI_IOCTL_GET_IDLUN:
+       case SCSI_IOCTL_GET_BUS_NUMBER:
        default:
                return -ENOTTY;
        }
@@ -1234,7 +1262,7 @@ static void cciss_softirq_done(struct request *rq)
                pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
        }
 
-       complete_buffers(rq->bio, rq->errors);
+       complete_buffers(rq->bio, (rq->errors == 0));
 
        if (blk_fs_request(rq)) {
                const int rw = rq_data_dir(rq);
@@ -1248,7 +1276,7 @@ static void cciss_softirq_done(struct request *rq)
 
        add_disk_randomness(rq->rq_disk);
        spin_lock_irqsave(&h->lock, flags);
-       end_that_request_last(rq, rq->errors);
+       end_that_request_last(rq, (rq->errors == 0));
        cmd_free(h, cmd, 1);
        cciss_check_queues(h);
        spin_unlock_irqrestore(&h->lock, flags);
@@ -2336,6 +2364,44 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
        start_io(h);
 }
 
+static inline int evaluate_target_status(CommandList_struct *cmd)
+{
+       unsigned char sense_key;
+       int error_count = 1;
+
+       if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */
+               if (!blk_pc_request(cmd->rq))
+                       printk(KERN_WARNING "cciss: cmd %p "
+                              "has SCSI Status 0x%x\n",
+                              cmd, cmd->err_info->ScsiStatus);
+               return error_count;
+       }
+
+       /* check the sense key */
+       sense_key = 0xf & cmd->err_info->SenseInfo[2];
+       /* no status or recovered error */
+       if ((sense_key == 0x0) || (sense_key == 0x1))
+               error_count = 0;
+
+       if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
+               if (error_count != 0)
+                       printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
+                              " sense key = 0x%x\n", cmd, sense_key);
+               return error_count;
+       }
+
+       /* SG_IO or similar, copy sense data back */
+       if (cmd->rq->sense) {
+               if (cmd->rq->sense_len > cmd->err_info->SenseLen)
+                       cmd->rq->sense_len = cmd->err_info->SenseLen;
+               memcpy(cmd->rq->sense, cmd->err_info->SenseInfo,
+                       cmd->rq->sense_len);
+       } else
+               cmd->rq->sense_len = 0;
+
+       return error_count;
+}
+
 /* checks the status of the job and calls complete buffers to mark all
  * buffers for the completed job. Note that this function does not need
  * to hold the hba/queue lock.
@@ -2343,109 +2409,99 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
 static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
                                    int timeout)
 {
-       int status = 1;
        int retry_cmd = 0;
+       struct request *rq = cmd->rq;
+
+       rq->errors = 0;
 
        if (timeout)
-               status = 0;
+               rq->errors = 1;
 
-       if (cmd->err_info->CommandStatus != 0) {        /* an error has occurred */
-               switch (cmd->err_info->CommandStatus) {
-                       unsigned char sense_key;
-               case CMD_TARGET_STATUS:
-                       status = 0;
+       if (cmd->err_info->CommandStatus == 0)  /* no error has occurred */
+               goto after_error_processing;
 
-                       if (cmd->err_info->ScsiStatus == 0x02) {
-                               printk(KERN_WARNING "cciss: cmd %p "
-                                      "has CHECK CONDITION "
-                                      " byte 2 = 0x%x\n", cmd,
-                                      cmd->err_info->SenseInfo[2]
-                                   );
-                               /* check the sense key */
-                               sense_key = 0xf & cmd->err_info->SenseInfo[2];
-                               /* no status or recovered error */
-                               if ((sense_key == 0x0) || (sense_key == 0x1)) {
-                                       status = 1;
-                               }
-                       } else {
-                               printk(KERN_WARNING "cciss: cmd %p "
-                                      "has SCSI Status 0x%x\n",
-                                      cmd, cmd->err_info->ScsiStatus);
-                       }
-                       break;
-               case CMD_DATA_UNDERRUN:
+       switch (cmd->err_info->CommandStatus) {
+       case CMD_TARGET_STATUS:
+               rq->errors = evaluate_target_status(cmd);
+               break;
+       case CMD_DATA_UNDERRUN:
+               if (blk_fs_request(cmd->rq)) {
                        printk(KERN_WARNING "cciss: cmd %p has"
                               " completed with data underrun "
                               "reported\n", cmd);
-                       break;
-               case CMD_DATA_OVERRUN:
+                       cmd->rq->data_len = cmd->err_info->ResidualCnt;
+               }
+               break;
+       case CMD_DATA_OVERRUN:
+               if (blk_fs_request(cmd->rq))
                        printk(KERN_WARNING "cciss: cmd %p has"
                               " completed with data overrun "
                               "reported\n", cmd);
-                       break;
-               case CMD_INVALID:
-                       printk(KERN_WARNING "cciss: cmd %p is "
-                              "reported invalid\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_PROTOCOL_ERR:
-                       printk(KERN_WARNING "cciss: cmd %p has "
-                              "protocol error \n", cmd);
-                       status = 0;
-                       break;
-               case CMD_HARDWARE_ERR:
-                       printk(KERN_WARNING "cciss: cmd %p had "
-                              " hardware error\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_CONNECTION_LOST:
-                       printk(KERN_WARNING "cciss: cmd %p had "
-                              "connection lost\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_ABORTED:
-                       printk(KERN_WARNING "cciss: cmd %p was "
-                              "aborted\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_ABORT_FAILED:
-                       printk(KERN_WARNING "cciss: cmd %p reports "
-                              "abort failed\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_UNSOLICITED_ABORT:
-                       printk(KERN_WARNING "cciss%d: unsolicited "
-                              "abort %p\n", h->ctlr, cmd);
-                       if (cmd->retry_count < MAX_CMD_RETRIES) {
-                               retry_cmd = 1;
-                               printk(KERN_WARNING
-                                      "cciss%d: retrying %p\n", h->ctlr, cmd);
-                               cmd->retry_count++;
-                       } else
-                               printk(KERN_WARNING
-                                      "cciss%d: %p retried too "
-                                      "many times\n", h->ctlr, cmd);
-                       status = 0;
-                       break;
-               case CMD_TIMEOUT:
-                       printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
-                       status = 0;
-                       break;
-               default:
-                       printk(KERN_WARNING "cciss: cmd %p returned "
-                              "unknown status %x\n", cmd,
-                              cmd->err_info->CommandStatus);
-                       status = 0;
-               }
+               break;
+       case CMD_INVALID:
+               printk(KERN_WARNING "cciss: cmd %p is "
+                      "reported invalid\n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_PROTOCOL_ERR:
+               printk(KERN_WARNING "cciss: cmd %p has "
+                      "protocol error \n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_HARDWARE_ERR:
+               printk(KERN_WARNING "cciss: cmd %p had "
+                      " hardware error\n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_CONNECTION_LOST:
+               printk(KERN_WARNING "cciss: cmd %p had "
+                      "connection lost\n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_ABORTED:
+               printk(KERN_WARNING "cciss: cmd %p was "
+                      "aborted\n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_ABORT_FAILED:
+               printk(KERN_WARNING "cciss: cmd %p reports "
+                      "abort failed\n", cmd);
+               rq->errors = 1;
+               break;
+       case CMD_UNSOLICITED_ABORT:
+               printk(KERN_WARNING "cciss%d: unsolicited "
+                      "abort %p\n", h->ctlr, cmd);
+               if (cmd->retry_count < MAX_CMD_RETRIES) {
+                       retry_cmd = 1;
+                       printk(KERN_WARNING
+                              "cciss%d: retrying %p\n", h->ctlr, cmd);
+                       cmd->retry_count++;
+               } else
+                       printk(KERN_WARNING
+                              "cciss%d: %p retried too "
+                              "many times\n", h->ctlr, cmd);
+               rq->errors = 1;
+               break;
+       case CMD_TIMEOUT:
+               printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
+               rq->errors = 1;
+               break;
+       default:
+               printk(KERN_WARNING "cciss: cmd %p returned "
+                      "unknown status %x\n", cmd,
+                      cmd->err_info->CommandStatus);
+               rq->errors = 1;
        }
+
+after_error_processing:
+
        /* We need to return this command */
        if (retry_cmd) {
                resend_cciss_cmd(h, cmd);
                return;
        }
-
+       cmd->rq->data_len = 0;
        cmd->rq->completion_data = cmd;
-       cmd->rq->errors = status;
        blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
        blk_complete_request(cmd->rq);
 }
@@ -2539,32 +2595,40 @@ static void do_cciss_request(request_queue_t *q)
 #endif                         /* CCISS_DEBUG */
 
        c->Header.SGList = c->Header.SGTotal = seg;
-       if(h->cciss_read == CCISS_READ_10) {
-               c->Request.CDB[1] = 0;
-               c->Request.CDB[2] = (start_blk >> 24) & 0xff;   //MSB
-               c->Request.CDB[3] = (start_blk >> 16) & 0xff;
-               c->Request.CDB[4] = (start_blk >> 8) & 0xff;
-               c->Request.CDB[5] = start_blk & 0xff;
-               c->Request.CDB[6] = 0;  // (sect >> 24) & 0xff; MSB
-               c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
-               c->Request.CDB[8] = creq->nr_sectors & 0xff;
-               c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+       if (likely(blk_fs_request(creq))) {
+               if(h->cciss_read == CCISS_READ_10) {
+                       c->Request.CDB[1] = 0;
+                       c->Request.CDB[2] = (start_blk >> 24) & 0xff;   //MSB
+                       c->Request.CDB[3] = (start_blk >> 16) & 0xff;
+                       c->Request.CDB[4] = (start_blk >> 8) & 0xff;
+                       c->Request.CDB[5] = start_blk & 0xff;
+                       c->Request.CDB[6] = 0;  // (sect >> 24) & 0xff; MSB
+                       c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
+                       c->Request.CDB[8] = creq->nr_sectors & 0xff;
+                       c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+               } else {
+                       c->Request.CDBLen = 16;
+                       c->Request.CDB[1]= 0;
+                       c->Request.CDB[2]= (start_blk >> 56) & 0xff;    //MSB
+                       c->Request.CDB[3]= (start_blk >> 48) & 0xff;
+                       c->Request.CDB[4]= (start_blk >> 40) & 0xff;
+                       c->Request.CDB[5]= (start_blk >> 32) & 0xff;
+                       c->Request.CDB[6]= (start_blk >> 24) & 0xff;
+                       c->Request.CDB[7]= (start_blk >> 16) & 0xff;
+                       c->Request.CDB[8]= (start_blk >>  8) & 0xff;
+                       c->Request.CDB[9]= start_blk & 0xff;
+                       c->Request.CDB[10]= (creq->nr_sectors >>  24) & 0xff;
+                       c->Request.CDB[11]= (creq->nr_sectors >>  16) & 0xff;
+                       c->Request.CDB[12]= (creq->nr_sectors >>  8) & 0xff;
+                       c->Request.CDB[13]= creq->nr_sectors & 0xff;
+                       c->Request.CDB[14] = c->Request.CDB[15] = 0;
+               }
+       } else if (blk_pc_request(creq)) {
+               c->Request.CDBLen = creq->cmd_len;
+               memcpy(c->Request.CDB, creq->cmd, BLK_MAX_CDB);
        } else {
-               c->Request.CDBLen = 16;
-               c->Request.CDB[1]= 0;
-               c->Request.CDB[2]= (start_blk >> 56) & 0xff;    //MSB
-               c->Request.CDB[3]= (start_blk >> 48) & 0xff;
-               c->Request.CDB[4]= (start_blk >> 40) & 0xff;
-               c->Request.CDB[5]= (start_blk >> 32) & 0xff;
-               c->Request.CDB[6]= (start_blk >> 24) & 0xff;
-               c->Request.CDB[7]= (start_blk >> 16) & 0xff;
-               c->Request.CDB[8]= (start_blk >>  8) & 0xff;
-               c->Request.CDB[9]= start_blk & 0xff;
-               c->Request.CDB[10]= (creq->nr_sectors >>  24) & 0xff;
-               c->Request.CDB[11]= (creq->nr_sectors >>  16) & 0xff;
-               c->Request.CDB[12]= (creq->nr_sectors >>  8) & 0xff;
-               c->Request.CDB[13]= creq->nr_sectors & 0xff;
-               c->Request.CDB[14] = c->Request.CDB[15] = 0;
+               printk(KERN_WARNING "cciss%d: bad request type %d\n", h->ctlr, creq->cmd_type);
+               BUG();
        }
 
        spin_lock_irq(q->queue_lock);
index bb15051ffbe0d316182cbb9ef11d9dba9b8f64c0..90961a8ea8953f4b44c4aafeac544a7421d4c437 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <asm/atomic.h>
 
-#include <scsi/scsi.h> 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h> 
index 5231ed7e723f0a1ef34ca61684e0ef563b2bc468..3587cb434371f10a3219b9405a1dc6225cff93c9 100644 (file)
@@ -4334,7 +4334,10 @@ static int __init floppy_init(void)
                if (err)
                        goto out_flush_work;
 
-               device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
+               err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
+               if (err)
+                       goto out_unreg_platform_dev;
+
                /* to be cleaned up... */
                disks[drive]->private_data = (void *)(long)drive;
                disks[drive]->queue = floppy_queue;
@@ -4345,6 +4348,8 @@ static int __init floppy_init(void)
 
        return 0;
 
+out_unreg_platform_dev:
+       platform_device_unregister(&floppy_device[drive]);
 out_flush_work:
        flush_scheduled_work();
        if (usage_count)
index 0d4ccd4a09574fdfa3b72533b2fc333bfb191462..18cdd8c7762693d659bcc58c6e42b20e7b0e39dc 100644 (file)
@@ -77,9 +77,8 @@
 
 #include <asm/uaccess.h>
 
-static int max_loop = 8;
-static struct loop_device *loop_dev;
-static struct gendisk **disks;
+static LIST_HEAD(loop_devices);
+static DEFINE_MUTEX(loop_devices_mutex);
 
 /*
  * Transfer functions
@@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo)
        if (unlikely((loff_t)x != size))
                return -EFBIG;
 
-       set_capacity(disks[lo->lo_number], x);
+       set_capacity(lo->lo_disk, x);
        return 0;                                       
 }
 
@@ -244,17 +243,13 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
                transfer_result = lo_do_transfer(lo, WRITE, page, offset,
                                bvec->bv_page, bv_offs, size, IV);
                if (unlikely(transfer_result)) {
-                       char *kaddr;
-
                        /*
                         * The transfer failed, but we still write the data to
                         * keep prepare/commit calls balanced.
                         */
                        printk(KERN_ERR "loop: transfer error block %llu\n",
                               (unsigned long long)index);
-                       kaddr = kmap_atomic(page, KM_USER0);
-                       memset(kaddr + offset, 0, size);
-                       kunmap_atomic(kaddr, KM_USER0);
+                       zero_user_page(page, offset, size, KM_USER0);
                }
                flush_dcache_page(page);
                ret = aops->commit_write(file, page, offset,
@@ -812,7 +807,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
        lo->lo_queue->queuedata = lo;
        lo->lo_queue->unplug_fn = loop_unplug;
 
-       set_capacity(disks[lo->lo_number], size);
+       set_capacity(lo->lo_disk, size);
        bd_set_size(bdev, size << 9);
 
        set_blocksize(bdev, lo_blocksize);
@@ -832,7 +827,7 @@ out_clr:
        lo->lo_device = NULL;
        lo->lo_backing_file = NULL;
        lo->lo_flags = 0;
-       set_capacity(disks[lo->lo_number], 0);
+       set_capacity(lo->lo_disk, 0);
        invalidate_bdev(bdev);
        bd_set_size(bdev, 0);
        mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
@@ -918,7 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
        invalidate_bdev(bdev);
-       set_capacity(disks[lo->lo_number], 0);
+       set_capacity(lo->lo_disk, 0);
        bd_set_size(bdev, 0);
        mapping_set_gfp_mask(filp->f_mapping, gfp);
        lo->lo_state = Lo_unbound;
@@ -1322,6 +1317,18 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
 }
 #endif
 
+static struct loop_device *loop_find_dev(int number)
+{
+       struct loop_device *lo;
+
+       list_for_each_entry(lo, &loop_devices, lo_list) {
+               if (lo->lo_number == number)
+                       return lo;
+       }
+       return NULL;
+}
+
+static struct loop_device *loop_init_one(int i);
 static int lo_open(struct inode *inode, struct file *file)
 {
        struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1330,6 +1337,11 @@ static int lo_open(struct inode *inode, struct file *file)
        lo->lo_refcnt++;
        mutex_unlock(&lo->lo_ctl_mutex);
 
+       mutex_lock(&loop_devices_mutex);
+       if (!loop_find_dev(lo->lo_number + 1))
+               loop_init_one(lo->lo_number + 1);
+       mutex_unlock(&loop_devices_mutex);
+
        return 0;
 }
 
@@ -1357,8 +1369,9 @@ static struct block_device_operations lo_fops = {
 /*
  * And now the modules code and kernel interface.
  */
+static int max_loop;
 module_param(max_loop, int, 0);
-MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)");
+MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
 
@@ -1383,7 +1396,7 @@ int loop_unregister_transfer(int number)
 
        xfer_funcs[n] = NULL;
 
-       for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) {
+       list_for_each_entry(lo, &loop_devices, lo_list) {
                mutex_lock(&lo->lo_ctl_mutex);
 
                if (lo->lo_encryption == xfer)
@@ -1398,91 +1411,110 @@ int loop_unregister_transfer(int number)
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);
 
-static int __init loop_init(void)
+static struct loop_device *loop_init_one(int i)
 {
-       int     i;
+       struct loop_device *lo;
+       struct gendisk *disk;
 
-       if (max_loop < 1 || max_loop > 256) {
-               printk(KERN_WARNING "loop: invalid max_loop (must be between"
-                                   " 1 and 256), using default (8)\n");
-               max_loop = 8;
-       }
+       lo = kzalloc(sizeof(*lo), GFP_KERNEL);
+       if (!lo)
+               goto out;
+
+       lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
+       if (!lo->lo_queue)
+               goto out_free_dev;
+
+       disk = lo->lo_disk = alloc_disk(1);
+       if (!disk)
+               goto out_free_queue;
+
+       mutex_init(&lo->lo_ctl_mutex);
+       lo->lo_number           = i;
+       lo->lo_thread           = NULL;
+       init_waitqueue_head(&lo->lo_event);
+       spin_lock_init(&lo->lo_lock);
+       disk->major             = LOOP_MAJOR;
+       disk->first_minor       = i;
+       disk->fops              = &lo_fops;
+       disk->private_data      = lo;
+       disk->queue             = lo->lo_queue;
+       sprintf(disk->disk_name, "loop%d", i);
+       add_disk(disk);
+       list_add_tail(&lo->lo_list, &loop_devices);
+       return lo;
+
+out_free_queue:
+       blk_cleanup_queue(lo->lo_queue);
+out_free_dev:
+       kfree(lo);
+out:
+       return ERR_PTR(-ENOMEM);
+}
+
+static void loop_del_one(struct loop_device *lo)
+{
+       del_gendisk(lo->lo_disk);
+       blk_cleanup_queue(lo->lo_queue);
+       put_disk(lo->lo_disk);
+       list_del(&lo->lo_list);
+       kfree(lo);
+}
+
+static struct kobject *loop_probe(dev_t dev, int *part, void *data)
+{
+       unsigned int number = dev & MINORMASK;
+       struct loop_device *lo;
+
+       mutex_lock(&loop_devices_mutex);
+       lo = loop_find_dev(number);
+       if (lo == NULL)
+               lo = loop_init_one(number);
+       mutex_unlock(&loop_devices_mutex);
+
+       *part = 0;
+       if (IS_ERR(lo))
+               return (void *)lo;
+       else
+               return &lo->lo_disk->kobj;
+}
+
+static int __init loop_init(void)
+{
+       struct loop_device *lo;
 
        if (register_blkdev(LOOP_MAJOR, "loop"))
                return -EIO;
+       blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
+                                 THIS_MODULE, loop_probe, NULL, NULL);
 
-       loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL);
-       if (!loop_dev)
-               goto out_mem1;
-       memset(loop_dev, 0, max_loop * sizeof(struct loop_device));
+       lo = loop_init_one(0);
+       if (IS_ERR(lo))
+               goto out;
 
-       disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL);
-       if (!disks)
-               goto out_mem2;
+       if (max_loop) {
+               printk(KERN_INFO "loop: the max_loop option is obsolete "
+                                "and will be removed in March 2008\n");
 
-       for (i = 0; i < max_loop; i++) {
-               disks[i] = alloc_disk(1);
-               if (!disks[i])
-                       goto out_mem3;
        }
-
-       for (i = 0; i < max_loop; i++) {
-               struct loop_device *lo = &loop_dev[i];
-               struct gendisk *disk = disks[i];
-
-               memset(lo, 0, sizeof(*lo));
-               lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
-               if (!lo->lo_queue)
-                       goto out_mem4;
-               mutex_init(&lo->lo_ctl_mutex);
-               lo->lo_number = i;
-               lo->lo_thread = NULL;
-               init_waitqueue_head(&lo->lo_event);
-               spin_lock_init(&lo->lo_lock);
-               disk->major = LOOP_MAJOR;
-               disk->first_minor = i;
-               disk->fops = &lo_fops;
-               sprintf(disk->disk_name, "loop%d", i);
-               disk->private_data = lo;
-               disk->queue = lo->lo_queue;
-       }
-
-       /* We cannot fail after we call this, so another loop!*/
-       for (i = 0; i < max_loop; i++)
-               add_disk(disks[i]);
-       printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
+       printk(KERN_INFO "loop: module loaded\n");
        return 0;
 
-out_mem4:
-       while (i--)
-               blk_cleanup_queue(loop_dev[i].lo_queue);
-       i = max_loop;
-out_mem3:
-       while (i--)
-               put_disk(disks[i]);
-       kfree(disks);
-out_mem2:
-       kfree(loop_dev);
-out_mem1:
+out:
        unregister_blkdev(LOOP_MAJOR, "loop");
        printk(KERN_ERR "loop: ran out of memory\n");
        return -ENOMEM;
 }
 
-static void loop_exit(void)
+static void __exit loop_exit(void)
 {
-       int i;
+       struct loop_device *lo, *next;
 
-       for (i = 0; i < max_loop; i++) {
-               del_gendisk(disks[i]);
-               blk_cleanup_queue(loop_dev[i].lo_queue);
-               put_disk(disks[i]);
-       }
+       list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+               loop_del_one(lo);
+
+       blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
        if (unregister_blkdev(LOOP_MAJOR, "loop"))
                printk(KERN_WARNING "loop: cannot unregister blkdev\n");
-
-       kfree(disks);
-       kfree(loop_dev);
 }
 
 module_init(loop_init);
index 090796bef78f16374f8c94f2bf70e23e602deabd..069ae39a9cd9023eb62d9115f2885383c2df86ef 100644 (file)
@@ -366,20 +366,25 @@ static struct disk_attribute pid_attr = {
        .show = pid_show,
 };
 
-static void nbd_do_it(struct nbd_device *lo)
+static int nbd_do_it(struct nbd_device *lo)
 {
        struct request *req;
+       int ret;
 
        BUG_ON(lo->magic != LO_MAGIC);
 
        lo->pid = current->pid;
-       sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
+       ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
+       if (ret) {
+               printk(KERN_ERR "nbd: sysfs_create_file failed!");
+               return ret;
+       }
 
        while ((req = nbd_read_stat(lo)) != NULL)
                nbd_end_request(req);
 
        sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
-       return;
+       return 0;
 }
 
 static void nbd_clear_que(struct nbd_device *lo)
@@ -569,7 +574,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        case NBD_DO_IT:
                if (!lo->file)
                        return -EINVAL;
-               nbd_do_it(lo);
+               error = nbd_do_it(lo);
+               if (error)
+                       return error;
                /* on return tidy up in case we have a signal */
                /* Forcibly shutdown the socket causing all listeners
                 * to error
index 43d4ebcb3b4410b6f1218e22df8cbee482744a39..a1512da3241069b7abc5f7395da5a098fdc57e0b 100644 (file)
@@ -151,7 +151,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page,
 }
 
 /*
- * ->writepage to the the blockdev's mapping has to redirty the page so that the
+ * ->writepage to the blockdev's mapping has to redirty the page so that the
  * VM doesn't go and steal it.  We return AOP_WRITEPAGE_ACTIVATE so that the VM
  * won't try to (pointlessly) write the page again for a while.
  *
index 5872036e8ae6b90f36b2c29789c826755f0d7903..6f5d6203d725a510eb4f82dc2ab7a82409b03549 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
index a26d91743b24221b311c21a46c0d3d188325680a..2df42fdcdc91d5ae87991f1de54de44b756ab040 100644 (file)
@@ -127,7 +127,7 @@ config ROCKETPORT
 
 config CYCLADES
        tristate "Cyclades async mux support"
-       depends on SERIAL_NONSTANDARD
+       depends on SERIAL_NONSTANDARD && (PCI || ISA)
        ---help---
          This driver supports Cyclades Z and Y multiserial boards.
          You would need something like this to connect more than two modems to
@@ -631,7 +631,8 @@ config HVC_CONSOLE
 
 config HVC_ISERIES
        bool "iSeries Hypervisor Virtual Console support"
-       depends on PPC_ISERIES && !VIOCONS
+       depends on PPC_ISERIES
+       default y
        select HVC_DRIVER
        help
          iSeries machines support a hypervisor virtual console.
@@ -1071,5 +1072,11 @@ config TELCLOCK
          /sys/devices/platform/telco_clock, with a number of files for
          controlling the behavior of this hardware.
 
+config DEVPORT
+       bool
+       depends on !M68K
+       depends on ISA || PCI
+       default y
+
 endmenu
 
index 91b062126a686edd0af2c2e2e564c2f4a9181d81..42c0a600b1ac66102d9a5ea7c95266d28edace13 100644 (file)
@@ -613,7 +613,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
                uninorth_node = of_find_node_by_name(NULL, "u3");
        }
        if (uninorth_node) {
-               const int *revprop = get_property(uninorth_node,
+               const int *revprop = of_get_property(uninorth_node,
                                "device-rev", NULL);
                if (revprop != NULL)
                        uninorth_rev = *revprop & 0x3f;
index 0e2b72f2b8871d96f124581bba1ee724c2f936c0..4eaceabd8cea6c09818f527c9816c24e1f29f3c3 100644 (file)
@@ -1574,7 +1574,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
@@ -1700,7 +1700,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
                schedule();
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->open_wait, &wait);
        if (extra_count)
                state->count++;
index c70d52ace8b2da72237bbe7bd38a1f36a6d3d726..ed53f541d9e8a90e2aa4d06cd4952a1372512013 100644 (file)
@@ -206,7 +206,7 @@ static int __init briq_panel_init(void)
        const char *machine;
        int i;
 
-       machine = get_property(root, "model", NULL);
+       machine = of_get_property(root, "model", NULL);
        if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) {
                of_node_put(root);
                return -ENODEV;
index b99b7561260dca1eeea4472bb95f3a087c9f688a..fd40b959afddd92c18a1924d74b24f14551df6b2 100644 (file)
@@ -626,10 +626,10 @@ conv_uni_to_pc(struct vc_data *conp, long ucs)
   
        /* Only 16-bit codes supported at this time */
        if (ucs > 0xffff)
-               ucs = 0xfffd;           /* U+FFFD: REPLACEMENT CHARACTER */
-       else if (ucs < 0x20 || ucs >= 0xfffe)
+               return -4;              /* Not found */
+       else if (ucs < 0x20)
                return -1;              /* Not a printable character */
-       else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
+       else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
                return -2;                      /* Zero-width space */
        /*
         * UNI_DIRECT_BASE indicates the start of the region in the User Zone
index c02d9e99e0501737ce909c30ab5292b28b72ef9d..fe6d2407baed4365250de2357d39fa75cff81991 100644 (file)
@@ -44,6 +44,7 @@ static struct pci_device_id divil_pci[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
        { } /* NULL entry */
 };
+MODULE_DEVICE_TABLE(pci, divil_pci);
 
 static struct cdev cs5535_gpio_cdev;
 
index 16dc5d1d3cb4f2715be9889d3e2a8bf822dfefec..c72ee97d3892543f6e8d2ebd053657776bba49dc 100644 (file)
  *
  * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
  * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
- * Currently maintained by Cyclades team <async@cyclades.com>.
  *
- * For Technical support and installation problems, please send e-mail
- * to support@cyclades.com.
+ * Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com>
  *
  * Much of the design and some of the code came from serial.c
  * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
  * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
  * and then fixed as suggested by Michael K. Johnson 12/12/92.
+ * Converted to pci probing and cleaned up by Jiri Slaby.
  *
  * This version supports shared IRQ's (only for PCI boards).
  *
  *
  */
 
-#define CY_VERSION     "2.4"
+#define CY_VERSION     "2.5"
 
 /* If you need to install more boards than NR_CARDS, change the constant
    in the definition below. No other change is necessary to support up to
 #undef CY_ENABLE_MONITORING
 #undef CY_PCI_DEBUG
 
-#if 0
-#define PAUSE __asm__("nop")
-#else
-#define PAUSE do {} while (0)
-#endif
-
 /*
  * Include section 
  */
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#define        CY_LOCK(info,flags)                                     \
-               do {                                            \
-               spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \
-               } while (0)
-
-#define        CY_UNLOCK(info,flags)                                   \
-               do {                                            \
-               spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \
-               } while (0)
-
-#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 
@@ -682,13 +664,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
 #define IS_CYC_Z(card) ((card).num_chips == -1)
 
 #define Z_FPGA_CHECK(card) \
-       ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
+       ((readl(&((struct RUNTIME_9060 __iomem *) \
                ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
 
-#define ISZLOADED(card)        (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
+#define ISZLOADED(card)        (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \
                        ((card).ctl_addr))->mail_box_0)) || \
                        Z_FPGA_CHECK(card)) && \
-                       (ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \
+                       (ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \
                        ((card).base_addr+ID_ADDRESS))->signature)))
 
 #ifndef SERIAL_XMIT_SIZE
@@ -725,8 +707,8 @@ static unsigned int cy_isa_addresses[] = {
 #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
 
 #ifdef MODULE
-static long maddr[NR_CARDS] = { 0, };
-static int irq[NR_CARDS] = { 0, };
+static long maddr[NR_CARDS];
+static int irq[NR_CARDS];
 
 module_param_array(maddr, long, NULL, 0);
 module_param_array(irq, int, NULL, 0);
@@ -739,11 +721,6 @@ module_param_array(irq, int, NULL, 0);
 */
 static struct cyclades_card cy_card[NR_CARDS];
 
-/* This is the per-channel data structure containing pointers, flags
- and variables for the port. This driver supports a maximum of NR_PORTS.
-*/
-static struct cyclades_port cy_port[NR_PORTS];
-
 static int cy_next_channel;    /* next minor available */
 
 /*
@@ -825,9 +802,6 @@ static int cy_chip_offset[] = { 0x0000,
 
 /* PCI related definitions */
 
-static unsigned short cy_pci_nboard;
-static unsigned short cy_isa_nboard;
-static unsigned short cy_nboard;
 #ifdef CONFIG_PCI
 static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
        { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },      /* PCI < 1Mb */
@@ -845,7 +819,7 @@ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
 
 static void cy_start(struct tty_struct *);
 static void set_line_char(struct cyclades_port *);
-static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
+static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
 #ifdef CONFIG_ISA
 static unsigned detect_isa_irq(void __iomem *);
 #endif                         /* CONFIG_ISA */
@@ -858,7 +832,6 @@ static void cyz_poll(unsigned long);
 /* The Cyclades-Z polling cycle is defined by this variable */
 static long cyz_polling_cycle = CZ_DEF_POLL;
 
-static int cyz_timeron = 0;
 static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
 
 #else                          /* CONFIG_CYZ_INTR */
@@ -871,21 +844,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
 {
 #ifdef SERIAL_PARANOIA_CHECK
        if (!info) {
-               printk("cyc Warning: null cyclades_port for (%s) in %s\n",
-                               name, routine);
-               return 1;
-       }
-
-       if ((long)info < (long)(&cy_port[0]) ||
-                       (long)(&cy_port[NR_PORTS]) < (long)info) {
-               printk("cyc Warning: cyclades_port out of range for (%s) in "
-                               "%s\n", name, routine);
+               printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
+                               "in %s\n", name, routine);
                return 1;
        }
 
        if (info->magic != CYCLADES_MAGIC) {
-               printk("cyc Warning: bad magic number for serial struct (%s) "
-                               "in %s\n", name, routine);
+               printk(KERN_WARNING "cyc Warning: bad magic number for serial "
+                               "struct (%s) in %s\n", name, routine);
                return 1;
        }
 #endif
@@ -943,22 +909,16 @@ do_softint(struct work_struct *work)
        if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event))
                wake_up_interruptible(&info->open_wait);
 #ifdef CONFIG_CYZ_INTR
-       if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
-               if (cyz_rx_full_timer[info->line].function == NULL) {
-                       cyz_rx_full_timer[info->line].expires = jiffies + 1;
-                       cyz_rx_full_timer[info->line].function = cyz_rx_restart;
-                       cyz_rx_full_timer[info->line].data =
-                                               (unsigned long)info;
-                       add_timer(&cyz_rx_full_timer[info->line]);
-               }
-       }
+       if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event) &&
+                       !timer_pending(&cyz_rx_full_timer[info->line]))
+               mod_timer(&cyz_rx_full_timer[info->line], jiffies + 1);
 #endif
        if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event))
                wake_up_interruptible(&info->delta_msr_wait);
        tty_wakeup(tty);
 #ifdef Z_WAKE
        if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event))
-               wake_up_interruptible(&info->shutdown_wait);
+               complete(&info->shutdown_wait);
 #endif
 } /* do_softint */
 
@@ -975,11 +935,11 @@ do_softint(struct work_struct *work)
  */
 static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
 {
-       volatile int i;
+       unsigned int i;
 
        /* Check to see that the previous command has completed */
        for (i = 0; i < 100; i++) {
-               if (cy_readb(base_addr + (CyCCR << index)) == 0) {
+               if (readb(base_addr + (CyCCR << index)) == 0) {
                        break;
                }
                udelay(10L);
@@ -1022,7 +982,7 @@ static unsigned detect_isa_irq(void __iomem * address)
 
        cy_writeb(address + (CyCAR << index), 0);
        cy_writeb(address + (CySRER << index),
-                 cy_readb(address + (CySRER << index)) | CyTxRdy);
+                 readb(address + (CySRER << index)) | CyTxRdy);
        local_irq_restore(flags);
 
        /* Wait ... */
@@ -1032,11 +992,11 @@ static unsigned detect_isa_irq(void __iomem * address)
        irq = probe_irq_off(irqs);
 
        /* Clean up */
-       save_xir = (u_char) cy_readb(address + (CyTIR << index));
-       save_car = cy_readb(address + (CyCAR << index));
+       save_xir = (u_char) readb(address + (CyTIR << index));
+       save_car = readb(address + (CyCAR << index));
        cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
        cy_writeb(address + (CySRER << index),
-                 cy_readb(address + (CySRER << index)) & ~CyTxRdy);
+                 readb(address + (CySRER << index)) & ~CyTxRdy);
        cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
        cy_writeb(address + (CyCAR << index), (save_car));
        cy_writeb(address + (Cy_ClrIntr << index), 0);
@@ -1051,45 +1011,43 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
 {
        struct cyclades_port *info;
        struct tty_struct *tty;
-       volatile int char_count;
-       int i, j, len, mdm_change, mdm_status, outch;
+       int char_count;
+       int j, len, mdm_change, mdm_status, outch;
        int save_xir, channel, save_car;
        char data;
 
        if (status & CySRReceive) {     /* reception interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
+               printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
 #endif
                /* determine the channel & change to that context */
                spin_lock(&cinfo->card_lock);
-               save_xir = (u_char) cy_readb(base_addr + (CyRIR << index));
+               save_xir = (u_char) readb(base_addr + (CyRIR << index));
                channel = (u_short) (save_xir & CyIRChannel);
-               i = channel + chip * 4 + cinfo->first_line;
-               info = &cy_port[i];
-               info->last_active = jiffies;
-               save_car = cy_readb(base_addr + (CyCAR << index));
+               info = &cinfo->ports[channel + chip * 4];
+               save_car = readb(base_addr + (CyCAR << index));
                cy_writeb(base_addr + (CyCAR << index), save_xir);
 
                /* if there is nowhere to put the data, discard it */
-               if (info->tty == 0) {
-                       j = (cy_readb(base_addr + (CyRIVR << index)) &
+               if (info->tty == NULL) {
+                       j = (readb(base_addr + (CyRIVR << index)) &
                                CyIVRMask);
                        if (j == CyIVRRxEx) {   /* exception */
-                               data = cy_readb(base_addr + (CyRDSR << index));
+                               data = readb(base_addr + (CyRDSR << index));
                        } else {        /* normal character reception */
-                               char_count = cy_readb(base_addr +
+                               char_count = readb(base_addr +
                                                (CyRDCR << index));
                                while (char_count--) {
-                                       data = cy_readb(base_addr +
+                                       data = readb(base_addr +
                                                (CyRDSR << index));
                                }
                        }
                } else {        /* there is an open port for this data */
                        tty = info->tty;
-                       j = (cy_readb(base_addr + (CyRIVR << index)) &
+                       j = (readb(base_addr + (CyRIVR << index)) &
                                        CyIVRMask);
                        if (j == CyIVRRxEx) {   /* exception */
-                               data = cy_readb(base_addr + (CyRDSR << index));
+                               data = readb(base_addr + (CyRDSR << index));
 
                                /* For statistics only */
                                if (data & CyBREAK)
@@ -1110,7 +1068,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                                if (data & CyBREAK) {
                                                        tty_insert_flip_char(
                                                                tty,
-                                                               cy_readb(
+                                                               readb(
                                                                base_addr +
                                                                (CyRDSR <<
                                                                        index)),
@@ -1123,7 +1081,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                                } else if (data & CyFRAME) {
                                                        tty_insert_flip_char(
                                                                tty,
-                                                               cy_readb(
+                                                               readb(
                                                                base_addr +
                                                                (CyRDSR <<
                                                                        index)),
@@ -1135,7 +1093,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                                        /* Pieces of seven... */
                                                        tty_insert_flip_char(
                                                                tty,
-                                                               cy_readb(
+                                                               readb(
                                                                base_addr +
                                                                (CyRDSR <<
                                                                        index)),
@@ -1154,7 +1112,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                                 */
                                                        tty_insert_flip_char(
                                                                tty,
-                                                               cy_readb(
+                                                               readb(
                                                                base_addr +
                                                                (CyRDSR <<
                                                                        index)),
@@ -1186,7 +1144,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                }
                        } else {        /* normal character reception */
                                /* load # chars available from the chip */
-                               char_count = cy_readb(base_addr +
+                               char_count = readb(base_addr +
                                                (CyRDCR << index));
 
 #ifdef CY_ENABLE_MONITORING
@@ -1198,7 +1156,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
 #endif
                                len = tty_buffer_request_room(tty, char_count);
                                while (len--) {
-                                       data = cy_readb(base_addr +
+                                       data = readb(base_addr +
                                                        (CyRDSR << index));
                                        tty_insert_flip_char(tty, data,
                                                        TTY_NORMAL);
@@ -1223,29 +1181,27 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                   is empty, we know we can always stuff a dozen
                   characters. */
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
+               printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
 #endif
 
                /* determine the channel & change to that context */
                spin_lock(&cinfo->card_lock);
-               save_xir = (u_char) cy_readb(base_addr + (CyTIR << index));
+               save_xir = (u_char) readb(base_addr + (CyTIR << index));
                channel = (u_short) (save_xir & CyIRChannel);
-               i = channel + chip * 4 + cinfo->first_line;
-               save_car = cy_readb(base_addr + (CyCAR << index));
+               save_car = readb(base_addr + (CyCAR << index));
                cy_writeb(base_addr + (CyCAR << index), save_xir);
 
                /* validate the port# (as configured and open) */
-               if ((i < 0) || (NR_PORTS <= i)) {
+               if (channel + chip * 4 >= cinfo->nports) {
                        cy_writeb(base_addr + (CySRER << index),
-                                 cy_readb(base_addr + (CySRER << index)) &
+                                 readb(base_addr + (CySRER << index)) &
                                  ~CyTxRdy);
                        goto txend;
                }
-               info = &cy_port[i];
-               info->last_active = jiffies;
-               if (info->tty == 0) {
+               info = &cinfo->ports[channel + chip * 4];
+               if (info->tty == NULL) {
                        cy_writeb(base_addr + (CySRER << index),
-                                 cy_readb(base_addr + (CySRER << index)) &
+                                 readb(base_addr + (CySRER << index)) &
                                  ~CyTxRdy);
                        goto txdone;
                }
@@ -1278,29 +1234,29 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
 
                while (char_count-- > 0) {
                        if (!info->xmit_cnt) {
-                               if (cy_readb(base_addr + (CySRER << index)) &
+                               if (readb(base_addr + (CySRER << index)) &
                                                CyTxMpty) {
                                        cy_writeb(base_addr + (CySRER << index),
-                                               cy_readb(base_addr +
+                                               readb(base_addr +
                                                        (CySRER << index)) &
                                                ~CyTxMpty);
                                } else {
                                        cy_writeb(base_addr + (CySRER << index),
-                                               (cy_readb(base_addr +
+                                               (readb(base_addr +
                                                        (CySRER << index)) &
                                                ~CyTxRdy) | CyTxMpty);
                                }
                                goto txdone;
                        }
-                       if (info->xmit_buf == 0) {
+                       if (info->xmit_buf == NULL) {
                                cy_writeb(base_addr + (CySRER << index),
-                                       cy_readb(base_addr + (CySRER << index))&
+                                       readb(base_addr + (CySRER << index)) &
                                        ~CyTxRdy);
                                goto txdone;
                        }
                        if (info->tty->stopped || info->tty->hw_stopped) {
                                cy_writeb(base_addr + (CySRER << index),
-                                       cy_readb(base_addr + (CySRER << index))&
+                                       readb(base_addr + (CySRER << index)) &
                                        ~CyTxRdy);
                                goto txdone;
                        }
@@ -1333,7 +1289,6 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                                                0);
                                        info->icount.tx++;
                                        char_count--;
-                               } else {
                                }
                        }
                }
@@ -1353,19 +1308,16 @@ txend:
 
                /* determine the channel & change to that context */
                spin_lock(&cinfo->card_lock);
-               save_xir = (u_char) cy_readb(base_addr + (CyMIR << index));
+               save_xir = (u_char) readb(base_addr + (CyMIR << index));
                channel = (u_short) (save_xir & CyIRChannel);
-               info = &cy_port[channel + chip * 4 + cinfo->first_line];
-               info->last_active = jiffies;
-               save_car = cy_readb(base_addr + (CyCAR << index));
+               info = &cinfo->ports[channel + chip * 4];
+               save_car = readb(base_addr + (CyCAR << index));
                cy_writeb(base_addr + (CyCAR << index), save_xir);
 
-               mdm_change = cy_readb(base_addr + (CyMISR << index));
-               mdm_status = cy_readb(base_addr + (CyMSVR1 << index));
+               mdm_change = readb(base_addr + (CyMISR << index));
+               mdm_status = readb(base_addr + (CyMSVR1 << index));
 
-               if (info->tty == 0) {   /* no place for data, ignore it */
-                       ;
-               } else {
+               if (info->tty) {
                        if (mdm_change & CyANY_DELTA) {
                                /* For statistics only */
                                if (mdm_change & CyDCD)
@@ -1398,7 +1350,7 @@ txend:
                                                info->tty->hw_stopped = 0;
                                                cy_writeb(base_addr +
                                                        (CySRER << index),
-                                                       cy_readb(base_addr +
+                                                       readb(base_addr +
                                                                (CySRER <<
                                                                        index))|
                                                        CyTxRdy);
@@ -1412,17 +1364,17 @@ txend:
                                                info->tty->hw_stopped = 1;
                                                cy_writeb(base_addr +
                                                        (CySRER << index),
-                                                       cy_readb(base_addr +
+                                                       readb(base_addr +
                                                                (CySRER <<
                                                                index)) &
                                                        ~CyTxRdy);
                                        }
                                }
                        }
-                       if (mdm_change & CyDSR) {
+/*                     if (mdm_change & CyDSR) {
                        }
                        if (mdm_change & CyRI) {
-                       }
+                       }*/
                }
                /* end of service */
                cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
@@ -1438,16 +1390,16 @@ txend:
 static irqreturn_t cyy_interrupt(int irq, void *dev_id)
 {
        int status;
-       struct cyclades_card *cinfo;
+       struct cyclades_card *cinfo = dev_id;
        void __iomem *base_addr, *card_base_addr;
        int chip;
        int index;
        int too_many;
        int had_work;
 
-       if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+       if (unlikely(cinfo == NULL)) {
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
+               printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq);
 #endif
                return IRQ_NONE;        /* spurious interrupt */
        }
@@ -1455,6 +1407,10 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
        card_base_addr = cinfo->base_addr;
        index = cinfo->bus_index;
 
+       /* card was not initialized yet (e.g. DEBUG_SHIRQ) */
+       if (unlikely(card_base_addr == NULL))
+               return IRQ_HANDLED;
+
        /* This loop checks all chips in the card.  Make a note whenever
           _any_ chip had some work to do, as this is considered an
           indication that there will be more to do.  Only when no chip
@@ -1466,7 +1422,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
                        base_addr = cinfo->base_addr +
                                        (cy_chip_offset[chip] << index);
                        too_many = 0;
-                       while ((status = cy_readb(base_addr +
+                       while ((status = readb(base_addr +
                                                (CySVRR << index))) != 0x00) {
                                had_work++;
                        /* The purpose of the following test is to ensure that
@@ -1498,7 +1454,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
 
 static int
 cyz_fetch_msg(struct cyclades_card *cinfo,
-               uclong * channel, ucchar * cmd, uclong * param)
+               __u32 * channel, __u8 * cmd, __u32 * param)
 {
        struct FIRM_ID __iomem *firm_id;
        struct ZFW_CTRL __iomem *zfw_ctrl;
@@ -1509,16 +1465,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
        if (!ISZLOADED(*cinfo)) {
                return -1;
        }
-       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
-                       0xfffff);
+       zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
-       loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
+       loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *)
                                  (cinfo->ctl_addr))->loc_doorbell);
        if (loc_doorbell) {
                *cmd = (char)(0xff & loc_doorbell);
-               *channel = cy_readl(&board_ctrl->fwcmd_channel);
-               *param = (uclong) cy_readl(&board_ctrl->fwcmd_param);
+               *channel = readl(&board_ctrl->fwcmd_channel);
+               *param = (__u32) readl(&board_ctrl->fwcmd_param);
                cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
                          loc_doorbell, 0xffffffff);
                return 1;
@@ -1528,28 +1483,27 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
 
 static int
 cyz_issue_cmd(struct cyclades_card *cinfo,
-               uclong channel, ucchar cmd, uclong param)
+               __u32 channel, __u8 cmd, __u32 param)
 {
        struct FIRM_ID __iomem *firm_id;
        struct ZFW_CTRL __iomem *zfw_ctrl;
        struct BOARD_CTRL __iomem *board_ctrl;
-       unsigned long __iomem *pci_doorbell;
+       __u32 __iomem *pci_doorbell;
        int index;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
        if (!ISZLOADED(*cinfo)) {
                return -1;
        }
-       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
-                       0xfffff);
+       zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
        index = 0;
        pci_doorbell =
            &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
-       while ((cy_readl(pci_doorbell) & 0xff) != 0) {
+       while ((readl(pci_doorbell) & 0xff) != 0) {
                if (index++ == 1000) {
-                       return (int)(cy_readl(pci_doorbell) & 0xff);
+                       return (int)(readl(pci_doorbell) & 0xff);
                }
                udelay(50L);
        }
@@ -1561,34 +1515,30 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
 }                              /* cyz_issue_cmd */
 
 static void
-cyz_handle_rx(struct cyclades_port *info,
-               volatile struct CH_CTRL __iomem * ch_ctrl,
-               volatile struct BUF_CTRL __iomem * buf_ctrl)
+cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
+               struct BUF_CTRL __iomem *buf_ctrl)
 {
-       struct cyclades_card *cinfo = &cy_card[info->card];
+       struct cyclades_card *cinfo = info->card;
        struct tty_struct *tty = info->tty;
-       volatile int char_count;
+       int char_count;
        int len;
 #ifdef BLOCKMOVE
-       int small_count;
+       unsigned char *buf;
 #else
        char data;
 #endif
-       volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
+       __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
 
-       rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
-       rx_put = cy_readl(&buf_ctrl->rx_put);
-       rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
-       rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
+       rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
+       rx_put = readl(&buf_ctrl->rx_put);
+       rx_bufsize = readl(&buf_ctrl->rx_bufsize);
+       rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
        if (rx_put >= rx_get)
                char_count = rx_put - rx_get;
        else
                char_count = rx_put - rx_get + rx_bufsize;
 
        if (char_count) {
-               info->last_active = jiffies;
-               info->jiffies[1] = jiffies;
-
 #ifdef CY_ENABLE_MONITORING
                info->mon.int_count++;
                info->mon.char_count += char_count;
@@ -1596,7 +1546,7 @@ cyz_handle_rx(struct cyclades_port *info,
                        info->mon.char_max = char_count;
                info->mon.char_last = char_count;
 #endif
-               if (tty == 0) {
+               if (tty == NULL) {
                        /* flush received characters */
                        new_rx_get = (new_rx_get + char_count) &
                                        (rx_bufsize - 1);
@@ -1606,30 +1556,28 @@ cyz_handle_rx(struct cyclades_port *info,
                /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
                   for performance, but because of buffer boundaries, there
                   may be several steps to the operation */
-                       while (0 < (small_count = min_t(unsigned int,
-                                       rx_bufsize - new_rx_get,
-                                       min_t(unsigned int, TTY_FLIPBUF_SIZE -
-                                               tty->flip.count, char_count)))){
-                               memcpy_fromio(tty->flip.char_buf_ptr,
-                                       (char *)(cinfo->base_addr + rx_bufaddr +
-                                               new_rx_get),
-                                       small_count);
+                       while (1) {
+                               len = tty_prepare_flip_string(tty, &buf,
+                                               char_count);
+                               if (!len)
+                                       break;
 
-                               tty->flip.char_buf_ptr += small_count;
-                               memset(tty->flip.flag_buf_ptr, TTY_NORMAL,
-                                       small_count);
-                               tty->flip.flag_buf_ptr += small_count;
-                               new_rx_get = (new_rx_get + small_count) &
+                               len = min_t(unsigned int, min(len, char_count),
+                                               rx_bufsize - new_rx_get);
+
+                               memcpy_fromio(buf, cinfo->base_addr +
+                                               rx_bufaddr + new_rx_get, len);
+
+                               new_rx_get = (new_rx_get + len) &
                                                (rx_bufsize - 1);
-                               char_count -= small_count;
-                               info->icount.rx += small_count;
-                               info->idle_stats.recv_bytes += small_count;
-                               tty->flip.count += small_count;
+                               char_count -= len;
+                               info->icount.rx += len;
+                               info->idle_stats.recv_bytes += len;
                        }
 #else
                        len = tty_buffer_request_room(tty, char_count);
                        while (len--) {
-                               data = cy_readb(cinfo->base_addr + rx_bufaddr +
+                               data = readb(cinfo->base_addr + rx_bufaddr +
                                                new_rx_get);
                                new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1);
                                tty_insert_flip_char(tty, data, TTY_NORMAL);
@@ -1640,13 +1588,12 @@ cyz_handle_rx(struct cyclades_port *info,
 #ifdef CONFIG_CYZ_INTR
                /* Recalculate the number of chars in the RX buffer and issue
                   a cmd in case it's higher than the RX high water mark */
-                       rx_put = cy_readl(&buf_ctrl->rx_put);
+                       rx_put = readl(&buf_ctrl->rx_put);
                        if (rx_put >= rx_get)
                                char_count = rx_put - rx_get;
                        else
                                char_count = rx_put - rx_get + rx_bufsize;
-                       if (char_count >= (int)cy_readl(&buf_ctrl->
-                                       rx_threshold)) {
+                       if (char_count >= (int)readl(&buf_ctrl->rx_threshold)) {
                                cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
                        }
 #endif
@@ -1659,26 +1606,25 @@ cyz_handle_rx(struct cyclades_port *info,
 }
 
 static void
-cyz_handle_tx(struct cyclades_port *info,
-               volatile struct CH_CTRL __iomem * ch_ctrl,
-               volatile struct BUF_CTRL __iomem * buf_ctrl)
+cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
+               struct BUF_CTRL __iomem *buf_ctrl)
 {
-       struct cyclades_card *cinfo = &cy_card[info->card];
+       struct cyclades_card *cinfo = info->card;
        struct tty_struct *tty = info->tty;
        char data;
-       volatile int char_count;
+       int char_count;
 #ifdef BLOCKMOVE
        int small_count;
 #endif
-       volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
+       __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
 
        if (info->xmit_cnt <= 0)        /* Nothing to transmit */
                return;
 
-       tx_get = cy_readl(&buf_ctrl->tx_get);
-       tx_put = cy_readl(&buf_ctrl->tx_put);
-       tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
-       tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
+       tx_get = readl(&buf_ctrl->tx_get);
+       tx_put = readl(&buf_ctrl->tx_put);
+       tx_bufsize = readl(&buf_ctrl->tx_bufsize);
+       tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
        if (tx_put >= tx_get)
                char_count = tx_get - tx_put - 1 + tx_bufsize;
        else
@@ -1686,9 +1632,8 @@ cyz_handle_tx(struct cyclades_port *info,
 
        if (char_count) {
 
-               if (tty == 0) {
+               if (tty == NULL)
                        goto ztxdone;
-               }
 
                if (info->x_char) {     /* send special char */
                        data = info->x_char;
@@ -1698,8 +1643,6 @@ cyz_handle_tx(struct cyclades_port *info,
                        info->x_char = 0;
                        char_count--;
                        info->icount.tx++;
-                       info->last_active = jiffies;
-                       info->jiffies[2] = jiffies;
                }
 #ifdef BLOCKMOVE
                while (0 < (small_count = min_t(unsigned int,
@@ -1719,8 +1662,6 @@ cyz_handle_tx(struct cyclades_port *info,
                        info->xmit_cnt -= small_count;
                        info->xmit_tail = (info->xmit_tail + small_count) &
                                        (SERIAL_XMIT_SIZE - 1);
-                       info->last_active = jiffies;
-                       info->jiffies[2] = jiffies;
                }
 #else
                while (info->xmit_cnt && char_count) {
@@ -1733,8 +1674,6 @@ cyz_handle_tx(struct cyclades_port *info,
                        tx_put = (tx_put + 1) & (tx_bufsize - 1);
                        char_count--;
                        info->icount.tx++;
-                       info->last_active = jiffies;
-                       info->jiffies[2] = jiffies;
                }
 #endif
 ztxdone:
@@ -1750,33 +1689,32 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 {
        struct tty_struct *tty;
        struct cyclades_port *info;
-       static volatile struct FIRM_ID __iomem *firm_id;
-       static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
-       static volatile struct BOARD_CTRL __iomem *board_ctrl;
-       static volatile struct CH_CTRL __iomem *ch_ctrl;
-       static volatile struct BUF_CTRL __iomem *buf_ctrl;
-       uclong channel;
-       ucchar cmd;
-       uclong param;
-       uclong hw_ver, fw_ver;
+       static struct FIRM_ID __iomem *firm_id;
+       static struct ZFW_CTRL __iomem *zfw_ctrl;
+       static struct BOARD_CTRL __iomem *board_ctrl;
+       static struct CH_CTRL __iomem *ch_ctrl;
+       static struct BUF_CTRL __iomem *buf_ctrl;
+       __u32 channel;
+       __u8 cmd;
+       __u32 param;
+       __u32 hw_ver, fw_ver;
        int special_count;
        int delta_count;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
-       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
-                       0xfffff);
+       zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
-       fw_ver = cy_readl(&board_ctrl->fw_version);
-       hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
+       fw_ver = readl(&board_ctrl->fw_version);
+       hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
                        mail_box_0);
 
        while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
                special_count = 0;
                delta_count = 0;
-               info = &cy_port[channel + cinfo->first_line];
-               if ((tty = info->tty) == 0) {
+               info = &cinfo->ports[channel];
+               if ((tty = info->tty) == NULL)
                        continue;
-               }
+
                ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
                buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
 
@@ -1801,7 +1739,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                        delta_count++;
                        if (info->flags & ASYNC_CHECK_CD) {
                                if ((fw_ver > 241 ? ((u_long) param) :
-                                               cy_readl(&ch_ctrl->rs_status)) &
+                                               readl(&ch_ctrl->rs_status)) &
                                                C_RS_DCD) {
                                        cy_sched_event(info,
                                                        Cy_EVENT_OPEN_WAKEUP);
@@ -1833,8 +1771,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                case C_CM_INTBACK2:
                        /* Reception Interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-                       printk("cyz_interrupt: rcvd intr, card %d, "
-                                       "port %ld\n\r", info->card, channel);
+                       printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
+                                       "port %ld\n", info->card, channel);
 #endif
                        cyz_handle_rx(info, ch_ctrl, buf_ctrl);
                        break;
@@ -1843,8 +1781,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                case C_CM_INTBACK:
                        /* Transmission Interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-                       printk("cyz_interrupt: xmit intr, card %d, "
-                                       "port %ld\n\r", info->card, channel);
+                       printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
+                                       "port %ld\n", info->card, channel);
 #endif
                        cyz_handle_tx(info, ch_ctrl, buf_ctrl);
                        break;
@@ -1865,18 +1803,19 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 #ifdef CONFIG_CYZ_INTR
 static irqreturn_t cyz_interrupt(int irq, void *dev_id)
 {
-       struct cyclades_card *cinfo;
+       struct cyclades_card *cinfo = dev_id;
 
-       if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+       if (unlikely(cinfo == NULL)) {
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+               printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",irq);
 #endif
                return IRQ_NONE;        /* spurious interrupt */
        }
 
-       if (!ISZLOADED(*cinfo)) {
+       if (unlikely(!ISZLOADED(*cinfo))) {
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
+               printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
+                               "(IRQ%d).\n", irq);
 #endif
                return IRQ_NONE;
        }
@@ -1890,19 +1829,18 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id)
 static void cyz_rx_restart(unsigned long arg)
 {
        struct cyclades_port *info = (struct cyclades_port *)arg;
+       struct cyclades_card *card = info->card;
        int retval;
-       int card = info->card;
-       uclong channel = (info->line) - (cy_card[card].first_line);
+       __u32 channel = info->line - card->first_line;
        unsigned long flags;
 
-       CY_LOCK(info, flags);
-       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
+       spin_lock_irqsave(&card->card_lock, flags);
+       retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
        if (retval != 0) {
-               printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n",
+               printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
                        info->line, retval);
        }
-       cyz_rx_full_timer[info->line].function = NULL;
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
 }
 
 #else                          /* CONFIG_CYZ_INTR */
@@ -1912,14 +1850,14 @@ static void cyz_poll(unsigned long arg)
        struct cyclades_card *cinfo;
        struct cyclades_port *info;
        struct tty_struct *tty;
-       static volatile struct FIRM_ID *firm_id;
-       static volatile struct ZFW_CTRL *zfw_ctrl;
-       static volatile struct BOARD_CTRL *board_ctrl;
-       static volatile struct CH_CTRL *ch_ctrl;
-       static volatile struct BUF_CTRL *buf_ctrl;
+       static struct FIRM_ID *firm_id;
+       static struct ZFW_CTRL *zfw_ctrl;
+       static struct BOARD_CTRL *board_ctrl;
+       static struct CH_CTRL *ch_ctrl;
+       static struct BUF_CTRL *buf_ctrl;
+       unsigned long expires = jiffies + HZ;
        int card, port;
 
-       cyz_timerlist.expires = jiffies + (HZ);
        for (card = 0; card < NR_CARDS; card++) {
                cinfo = &cy_card[card];
 
@@ -1930,12 +1868,12 @@ static void cyz_poll(unsigned long arg)
 
                firm_id = cinfo->base_addr + ID_ADDRESS;
                zfw_ctrl = cinfo->base_addr +
-                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+                               (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                board_ctrl = &(zfw_ctrl->board_ctrl);
 
        /* Skip first polling cycle to avoid racing conditions with the FW */
                if (!cinfo->intr_enabled) {
-                       cinfo->nports = (int)cy_readl(&board_ctrl->n_channel);
+                       cinfo->nports = (int)readl(&board_ctrl->n_channel);
                        cinfo->intr_enabled = 1;
                        continue;
                }
@@ -1943,7 +1881,7 @@ static void cyz_poll(unsigned long arg)
                cyz_handle_cmd(cinfo);
 
                for (port = 0; port < cinfo->nports; port++) {
-                       info = &cy_port[port + cinfo->first_line];
+                       info = &cinfo->ports[port];
                        tty = info->tty;
                        ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
                        buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
@@ -1953,9 +1891,9 @@ static void cyz_poll(unsigned long arg)
                        cyz_handle_tx(info, ch_ctrl, buf_ctrl);
                }
                /* poll every 'cyz_polling_cycle' period */
-               cyz_timerlist.expires = jiffies + cyz_polling_cycle;
+               expires = jiffies + cyz_polling_cycle;
        }
-       add_timer(&cyz_timerlist);
+       mod_timer(&cyz_timerlist, expires);
 }                              /* cyz_poll */
 
 #endif                         /* CONFIG_CYZ_INTR */
@@ -1968,20 +1906,21 @@ static void cyz_poll(unsigned long arg)
  */
 static int startup(struct cyclades_port *info)
 {
+       struct cyclades_card *card;
        unsigned long flags;
        int retval = 0;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
        unsigned long page;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
+       channel = info->line - card->first_line;
 
        page = get_zeroed_page(GFP_KERNEL);
        if (!page)
                return -ENOMEM;
 
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&card->card_lock, flags);
 
        if (info->flags & ASYNC_INITIALIZED) {
                free_page(page);
@@ -2001,24 +1940,22 @@ static int startup(struct cyclades_port *info)
        else
                info->xmit_buf = (unsigned char *)page;
 
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
 
        set_line_char(info);
 
-       if (!IS_CYC_Z(cy_card[card])) {
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr = cy_card[card].base_addr +
-                               (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 #ifdef CY_DEBUG_OPEN
-               printk("cyc startup card %d, chip %d, channel %d, "
-                               "base_addr %lx\n",
-                               card, chip, channel, (long)base_addr);
-               /**/
+               printk(KERN_DEBUG "cyc startup card %d, chip %d, channel %d, "
+                               "base_addr %p\n",
+                               card, chip, channel, base_addr);
 #endif
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
 
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
 
@@ -2034,14 +1971,14 @@ static int startup(struct cyclades_port *info)
                cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
 
 #ifdef CY_DEBUG_DTR
-               printk("cyc:startup raising DTR\n");
-               printk("     status: 0x%x, 0x%x\n",
-                       cy_readb(base_addr + (CyMSVR1 << index)),
-                       cy_readb(base_addr + (CyMSVR2 << index)));
+               printk(KERN_DEBUG "cyc:startup raising DTR\n");
+               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                       readb(base_addr + (CyMSVR1 << index)),
+                       readb(base_addr + (CyMSVR2 << index)));
 #endif
 
                cy_writeb(base_addr + (CySRER << index),
-                       cy_readb(base_addr + (CySRER << index)) | CyRxData);
+                       readb(base_addr + (CySRER << index)) | CyRxData);
                info->flags |= ASYNC_INITIALIZED;
 
                if (info->tty) {
@@ -2054,7 +1991,7 @@ static int startup(struct cyclades_port *info)
                info->idle_stats.recv_idle =
                info->idle_stats.xmit_idle = jiffies;
 
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
 
        } else {
                struct FIRM_ID __iomem *firm_id;
@@ -2063,24 +2000,23 @@ static int startup(struct cyclades_port *info)
                struct CH_CTRL __iomem *ch_ctrl;
                int retval;
 
-               base_addr = cy_card[card].base_addr;
+               base_addr = card->base_addr;
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(cy_card[card])) {
+               if (!ISZLOADED(*card)) {
                        return -ENODEV;
                }
 
-               zfw_ctrl = cy_card[card].base_addr +
-                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               zfw_ctrl = card->base_addr +
+                               (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = zfw_ctrl->ch_ctrl;
 
 #ifdef CY_DEBUG_OPEN
-               printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
-                       card, channel, (long)base_addr);
-               /**/
+               printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
+                       "base_addr %p\n", card, channel, base_addr);
 #endif
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
 
                cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
 #ifdef Z_WAKE
@@ -2102,33 +2038,31 @@ static int startup(struct cyclades_port *info)
 #endif                         /* CONFIG_CYZ_INTR */
 #endif                         /* Z_WAKE */
 
-               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
                if (retval != 0) {
-                       printk("cyc:startup(1) retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
+                               "%x\n", info->line, retval);
                }
 
                /* Flush RX buffers before raising DTR and RTS */
-               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX,
-                               0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
                if (retval != 0) {
-                       printk("cyc:startup(2) retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
+                               "%x\n", info->line, retval);
                }
 
                /* set timeout !!! */
                /* set RTS and DTR !!! */
                cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
+                       readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
                        C_RS_DTR);
-               retval = cyz_issue_cmd(&cy_card[info->card], channel,
-                               C_CM_IOCTLM, 0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
                if (retval != 0) {
-                       printk("cyc:startup(3) retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
+                               "%x\n", info->line, retval);
                }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:startup raising Z DTR\n");
+               printk(KERN_DEBUG "cyc:startup raising Z DTR\n");
 #endif
 
                /* enable send, recv, modem !!! */
@@ -2144,51 +2078,50 @@ static int startup(struct cyclades_port *info)
                info->idle_stats.recv_idle =
                info->idle_stats.xmit_idle = jiffies;
 
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
 
 #ifdef CY_DEBUG_OPEN
-       printk(cyc startup done\n");
+       printk(KERN_DEBUG "cyc startup done\n");
 #endif
        return 0;
 
 errout:
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
        return retval;
 }                              /* startup */
 
 static void start_xmit(struct cyclades_port *info)
 {
+       struct cyclades_card *card;
        unsigned long flags;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr = cy_card[card].base_addr +
-                               (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
                cy_writeb(base_addr + (CyCAR << index), channel);
                cy_writeb(base_addr + (CySRER << index),
-                       cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
-               CY_UNLOCK(info, flags);
+                       readb(base_addr + (CySRER << index)) | CyTxRdy);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
 #ifdef CONFIG_CYZ_INTR
                int retval;
 
-               CY_LOCK(info, flags);
-               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK,
-                               0L);
+               spin_lock_irqsave(&card->card_lock, flags);
+               retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
                if (retval != 0) {
-                       printk("cyc:start_xmit retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
+                               "%x\n", info->line, retval);
                }
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
 #else                          /* CONFIG_CYZ_INTR */
                /* Don't have to do anything at this time */
 #endif                         /* CONFIG_CYZ_INTR */
@@ -2201,30 +2134,30 @@ static void start_xmit(struct cyclades_port *info)
  */
 static void shutdown(struct cyclades_port *info)
 {
+       struct cyclades_card *card;
        unsigned long flags;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
 
        if (!(info->flags & ASYNC_INITIALIZED)) {
                return;
        }
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr = cy_card[card].base_addr +
-                               (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 #ifdef CY_DEBUG_OPEN
-               printk("cyc shutdown Y card %d, chip %d, channel %d, "
-                               "base_addr %lx\n",
-                               card, chip, channel, (long)base_addr);
+               printk(KERN_DEBUG "cyc shutdown Y card %d, chip %d, "
+                               "channel %d, base_addr %p\n",
+                               card, chip, channel, base_addr);
 #endif
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
 
                /* Clear delta_msr_wait queue to avoid mem leaks. */
                wake_up_interruptible(&info->delta_msr_wait);
@@ -2240,10 +2173,10 @@ static void shutdown(struct cyclades_port *info)
                        cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
                        cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
-                       printk("cyc shutdown dropping DTR\n");
-                       printk("     status: 0x%x, 0x%x\n",
-                               cy_readb(base_addr + (CyMSVR1 << index)),
-                               cy_readb(base_addr + (CyMSVR2 << index)));
+                       printk(KERN_DEBUG "cyc shutdown dropping DTR\n");
+                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                               readb(base_addr + (CyMSVR1 << index)),
+                               readb(base_addr + (CyMSVR2 << index)));
 #endif
                }
                cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
@@ -2254,7 +2187,7 @@ static void shutdown(struct cyclades_port *info)
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
                }
                info->flags &= ~ASYNC_INITIALIZED;
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
                struct FIRM_ID __iomem *firm_id;
                struct ZFW_CTRL __iomem *zfw_ctrl;
@@ -2262,23 +2195,23 @@ static void shutdown(struct cyclades_port *info)
                struct CH_CTRL __iomem *ch_ctrl;
                int retval;
 
-               base_addr = cy_card[card].base_addr;
+               base_addr = card->base_addr;
 #ifdef CY_DEBUG_OPEN
-               printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
-                       card, channel, (long)base_addr);
+               printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
+                       "base_addr %p\n", card, channel, base_addr);
 #endif
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(cy_card[card])) {
+               if (!ISZLOADED(*card)) {
                        return;
                }
 
-               zfw_ctrl = cy_card[card].base_addr +
-                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               zfw_ctrl = card->base_addr +
+                               (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = zfw_ctrl->ch_ctrl;
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
 
                if (info->xmit_buf) {
                        unsigned char *temp;
@@ -2289,16 +2222,16 @@ static void shutdown(struct cyclades_port *info)
 
                if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
                        cy_writel(&ch_ctrl[channel].rs_control,
-                               (uclong)(cy_readl(&ch_ctrl[channel].rs_control)&
+                               (__u32)(readl(&ch_ctrl[channel].rs_control) &
                                        ~(C_RS_RTS | C_RS_DTR)));
-                       retval = cyz_issue_cmd(&cy_card[info->card], channel,
+                       retval = cyz_issue_cmd(info->card, channel,
                                        C_CM_IOCTLM, 0L);
                        if (retval != 0) {
-                               printk("cyc:shutdown retval on ttyC%d was %x\n",
-                                       info->line, retval);
+                               printk(KERN_ERR"cyc:shutdown retval on ttyC%d "
+                                       "was %x\n", info->line, retval);
                        }
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:shutdown dropping Z DTR\n");
+                       printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n");
 #endif
                }
 
@@ -2307,11 +2240,11 @@ static void shutdown(struct cyclades_port *info)
                }
                info->flags &= ~ASYNC_INITIALIZED;
 
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
 
 #ifdef CY_DEBUG_OPEN
-       printk(cyc shutdown done\n");
+       printk(KERN_DEBUG "cyc shutdown done\n");
 #endif
 }                              /* shutdown */
 
@@ -2332,7 +2265,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
        int retval;
        void __iomem *base_addr;
 
-       cinfo = &cy_card[info->card];
+       cinfo = info->card;
        channel = info->line - cinfo->first_line;
 
        /*
@@ -2340,9 +2273,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
         * until it's done, and then try again.
         */
        if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-               if (info->flags & ASYNC_CLOSING) {
-                       interruptible_sleep_on(&info->close_wait);
-               }
+               wait_event_interruptible(info->close_wait,
+                               !(info->flags & ASYNC_CLOSING));
                return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
        }
 
@@ -2365,17 +2297,16 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
        retval = 0;
        add_wait_queue(&info->open_wait, &wait);
 #ifdef CY_DEBUG_OPEN
-       printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
-               info->line, info->count);
-       /**/
+       printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
+               "count = %d\n", info->line, info->count);
 #endif
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&cinfo->card_lock, flags);
        if (!tty_hung_up_p(filp))
                info->count--;
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&cinfo->card_lock, flags);
 #ifdef CY_DEBUG_COUNT
-       printk("cyc block_til_ready: (%d): decrementing count to %d\n",
-               current->pid, info->count);
+       printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to "
+               "%d\n", current->pid, info->count);
 #endif
        info->blocked_open++;
 
@@ -2386,7 +2317,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
 
                while (1) {
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&cinfo->card_lock, flags);
                        if ((tty->termios->c_cflag & CBAUD)) {
                                cy_writeb(base_addr + (CyCAR << index),
                                          (u_char) channel);
@@ -2395,15 +2326,14 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                                cy_writeb(base_addr + (CyMSVR2 << index),
                                          CyDTR);
 #ifdef CY_DEBUG_DTR
-                               printk("cyc:block_til_ready raising DTR\n");
-                               printk("     status: 0x%x, 0x%x\n",
-                                       cy_readb(base_addr +
-                                               (CyMSVR1 << index)),
-                                       cy_readb(base_addr +
-                                               (CyMSVR2 << index)));
+                               printk(KERN_DEBUG "cyc:block_til_ready raising "
+                                       "DTR\n");
+                               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                                       readb(base_addr + (CyMSVR1 << index)),
+                                       readb(base_addr + (CyMSVR2 << index)));
 #endif
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&cinfo->card_lock, flags);
 
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (tty_hung_up_p(filp) ||
@@ -2413,26 +2343,25 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                                break;
                        }
 
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&cinfo->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
-                                       (cy_readb(base_addr +
+                                       (readb(base_addr +
                                                (CyMSVR1 << index)) & CyDCD))) {
-                               CY_UNLOCK(info, flags);
+                               spin_unlock_irqrestore(&cinfo->card_lock, flags);
                                break;
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&cinfo->card_lock, flags);
 
                        if (signal_pending(current)) {
                                retval = -ERESTARTSYS;
                                break;
                        }
 #ifdef CY_DEBUG_OPEN
-                       printk("cyc block_til_ready blocking: ttyC%d, "
-                                       "count = %d\n",
-                                       info->line, info->count);
-                       /**/
+                       printk(KERN_DEBUG "cyc block_til_ready blocking: "
+                               "ttyC%d, count = %d\n",
+                               info->line, info->count);
 #endif
                        schedule();
                }
@@ -2446,31 +2375,30 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                base_addr = cinfo->base_addr;
                firm_id = base_addr + ID_ADDRESS;
                if (!ISZLOADED(*cinfo)) {
-                       current->state = TASK_RUNNING;
+                       __set_current_state(TASK_RUNNING);
                        remove_wait_queue(&info->open_wait, &wait);
                        return -EINVAL;
                }
 
-               zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
-                               0xfffff);
+               zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)& 0xfffff);
                board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = zfw_ctrl->ch_ctrl;
 
                while (1) {
                        if ((tty->termios->c_cflag & CBAUD)) {
                                cy_writel(&ch_ctrl[channel].rs_control,
-                                         cy_readl(&ch_ctrl[channel].
-                                                  rs_control) | (C_RS_RTS |
-                                                                 C_RS_DTR));
-                               retval = cyz_issue_cmd(&cy_card[info->card],
-                                               channel, C_CM_IOCTLM, 0L);
+                                       readl(&ch_ctrl[channel].rs_control) |
+                                       C_RS_RTS | C_RS_DTR);
+                               retval = cyz_issue_cmd(cinfo,
+                                       channel, C_CM_IOCTLM, 0L);
                                if (retval != 0) {
-                                       printk("cyc:block_til_ready retval on "
-                                               "ttyC%d was %x\n",
+                                       printk(KERN_ERR "cyc:block_til_ready "
+                                               "retval on ttyC%d was %x\n",
                                                info->line, retval);
                                }
 #ifdef CY_DEBUG_DTR
-                               printk("cyc:block_til_ready raising Z DTR\n");
+                               printk(KERN_DEBUG "cyc:block_til_ready raising "
+                                       "Z DTR\n");
 #endif
                        }
 
@@ -2482,7 +2410,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                                break;
                        }
                        if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
-                                       (cy_readl(&ch_ctrl[channel].rs_status) &
+                                       (readl(&ch_ctrl[channel].rs_status) &
                                                C_RS_DCD))) {
                                break;
                        }
@@ -2491,28 +2419,26 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                                break;
                        }
 #ifdef CY_DEBUG_OPEN
-                       printk("cyc block_til_ready blocking: ttyC%d, "
-                                       "count = %d\n",
-                                       info->line, info->count);
-                       /**/
+                       printk(KERN_DEBUG "cyc block_til_ready blocking: "
+                               "ttyC%d, count = %d\n",
+                               info->line, info->count);
 #endif
                        schedule();
                }
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->open_wait, &wait);
        if (!tty_hung_up_p(filp)) {
                info->count++;
 #ifdef CY_DEBUG_COUNT
-               printk("cyc:block_til_ready (%d): incrementing count to %d\n",
-                       current->pid, info->count);
+               printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing "
+                       "count to %d\n", current->pid, info->count);
 #endif
        }
        info->blocked_open--;
 #ifdef CY_DEBUG_OPEN
-       printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
-               info->line, info->count);
-       /**/
+       printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, "
+               "count = %d\n", info->line, info->count);
 #endif
        if (retval)
                return retval;
@@ -2527,13 +2453,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 static int cy_open(struct tty_struct *tty, struct file *filp)
 {
        struct cyclades_port *info;
+       unsigned int i;
        int retval, line;
 
        line = tty->index;
        if ((line < 0) || (NR_PORTS <= line)) {
                return -ENODEV;
        }
-       info = &cy_port[line];
+       for (i = 0; i < NR_CARDS; i++)
+               if (line < cy_card[i].first_line + cy_card[i].nports &&
+                               line >= cy_card[i].first_line)
+                       break;
+       if (i >= NR_CARDS)
+               return -ENODEV;
+       info = &cy_card[i].ports[line - cy_card[i].first_line];
        if (info->line < 0) {
                return -ENODEV;
        }
@@ -2542,23 +2475,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
           treat it as absent from the system.  This
           will make the user pay attention.
         */
-       if (IS_CYC_Z(cy_card[info->card])) {
-               struct cyclades_card *cinfo = &cy_card[info->card];
+       if (IS_CYC_Z(*info->card)) {
+               struct cyclades_card *cinfo = info->card;
                struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
 
                if (!ISZLOADED(*cinfo)) {
-                       if (((ZE_V1 == cy_readl(
-                                       &((struct RUNTIME_9060 __iomem *)
+                       if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *)
                                         (cinfo->ctl_addr))->mail_box_0)) &&
                                        Z_FPGA_CHECK(*cinfo)) &&
-                                       (ZFIRM_HLT == cy_readl(
+                                       (ZFIRM_HLT == readl(
                                                &firm_id->signature))) {
-                               printk("cyc:Cyclades-Z Error: you need an "
-                                       "external power supply for this number "
-                                       "of ports.\n\rFirmware halted.\r\n");
+                               printk(KERN_ERR "cyc:Cyclades-Z Error: you "
+                                       "need an external power supply for "
+                                       "this number of ports.\nFirmware "
+                                       "halted.\n");
                        } else {
-                               printk("cyc:Cyclades-Z firmware not yet "
-                                       "loaded\n");
+                               printk(KERN_ERR "cyc:Cyclades-Z firmware not "
+                                       "yet loaded\n");
                        }
                        return -ENODEV;
                }
@@ -2572,24 +2505,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
                                struct BOARD_CTRL __iomem *board_ctrl;
 
                                zfw_ctrl = cinfo->base_addr +
-                                       (cy_readl(&firm_id->zfwctrl_addr) &
-                                               0xfffff);
+                                       (readl(&firm_id->zfwctrl_addr) &
+                                        0xfffff);
 
                                board_ctrl = &zfw_ctrl->board_ctrl;
 
                                /* Enable interrupts on the PLX chip */
                                cy_writew(cinfo->ctl_addr + 0x68,
-                                         cy_readw(cinfo->ctl_addr +
-                                                  0x68) | 0x0900);
+                                       readw(cinfo->ctl_addr + 0x68) | 0x0900);
                                /* Enable interrupts on the FW */
                                retval = cyz_issue_cmd(cinfo, 0,
                                                C_CM_IRQ_ENBL, 0L);
                                if (retval != 0) {
-                                       printk("cyc:IRQ enable retval was %x\n",
-                                               retval);
+                                       printk(KERN_ERR "cyc:IRQ enable retval "
+                                               "was %x\n", retval);
                                }
                                cinfo->nports =
-                                       (int)cy_readl(&board_ctrl->n_channel);
+                                       (int)readl(&board_ctrl->n_channel);
                                cinfo->intr_enabled = 1;
                        }
                }
@@ -2599,7 +2531,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
                        return -ENODEV;
        }
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_open ttyC%d\n", info->line);     /* */
+       printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
 #endif
        tty->driver_data = info;
        info->tty = tty;
@@ -2607,12 +2539,12 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
                return -ENODEV;
        }
 #ifdef CY_DEBUG_OPEN
-       printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count);
-       /**/
+       printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
+                       info->count);
 #endif
        info->count++;
 #ifdef CY_DEBUG_COUNT
-       printk("cyc:cy_open (%d): incrementing count to %d\n",
+       printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
                current->pid, info->count);
 #endif
 
@@ -2620,8 +2552,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
         * If the port is the middle of closing, bail out now
         */
        if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-               if (info->flags & ASYNC_CLOSING)
-                       interruptible_sleep_on(&info->close_wait);
+               wait_event_interruptible(info->close_wait,
+                               !(info->flags & ASYNC_CLOSING));
                return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
        }
 
@@ -2636,8 +2568,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        retval = block_til_ready(tty, filp, info);
        if (retval) {
 #ifdef CY_DEBUG_OPEN
-               printk("cyc:cy_open returning after block_til_ready with %d\n",
-                       retval);
+               printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
+                       "with %d\n", retval);
 #endif
                return retval;
        }
@@ -2645,8 +2577,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        info->throttle = 0;
 
 #ifdef CY_DEBUG_OPEN
-       printk(" cyc:cy_open done\n");
-       /**/
+       printk(KERN_DEBUG "cyc:cy_open done\n");
 #endif
        return 0;
 }                              /* cy_open */
@@ -2656,9 +2587,10 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
  */
 static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_card *card;
+       struct cyclades_port *info = tty->driver_data;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
        unsigned long orig_jiffies;
        int char_time;
 
@@ -2697,20 +2629,19 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
        if (!timeout || timeout > 2 * info->timeout)
                timeout = 2 * info->timeout;
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-       printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
-       printk("jiff=%lu...", jiffies);
+       printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...",
+               timeout, char_time, jiffies);
 #endif
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = (info->line) - (card->first_line);
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
-               while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) {
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
+               while (readb(base_addr + (CySRER << index)) & CyTxRdy) {
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-                       printk("Not clean (jiff=%lu)...", jiffies);
+                       printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
 #endif
                        if (msleep_interruptible(jiffies_to_msecs(char_time)))
                                break;
@@ -2718,13 +2649,11 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
                                        timeout))
                                break;
                }
-       } else {
-               /* Nothing to do! */
        }
        /* Run one more char cycle */
        msleep_interruptible(jiffies_to_msecs(char_time * 5));
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-       printk("Clean (jiff=%lu)...done\n", jiffies);
+       printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
 #endif
 }
 
@@ -2733,25 +2662,29 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
  */
 static void cy_close(struct tty_struct *tty, struct file *filp)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
        unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_close ttyC%d\n", info->line);
+       printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line);
 #endif
 
        if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
                return;
        }
 
-       CY_LOCK(info, flags);
+       card = info->card;
+
+       spin_lock_irqsave(&card->card_lock, flags);
        /* If the TTY is being hung up, nothing to do */
        if (tty_hung_up_p(filp)) {
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
                return;
        }
 #ifdef CY_DEBUG_OPEN
-       printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
+       printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line,
+               info->count);
 #endif
        if ((tty->count == 1) && (info->count != 1)) {
                /*
@@ -2761,22 +2694,22 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                 * one, we've got real problems, since it means the
                 * serial port won't be shutdown.
                 */
-               printk("cyc:cy_close: bad serial port count; tty->count is 1, "
-                       "info->count is %d\n", info->count);
+               printk(KERN_ERR "cyc:cy_close: bad serial port count; "
+                       "tty->count is 1, info->count is %d\n", info->count);
                info->count = 1;
        }
 #ifdef CY_DEBUG_COUNT
-       printk("cyc:cy_close at (%d): decrementing count to %d\n",
+       printk(KERN_DEBUG  "cyc:cy_close at (%d): decrementing count to %d\n",
                current->pid, info->count - 1);
 #endif
        if (--info->count < 0) {
 #ifdef CY_DEBUG_COUNT
-               printk("cyc:cyc_close setting count to 0\n");
+               printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n");
 #endif
                info->count = 0;
        }
        if (info->count) {
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
                return;
        }
        info->flags |= ASYNC_CLOSING;
@@ -2786,81 +2719,80 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
         * the line discipline to only process XON/XOFF characters.
         */
        tty->closing = 1;
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
        if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
                tty_wait_until_sent(tty, info->closing_wait);
        }
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&card->card_lock, flags);
 
-       if (!IS_CYC_Z(cy_card[info->card])) {
-               int channel = info->line - cy_card[info->card].first_line;
-               int index = cy_card[info->card].bus_index;
-               void __iomem *base_addr = cy_card[info->card].base_addr +
+       if (!IS_CYC_Z(*card)) {
+               int channel = info->line - card->first_line;
+               int index = card->bus_index;
+               void __iomem *base_addr = card->base_addr +
                        (cy_chip_offset[channel >> 2] << index);
                /* Stop accepting input */
                channel &= 0x03;
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
                cy_writeb(base_addr + (CySRER << index),
-                         cy_readb(base_addr + (CySRER << index)) & ~CyRxData);
+                         readb(base_addr + (CySRER << index)) & ~CyRxData);
                if (info->flags & ASYNC_INITIALIZED) {
                        /* Waiting for on-board buffers to be empty before closing
                           the port */
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                        cy_wait_until_sent(tty, info->timeout);
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                }
        } else {
 #ifdef Z_WAKE
                /* Waiting for on-board buffers to be empty before closing the port */
-               void __iomem *base_addr = cy_card[info->card].base_addr;
+               void __iomem *base_addr = card->base_addr;
                struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
                struct ZFW_CTRL __iomem *zfw_ctrl =
-                   base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+                   base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
-               int channel = info->line - cy_card[info->card].first_line;
+               int channel = info->line - card->first_line;
                int retval;
 
-               if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
-                       retval = cyz_issue_cmd(&cy_card[info->card], channel,
-                                               C_CM_IOCTLW, 0L);
+               if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
+                       retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
                        if (retval != 0) {
-                               printk("cyc:cy_close retval on ttyC%d was %x\n",
-                                       info->line, retval);
+                               printk(KERN_DEBUG "cyc:cy_close retval on "
+                                       "ttyC%d was %x\n", info->line, retval);
                        }
-                       CY_UNLOCK(info, flags);
-                       interruptible_sleep_on(&info->shutdown_wait);
-                       CY_LOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
+                       wait_for_completion_interruptible(&info->shutdown_wait);
+                       spin_lock_irqsave(&card->card_lock, flags);
                }
 #endif
        }
 
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
        shutdown(info);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
        tty_ldisc_flush(tty);
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&card->card_lock, flags);
 
        tty->closing = 0;
        info->event = 0;
        info->tty = NULL;
        if (info->blocked_open) {
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
                if (info->close_delay) {
                        msleep_interruptible(jiffies_to_msecs
                                                (info->close_delay));
                }
                wake_up_interruptible(&info->open_wait);
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
        }
        info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
        wake_up_interruptible(&info->close_wait);
 
 #ifdef CY_DEBUG_OTHER
-       printk(cyc:cy_close done\n");
+       printk(KERN_DEBUG "cyc:cy_close done\n");
 #endif
 
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
 }                              /* cy_close */
 
 /* This routine gets called when tty_write has put something into
@@ -2878,12 +2810,12 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
  */
 static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        unsigned long flags;
        int c, ret = 0;
 
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_write ttyC%d\n", info->line);    /* */
+       printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_write")) {
@@ -2893,7 +2825,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
        if (!info->xmit_buf)
                return 0;
 
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&info->card->card_lock, flags);
        while (1) {
                c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
                                   (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
@@ -2909,7 +2841,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
                count -= c;
                ret += c;
        }
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&info->card->card_lock, flags);
 
        info->idle_stats.xmit_bytes += ret;
        info->idle_stats.xmit_idle = jiffies;
@@ -2929,11 +2861,11 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
  */
 static void cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        unsigned long flags;
 
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_put_char ttyC%d\n", info->line);
+       printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_put_char"))
@@ -2942,9 +2874,9 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
        if (!info->xmit_buf)
                return;
 
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&info->card->card_lock, flags);
        if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&info->card->card_lock, flags);
                return;
        }
 
@@ -2953,7 +2885,7 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
        info->xmit_cnt++;
        info->idle_stats.xmit_bytes++;
        info->idle_stats.xmit_idle = jiffies;
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&info->card->card_lock, flags);
 }                              /* cy_put_char */
 
 /*
@@ -2962,10 +2894,10 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
  */
 static void cy_flush_chars(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
 
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_flush_chars ttyC%d\n", info->line);      /* */
+       printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
@@ -2986,11 +2918,11 @@ static void cy_flush_chars(struct tty_struct *tty)
  */
 static int cy_write_room(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        int ret;
 
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_write_room ttyC%d\n", info->line);       /* */
+       printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_write_room"))
@@ -3003,46 +2935,49 @@ static int cy_write_room(struct tty_struct *tty)
 
 static int cy_chars_in_buffer(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-       int card, channel;
+       struct cyclades_card *card;
+       struct cyclades_port *info = tty->driver_data;
+       int channel;
 
        if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
                return 0;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
+       channel = (info->line) - (card->first_line);
 
 #ifdef Z_EXT_CHARS_IN_BUFFER
        if (!IS_CYC_Z(cy_card[card])) {
 #endif                         /* Z_EXT_CHARS_IN_BUFFER */
 #ifdef CY_DEBUG_IO
-               printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt);       /* */
+               printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+                       info->line, info->xmit_cnt);
 #endif
                return info->xmit_cnt;
 #ifdef Z_EXT_CHARS_IN_BUFFER
        } else {
-               static volatile struct FIRM_ID *firm_id;
-               static volatile struct ZFW_CTRL *zfw_ctrl;
-               static volatile struct CH_CTRL *ch_ctrl;
-               static volatile struct BUF_CTRL *buf_ctrl;
+               static struct FIRM_ID *firm_id;
+               static struct ZFW_CTRL *zfw_ctrl;
+               static struct CH_CTRL *ch_ctrl;
+               static struct BUF_CTRL *buf_ctrl;
                int char_count;
-               volatile uclong tx_put, tx_get, tx_bufsize;
+               __u32 tx_put, tx_get, tx_bufsize;
 
-               firm_id = cy_card[card].base_addr + ID_ADDRESS;
-               zfw_ctrl = cy_card[card].base_addr +
-                       (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               firm_id = card->base_addr + ID_ADDRESS;
+               zfw_ctrl = card->base_addr +
+                       (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
                buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
 
-               tx_get = cy_readl(&buf_ctrl->tx_get);
-               tx_put = cy_readl(&buf_ctrl->tx_put);
-               tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+               tx_get = readl(&buf_ctrl->tx_get);
+               tx_put = readl(&buf_ctrl->tx_put);
+               tx_bufsize = readl(&buf_ctrl->tx_bufsize);
                if (tx_put >= tx_get)
                        char_count = tx_put - tx_get;
                else
                        char_count = tx_put - tx_get + tx_bufsize;
 #ifdef CY_DEBUG_IO
-               printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count);  /* */
+               printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+                       info->line, info->xmit_cnt + char_count);
 #endif
                return info->xmit_cnt + char_count;
        }
@@ -3055,10 +2990,10 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
  * ------------------------------------------------------------
  */
 
-static void cyy_baud_calc(struct cyclades_port *info, uclong baud)
+static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
 {
        int co, co_val, bpr;
-       uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
+       __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
                        25000000);
 
        if (baud == 0) {
@@ -3086,9 +3021,10 @@ static void cyy_baud_calc(struct cyclades_port *info, uclong baud)
  */
 static void set_line_char(struct cyclades_port *info)
 {
+       struct cyclades_card *card;
        unsigned long flags;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
        unsigned cflag, iflag;
        unsigned short chip_number;
        int baud, baud_rate = 0;
@@ -3118,12 +3054,12 @@ static void set_line_char(struct cyclades_port *info)
        }
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
+       channel = info->line - card->first_line;
        chip_number = channel / 4;
 
-       if (!IS_CYC_Z(cy_card[card])) {
+       if (!IS_CYC_Z(*card)) {
 
-               index = cy_card[card].bus_index;
+               index = card->bus_index;
 
                /* baud rate */
                baud = tty_get_baud_rate(info->tty);
@@ -3241,10 +3177,9 @@ static void set_line_char(struct cyclades_port *info)
 
                chip = channel >> 2;
                channel &= 0x03;
-               base_addr = cy_card[card].base_addr +
-                       (cy_chip_offset[chip] << index);
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
 
                /* tx and rx baud rate */
@@ -3276,8 +3211,7 @@ static void set_line_char(struct cyclades_port *info)
                if (C_CLOCAL(info->tty)) {
                        /* without modem intr */
                        cy_writeb(base_addr + (CySRER << index),
-                                 cy_readb(base_addr +
-                                          (CySRER << index)) | CyMdmCh);
+                               readb(base_addr + (CySRER << index)) | CyMdmCh);
                        /* act on 1->0 modem transitions */
                        if ((cflag & CRTSCTS) && info->rflow) {
                                cy_writeb(base_addr + (CyMCOR1 << index),
@@ -3291,7 +3225,7 @@ static void set_line_char(struct cyclades_port *info)
                } else {
                        /* without modem intr */
                        cy_writeb(base_addr + (CySRER << index),
-                                 cy_readb(base_addr +
+                                 readb(base_addr +
                                           (CySRER << index)) | CyMdmCh);
                        /* act on 1->0 modem transitions */
                        if ((cflag & CRTSCTS) && info->rflow) {
@@ -3316,10 +3250,10 @@ static void set_line_char(struct cyclades_port *info)
                                          ~CyDTR);
                        }
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_line_char dropping DTR\n");
-                       printk("     status: 0x%x, 0x%x\n",
-                               cy_readb(base_addr + (CyMSVR1 << index)),
-                               cy_readb(base_addr + (CyMSVR2 << index)));
+                       printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n");
+                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                               readb(base_addr + (CyMSVR1 << index)),
+                               readb(base_addr + (CyMSVR2 << index)));
 #endif
                } else {
                        if (info->rtsdtr_inv) {
@@ -3330,17 +3264,17 @@ static void set_line_char(struct cyclades_port *info)
                                          CyDTR);
                        }
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_line_char raising DTR\n");
-                       printk("     status: 0x%x, 0x%x\n",
-                               cy_readb(base_addr + (CyMSVR1 << index)),
-                               cy_readb(base_addr + (CyMSVR2 << index)));
+                       printk(KERN_DEBUG "cyc:set_line_char raising DTR\n");
+                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                               readb(base_addr + (CyMSVR1 << index)),
+                               readb(base_addr + (CyMSVR2 << index)));
 #endif
                }
 
                if (info->tty) {
                        clear_bit(TTY_IO_ERROR, &info->tty->flags);
                }
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
 
        } else {
                struct FIRM_ID __iomem *firm_id;
@@ -3348,16 +3282,16 @@ static void set_line_char(struct cyclades_port *info)
                struct BOARD_CTRL __iomem *board_ctrl;
                struct CH_CTRL __iomem *ch_ctrl;
                struct BUF_CTRL __iomem *buf_ctrl;
-               uclong sw_flow;
+               __u32 sw_flow;
                int retval;
 
-               firm_id = cy_card[card].base_addr + ID_ADDRESS;
-               if (!ISZLOADED(cy_card[card])) {
+               firm_id = card->base_addr + ID_ADDRESS;
+               if (!ISZLOADED(*card)) {
                        return;
                }
 
-               zfw_ctrl = cy_card[card].base_addr +
-                       (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               zfw_ctrl = card->base_addr +
+                       (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
                buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
@@ -3408,10 +3342,10 @@ static void set_line_char(struct cyclades_port *info)
                }
                if (cflag & CSTOPB) {
                        cy_writel(&ch_ctrl->comm_data_l,
-                                 cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
+                                 readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
                } else {
                        cy_writel(&ch_ctrl->comm_data_l,
-                                 cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
+                                 readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
                }
                if (cflag & PARENB) {
                        if (cflag & PARODD) {
@@ -3426,12 +3360,10 @@ static void set_line_char(struct cyclades_port *info)
                /* CTS flow control flag */
                if (cflag & CRTSCTS) {
                        cy_writel(&ch_ctrl->hw_flow,
-                                 cy_readl(&ch_ctrl->
-                                          hw_flow) | C_RS_CTS | C_RS_RTS);
+                               readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
                } else {
-                       cy_writel(&ch_ctrl->hw_flow,
-                                 cy_readl(&ch_ctrl->
-                                          hw_flow) & ~(C_RS_CTS | C_RS_RTS));
+                       cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
+                                       ~(C_RS_CTS | C_RS_RTS));
                }
                /* As the HW flow control is done in firmware, the driver
                   doesn't need to care about it */
@@ -3446,10 +3378,10 @@ static void set_line_char(struct cyclades_port *info)
                }
                cy_writel(&ch_ctrl->sw_flow, sw_flow);
 
-               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
                if (retval != 0) {
-                       printk("cyc:set_line_char retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
+                               "was %x\n", info->line, retval);
                }
 
                /* CD sensitivity */
@@ -3461,22 +3393,22 @@ static void set_line_char(struct cyclades_port *info)
 
                if (baud == 0) {        /* baud rate is zero, turn off line */
                        cy_writel(&ch_ctrl->rs_control,
-                                 cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
+                                 readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_line_char dropping Z DTR\n");
+                       printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
 #endif
                } else {
                        cy_writel(&ch_ctrl->rs_control,
-                                 cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
+                                 readl(&ch_ctrl->rs_control) | C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_line_char raising Z DTR\n");
+                       printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
 #endif
                }
 
-               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM,0L);
                if (retval != 0) {
-                       printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
+                               "was %x\n", info->line, retval);
                }
 
                if (info->tty) {
@@ -3490,14 +3422,15 @@ get_serial_info(struct cyclades_port *info,
                struct serial_struct __user * retinfo)
 {
        struct serial_struct tmp;
-       struct cyclades_card *cinfo = &cy_card[info->card];
+       struct cyclades_card *cinfo = info->card;
 
        if (!retinfo)
                return -EFAULT;
        memset(&tmp, 0, sizeof(tmp));
        tmp.type = info->type;
        tmp.line = info->line;
-       tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
+       tmp.port = (info->card - cy_card) * 0x100 + info->line -
+               cinfo->first_line;
        tmp.irq = cinfo->irq;
        tmp.flags = info->flags;
        tmp.close_delay = info->close_delay;
@@ -3566,25 +3499,25 @@ check_and_exit:
  */
 static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
 {
-       int card, chip, channel, index;
+       struct cyclades_card *card;
+       int chip, channel, index;
        unsigned char status;
        unsigned int result;
        unsigned long flags;
        void __iomem *base_addr;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = (info->line) - (card->first_line);
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
-               status = cy_readb(base_addr + (CySRER << index)) &
+               spin_lock_irqsave(&card->card_lock, flags);
+               status = readb(base_addr + (CySRER << index)) &
                                (CyTxRdy | CyTxMpty);
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
                result = (status ? 0 : TIOCSER_TEMT);
        } else {
                /* Not supported yet */
@@ -3595,8 +3528,9 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
 
 static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-       int card, chip, channel, index;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int chip, channel, index;
        void __iomem *base_addr;
        unsigned long flags;
        unsigned char status;
@@ -3611,19 +3545,18 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
                return -ENODEV;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-               status = cy_readb(base_addr + (CyMSVR1 << index));
-               status |= cy_readb(base_addr + (CyMSVR2 << index));
-               CY_UNLOCK(info, flags);
+               status = readb(base_addr + (CyMSVR1 << index));
+               status |= readb(base_addr + (CyMSVR2 << index));
+               spin_unlock_irqrestore(&card->card_lock, flags);
 
                if (info->rtsdtr_inv) {
                        result = ((status & CyRTS) ? TIOCM_DTR : 0) |
@@ -3637,19 +3570,14 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
                        ((status & CyDSR) ? TIOCM_DSR : 0) |
                        ((status & CyCTS) ? TIOCM_CTS : 0);
        } else {
-               base_addr = cy_card[card].base_addr;
-
-               if (cy_card[card].num_chips != -1) {
-                       return -EINVAL;
-               }
-
-               firm_id = cy_card[card].base_addr + ID_ADDRESS;
-               if (ISZLOADED(cy_card[card])) {
-                       zfw_ctrl = cy_card[card].base_addr +
-                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               base_addr = card->base_addr;
+               firm_id = card->base_addr + ID_ADDRESS;
+               if (ISZLOADED(*card)) {
+                       zfw_ctrl = card->base_addr +
+                               (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                        board_ctrl = &zfw_ctrl->board_ctrl;
                        ch_ctrl = zfw_ctrl->ch_ctrl;
-                       lstatus = cy_readl(&ch_ctrl[channel].rs_status);
+                       lstatus = readl(&ch_ctrl[channel].rs_status);
                        result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
                                ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
                                ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
@@ -3669,8 +3597,9 @@ static int
 cy_tiocmset(struct tty_struct *tty, struct file *file,
                unsigned int set, unsigned int clear)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-       int card, chip, channel, index;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int chip, channel, index;
        void __iomem *base_addr;
        unsigned long flags;
        struct FIRM_ID __iomem *firm_id;
@@ -3683,16 +3612,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                return -ENODEV;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = (info->line) - (card->first_line);
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
                if (set & TIOCM_RTS) {
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -3702,10 +3630,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                                cy_writeb(base_addr + (CyMSVR1 << index),
                                          CyRTS);
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                }
                if (clear & TIOCM_RTS) {
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -3715,10 +3643,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                                cy_writeb(base_addr + (CyMSVR1 << index),
                                          ~CyRTS);
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                }
                if (set & TIOCM_DTR) {
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -3729,15 +3657,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                                          CyDTR);
                        }
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_modem_info raising DTR\n");
-                       printk("     status: 0x%x, 0x%x\n",
-                               cy_readb(base_addr + (CyMSVR1 << index)),
-                               cy_readb(base_addr + (CyMSVR2 << index)));
+                       printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
+                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                               readb(base_addr + (CyMSVR1 << index)),
+                               readb(base_addr + (CyMSVR2 << index)));
 #endif
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                }
                if (clear & TIOCM_DTR) {
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -3749,68 +3677,69 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                        }
 
 #ifdef CY_DEBUG_DTR
-                       printk("cyc:set_modem_info dropping DTR\n");
-                       printk("     status: 0x%x, 0x%x\n",
-                               cy_readb(base_addr + (CyMSVR1 << index)),
-                               cy_readb(base_addr + (CyMSVR2 << index)));
+                       printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
+                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                               readb(base_addr + (CyMSVR1 << index)),
+                               readb(base_addr + (CyMSVR2 << index)));
 #endif
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                }
        } else {
-               base_addr = cy_card[card].base_addr;
+               base_addr = card->base_addr;
 
-               firm_id = cy_card[card].base_addr + ID_ADDRESS;
-               if (ISZLOADED(cy_card[card])) {
-                       zfw_ctrl = cy_card[card].base_addr +
-                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               firm_id = card->base_addr + ID_ADDRESS;
+               if (ISZLOADED(*card)) {
+                       zfw_ctrl = card->base_addr +
+                               (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                        board_ctrl = &zfw_ctrl->board_ctrl;
                        ch_ctrl = zfw_ctrl->ch_ctrl;
 
                        if (set & TIOCM_RTS) {
-                               CY_LOCK(info, flags);
+                               spin_lock_irqsave(&card->card_lock, flags);
                                cy_writel(&ch_ctrl[channel].rs_control,
-                                         cy_readl(&ch_ctrl[channel].
-                                                  rs_control) | C_RS_RTS);
-                               CY_UNLOCK(info, flags);
+                                       readl(&ch_ctrl[channel].rs_control) |
+                                       C_RS_RTS);
+                               spin_unlock_irqrestore(&card->card_lock, flags);
                        }
                        if (clear & TIOCM_RTS) {
-                               CY_LOCK(info, flags);
+                               spin_lock_irqsave(&card->card_lock, flags);
                                cy_writel(&ch_ctrl[channel].rs_control,
-                                         cy_readl(&ch_ctrl[channel].
-                                                  rs_control) & ~C_RS_RTS);
-                               CY_UNLOCK(info, flags);
+                                       readl(&ch_ctrl[channel].rs_control) &
+                                       ~C_RS_RTS);
+                               spin_unlock_irqrestore(&card->card_lock, flags);
                        }
                        if (set & TIOCM_DTR) {
-                               CY_LOCK(info, flags);
+                               spin_lock_irqsave(&card->card_lock, flags);
                                cy_writel(&ch_ctrl[channel].rs_control,
-                                         cy_readl(&ch_ctrl[channel].
-                                                  rs_control) | C_RS_DTR);
+                                       readl(&ch_ctrl[channel].rs_control) |
+                                       C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                               printk("cyc:set_modem_info raising Z DTR\n");
+                               printk(KERN_DEBUG "cyc:set_modem_info raising "
+                                       "Z DTR\n");
 #endif
-                               CY_UNLOCK(info, flags);
+                               spin_unlock_irqrestore(&card->card_lock, flags);
                        }
                        if (clear & TIOCM_DTR) {
-                               CY_LOCK(info, flags);
+                               spin_lock_irqsave(&card->card_lock, flags);
                                cy_writel(&ch_ctrl[channel].rs_control,
-                                         cy_readl(&ch_ctrl[channel].
-                                                  rs_control) & ~C_RS_DTR);
+                                       readl(&ch_ctrl[channel].rs_control) &
+                                       ~C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                               printk("cyc:set_modem_info clearing Z DTR\n");
+                               printk(KERN_DEBUG "cyc:set_modem_info clearing "
+                                       "Z DTR\n");
 #endif
-                               CY_UNLOCK(info, flags);
+                               spin_unlock_irqrestore(&card->card_lock, flags);
                        }
                } else {
                        return -ENODEV;
                }
-               CY_LOCK(info, flags);
-               retval = cyz_issue_cmd(&cy_card[info->card],
-                                       channel, C_CM_IOCTLM, 0L);
+               spin_lock_irqsave(&card->card_lock, flags);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
                if (retval != 0) {
-                       printk("cyc:set_modem_info retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
+                               "was %x\n", info->line, retval);
                }
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
        return 0;
 }                              /* cy_tiocmset */
@@ -3820,14 +3749,17 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
  */
 static void cy_break(struct tty_struct *tty, int break_state)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
        unsigned long flags;
 
        if (serial_paranoia_check(info, tty->name, "cy_break"))
                return;
 
-       CY_LOCK(info, flags);
-       if (!IS_CYC_Z(cy_card[info->card])) {
+       card = info->card;
+
+       spin_lock_irqsave(&card->card_lock, flags);
+       if (!IS_CYC_Z(*card)) {
                /* Let the transmit ISR take care of this (since it
                   requires stuffing characters into the output stream).
                 */
@@ -3835,18 +3767,18 @@ static void cy_break(struct tty_struct *tty, int break_state)
                        if (!info->breakon) {
                                info->breakon = 1;
                                if (!info->xmit_cnt) {
-                                       CY_UNLOCK(info, flags);
+                                       spin_unlock_irqrestore(&card->card_lock, flags);
                                        start_xmit(info);
-                                       CY_LOCK(info, flags);
+                                       spin_lock_irqsave(&card->card_lock, flags);
                                }
                        }
                } else {
                        if (!info->breakoff) {
                                info->breakoff = 1;
                                if (!info->xmit_cnt) {
-                                       CY_UNLOCK(info, flags);
+                                       spin_unlock_irqrestore(&card->card_lock, flags);
                                        start_xmit(info);
-                                       CY_LOCK(info, flags);
+                                       spin_lock_irqsave(&card->card_lock, flags);
                                }
                        }
                }
@@ -3854,24 +3786,25 @@ static void cy_break(struct tty_struct *tty, int break_state)
                int retval;
 
                if (break_state == -1) {
-                       retval = cyz_issue_cmd(&cy_card[info->card],
-                               info->line - cy_card[info->card].first_line,
+                       retval = cyz_issue_cmd(card,
+                               info->line - card->first_line,
                                C_CM_SET_BREAK, 0L);
                        if (retval != 0) {
-                               printk("cyc:cy_break (set) retval on ttyC%d "
-                                       "was %x\n", info->line, retval);
+                               printk(KERN_ERR "cyc:cy_break (set) retval on "
+                                       "ttyC%d was %x\n", info->line, retval);
                        }
                } else {
-                       retval = cyz_issue_cmd(&cy_card[info->card],
-                               info->line - cy_card[info->card].first_line,
+                       retval = cyz_issue_cmd(card,
+                               info->line - card->first_line,
                                C_CM_CLR_BREAK, 0L);
                        if (retval != 0) {
-                               printk("cyc:cy_break (clr) retval on ttyC%d "
-                                       "was %x\n", info->line, retval);
+                               printk(KERN_DEBUG "cyc:cy_break (clr) retval "
+                                       "on ttyC%d was %x\n", info->line,
+                                       retval);
                        }
                }
        }
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
 }                              /* cy_break */
 
 static int
@@ -3889,28 +3822,27 @@ get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
 
 static int set_threshold(struct cyclades_port *info, unsigned long value)
 {
+       struct cyclades_card *card;
        void __iomem *base_addr;
-       int card, channel, chip, index;
+       int channel, chip, index;
        unsigned long flags;
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
+               index = card->bus_index;
                base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+                   card->base_addr + (cy_chip_offset[chip] << index);
 
                info->cor3 &= ~CyREC_FIFO;
                info->cor3 |= value & CyREC_FIFO;
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
                cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
                cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
-               CY_UNLOCK(info, flags);
-       } else {
-               /* Nothing to do! */
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
        return 0;
 }                              /* set_threshold */
@@ -3918,25 +3850,23 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
 static int
 get_threshold(struct cyclades_port *info, unsigned long __user * value)
 {
+       struct cyclades_card *card;
        void __iomem *base_addr;
-       int card, channel, chip, index;
+       int channel, chip, index;
        unsigned long tmp;
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
+               tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
                return put_user(tmp, value);
-       } else {
-               /* Nothing to do! */
-               return 0;
        }
+       return 0;
 }                              /* get_threshold */
 
 static int
@@ -3954,49 +3884,45 @@ get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
 
 static int set_timeout(struct cyclades_port *info, unsigned long value)
 {
+       struct cyclades_card *card;
        void __iomem *base_addr;
-       int card, channel, chip, index;
+       int channel, chip, index;
        unsigned long flags;
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&card->card_lock, flags);
                cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
-               CY_UNLOCK(info, flags);
-       } else {
-               /* Nothing to do! */
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
        return 0;
 }                              /* set_timeout */
 
 static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
 {
+       struct cyclades_card *card;
        void __iomem *base_addr;
-       int card, channel, chip, index;
+       int channel, chip, index;
        unsigned long tmp;
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
-       if (!IS_CYC_Z(cy_card[card])) {
+       channel = info->line - card->first_line;
+       if (!IS_CYC_Z(*card)) {
                chip = channel >> 2;
                channel &= 0x03;
-               index = cy_card[card].bus_index;
-               base_addr =
-                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               index = card->bus_index;
+               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-               tmp = cy_readb(base_addr + (CyRTPR << index));
+               tmp = readb(base_addr + (CyRTPR << index));
                return put_user(tmp, value);
-       } else {
-               /* Nothing to do! */
-               return 0;
        }
+       return 0;
 }                              /* get_timeout */
 
 static int set_default_timeout(struct cyclades_port *info, unsigned long value)
@@ -4020,7 +3946,7 @@ static int
 cy_ioctl(struct tty_struct *tty, struct file *file,
         unsigned int cmd, unsigned long arg)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        struct cyclades_icount cprev, cnow;     /* kernel counter temps */
        struct serial_icounter_struct __user *p_cuser;  /* user space */
        int ret_val = 0;
@@ -4031,7 +3957,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                return -ENODEV;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg);      /* */
+       printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
+               info->line, cmd, arg);
 #endif
 
        switch (cmd) {
@@ -4076,14 +4003,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        case CYGETRTSDTR_INV:
                ret_val = info->rtsdtr_inv;
                break;
-       case CYGETCARDINFO:
-               if (copy_to_user(argp, &cy_card[info->card],
-                                sizeof(struct cyclades_card))) {
-                       ret_val = -EFAULT;
-                       break;
-               }
-               ret_val = 0;
-               break;
        case CYGETCD1400VER:
                ret_val = info->chip_rev;
                break;
@@ -4119,34 +4038,22 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                 * Caller should use TIOCGICOUNT to see which one it was
                 */
        case TIOCMIWAIT:
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&info->card->card_lock, flags);
                /* note the counters on entry */
-               cprev = info->icount;
-               CY_UNLOCK(info, flags);
-               while (1) {
-                       interruptible_sleep_on(&info->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current)) {
-                               return -ERESTARTSYS;
-                       }
-
-                       CY_LOCK(info, flags);
+               cnow = info->icount;
+               spin_unlock_irqrestore(&info->card->card_lock, flags);
+               ret_val = wait_event_interruptible(info->delta_msr_wait, ({
+                       cprev = cnow;
+                       spin_lock_irqsave(&info->card->card_lock, flags);
                        cnow = info->icount;    /* atomic copy */
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&info->card->card_lock, flags);
 
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-                               return -EIO;    /* no change => error */
-                       }
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
+                       ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                       ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+                       ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+                       ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts));
+               }));
+               break;
 
                /*
                 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
@@ -4155,9 +4062,9 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                 *     RI where only 0->1 is counted.
                 */
        case TIOCGICOUNT:
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&info->card->card_lock, flags);
                cnow = info->icount;
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&info->card->card_lock, flags);
                p_cuser = argp;
                ret_val = put_user(cnow.cts, &p_cuser->cts);
                if (ret_val)
@@ -4199,7 +4106,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        }
 
 #ifdef CY_DEBUG_OTHER
-       printk(cyc:cy_ioctl done\n");
+       printk(KERN_DEBUG "cyc:cy_ioctl done\n");
 #endif
 
        return ret_val;
@@ -4213,10 +4120,10 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
  */
 static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_set_termios ttyC%d\n", info->line);
+       printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
        if (tty->termios->c_cflag == old_termios->c_cflag &&
@@ -4248,8 +4155,9 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 */
 static void cy_send_xchar(struct tty_struct *tty, char ch)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-       int card, channel;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int channel;
 
        if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
                return;
@@ -4260,15 +4168,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch)
                cy_start(tty);
 
        card = info->card;
-       channel = info->line - cy_card[card].first_line;
+       channel = info->line - card->first_line;
 
-       if (IS_CYC_Z(cy_card[card])) {
+       if (IS_CYC_Z(*card)) {
                if (ch == STOP_CHAR(tty))
-                       cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF,
-                                       0L);
+                       cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
                else if (ch == START_CHAR(tty))
-                       cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON,
-                                       0L);
+                       cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
        }
 }
 
@@ -4278,15 +4184,16 @@ static void cy_send_xchar(struct tty_struct *tty, char ch)
  */
 static void cy_throttle(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
        unsigned long flags;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
        char buf[64];
 
-       printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf),
+       printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
                        tty->ldisc.chars_in_buffer(tty), info->line);
 #endif
 
@@ -4297,22 +4204,22 @@ static void cy_throttle(struct tty_struct *tty)
        card = info->card;
 
        if (I_IXOFF(tty)) {
-               if (!IS_CYC_Z(cy_card[card]))
+               if (!IS_CYC_Z(*card))
                        cy_send_xchar(tty, STOP_CHAR(tty));
                else
                        info->throttle = 1;
        }
 
        if (tty->termios->c_cflag & CRTSCTS) {
-               channel = info->line - cy_card[card].first_line;
-               if (!IS_CYC_Z(cy_card[card])) {
+               channel = info->line - card->first_line;
+               if (!IS_CYC_Z(*card)) {
                        chip = channel >> 2;
                        channel &= 0x03;
-                       index = cy_card[card].bus_index;
-                       base_addr = cy_card[card].base_addr +
+                       index = card->bus_index;
+                       base_addr = card->base_addr +
                                (cy_chip_offset[chip] << index);
 
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -4322,7 +4229,7 @@ static void cy_throttle(struct tty_struct *tty)
                                cy_writeb(base_addr + (CyMSVR1 << index),
                                          ~CyRTS);
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                } else {
                        info->throttle = 1;
                }
@@ -4336,16 +4243,17 @@ static void cy_throttle(struct tty_struct *tty)
  */
 static void cy_unthrottle(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
        unsigned long flags;
        void __iomem *base_addr;
-       int card, chip, channel, index;
+       int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
        char buf[64];
 
-       printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf),
-               tty->ldisc.chars_in_buffer(tty), info->line);
+       printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
+               tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty),info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) {
@@ -4361,15 +4269,15 @@ static void cy_unthrottle(struct tty_struct *tty)
 
        if (tty->termios->c_cflag & CRTSCTS) {
                card = info->card;
-               channel = info->line - cy_card[card].first_line;
-               if (!IS_CYC_Z(cy_card[card])) {
+               channel = info->line - card->first_line;
+               if (!IS_CYC_Z(*card)) {
                        chip = channel >> 2;
                        channel &= 0x03;
-                       index = cy_card[card].bus_index;
-                       base_addr = cy_card[card].base_addr +
+                       index = card->bus_index;
+                       base_addr = card->base_addr +
                                (cy_chip_offset[chip] << index);
 
-                       CY_LOCK(info, flags);
+                       spin_lock_irqsave(&card->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
                        if (info->rtsdtr_inv) {
@@ -4379,7 +4287,7 @@ static void cy_unthrottle(struct tty_struct *tty)
                                cy_writeb(base_addr + (CyMSVR1 << index),
                                          CyRTS);
                        }
-                       CY_UNLOCK(info, flags);
+                       spin_unlock_irqrestore(&card->card_lock, flags);
                } else {
                        info->throttle = 0;
                }
@@ -4392,102 +4300,96 @@ static void cy_unthrottle(struct tty_struct *tty)
 static void cy_stop(struct tty_struct *tty)
 {
        struct cyclades_card *cinfo;
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        void __iomem *base_addr;
        int chip, channel, index;
        unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_stop ttyC%d\n", info->line);     /* */
+       printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_stop"))
                return;
 
-       cinfo = &cy_card[info->card];
+       cinfo = info->card;
        channel = info->line - cinfo->first_line;
        if (!IS_CYC_Z(*cinfo)) {
                index = cinfo->bus_index;
                chip = channel >> 2;
                channel &= 0x03;
-               base_addr = cy_card[info->card].base_addr +
-                       (cy_chip_offset[chip] << index);
+               base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&cinfo->card_lock, flags);
                cy_writeb(base_addr + (CyCAR << index),
                        (u_char)(channel & 0x0003)); /* index channel */
                cy_writeb(base_addr + (CySRER << index),
-                         cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy);
-               CY_UNLOCK(info, flags);
-       } else {
-               /* Nothing to do! */
+                         readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+               spin_unlock_irqrestore(&cinfo->card_lock, flags);
        }
 }                              /* cy_stop */
 
 static void cy_start(struct tty_struct *tty)
 {
        struct cyclades_card *cinfo;
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
        void __iomem *base_addr;
        int chip, channel, index;
        unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_start ttyC%d\n", info->line);    /* */
+       printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_start"))
                return;
 
-       cinfo = &cy_card[info->card];
+       cinfo = info->card;
        channel = info->line - cinfo->first_line;
        index = cinfo->bus_index;
        if (!IS_CYC_Z(*cinfo)) {
                chip = channel >> 2;
                channel &= 0x03;
-               base_addr = cy_card[info->card].base_addr +
-                       (cy_chip_offset[chip] << index);
+               base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
 
-               CY_LOCK(info, flags);
+               spin_lock_irqsave(&cinfo->card_lock, flags);
                cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003));   /* index channel */
                cy_writeb(base_addr + (CySRER << index),
-                         cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
-               CY_UNLOCK(info, flags);
-       } else {
-               /* Nothing to do! */
+                         readb(base_addr + (CySRER << index)) | CyTxRdy);
+               spin_unlock_irqrestore(&cinfo->card_lock, flags);
        }
 }                              /* cy_start */
 
 static void cy_flush_buffer(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-       int card, channel, retval;
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int channel, retval;
        unsigned long flags;
 
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_flush_buffer ttyC%d\n", info->line);     /* */
+       printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
                return;
 
        card = info->card;
-       channel = (info->line) - (cy_card[card].first_line);
+       channel = info->line - card->first_line;
 
-       CY_LOCK(info, flags);
+       spin_lock_irqsave(&card->card_lock, flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       CY_UNLOCK(info, flags);
+       spin_unlock_irqrestore(&card->card_lock, flags);
 
-       if (IS_CYC_Z(cy_card[card])) {  /* If it is a Z card, flush the on-board
+       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
                                           buffers as well */
-               CY_LOCK(info, flags);
-               retval =
-                   cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
+               spin_lock_irqsave(&card->card_lock, flags);
+               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
                if (retval != 0) {
-                       printk("cyc: flush_buffer retval on ttyC%d was %x\n",
-                               info->line, retval);
+                       printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
+                               "was %x\n", info->line, retval);
                }
-               CY_UNLOCK(info, flags);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        }
        tty_wakeup(tty);
 }                              /* cy_flush_buffer */
@@ -4497,10 +4399,10 @@ static void cy_flush_buffer(struct tty_struct *tty)
  */
 static void cy_hangup(struct tty_struct *tty)
 {
-       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = tty->driver_data;
 
 #ifdef CY_DEBUG_OTHER
-       printk("cyc:cy_hangup ttyC%d\n", info->line);   /* */
+       printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_hangup"))
@@ -4511,7 +4413,8 @@ static void cy_hangup(struct tty_struct *tty)
        info->event = 0;
        info->count = 0;
 #ifdef CY_DEBUG_COUNT
-       printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
+       printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
+               current->pid);
 #endif
        info->tty = NULL;
        info->flags &= ~ASYNC_NORMAL_ACTIVE;
@@ -4526,10 +4429,107 @@ static void cy_hangup(struct tty_struct *tty)
  * ---------------------------------------------------------------------
  */
 
+static int __devinit cy_init_card(struct cyclades_card *cinfo)
+{
+       struct cyclades_port *info;
+       u32 mailbox;
+       unsigned int nports;
+       unsigned short chip_number;
+       int index, port;
+
+       spin_lock_init(&cinfo->card_lock);
+
+       if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */
+               mailbox = readl(&((struct RUNTIME_9060 __iomem *)
+                                    cinfo->ctl_addr)->mail_box_0);
+               nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
+               cinfo->intr_enabled = 0;
+               cinfo->nports = 0;      /* Will be correctly set later, after
+                                          Z FW is loaded */
+       } else {
+               index = cinfo->bus_index;
+               nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
+       }
+
+       cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
+       if (cinfo->ports == NULL) {
+               printk(KERN_ERR "Cyclades: cannot allocate ports\n");
+               cinfo->nports = 0;
+               return -ENOMEM;
+       }
+
+       for (port = cinfo->first_line; port < cinfo->first_line + nports;
+                       port++) {
+               info = &cinfo->ports[port - cinfo->first_line];
+               info->magic = CYCLADES_MAGIC;
+               info->card = cinfo;
+               info->line = port;
+               info->flags = STD_COM_FLAGS;
+               info->closing_wait = CLOSING_WAIT_DELAY;
+               info->close_delay = 5 * HZ / 10;
+
+               INIT_WORK(&info->tqueue, do_softint);
+               init_waitqueue_head(&info->open_wait);
+               init_waitqueue_head(&info->close_wait);
+               init_completion(&info->shutdown_wait);
+               init_waitqueue_head(&info->delta_msr_wait);
+
+               if (IS_CYC_Z(*cinfo)) {
+                       info->type = PORT_STARTECH;
+                       if (mailbox == ZO_V1)
+                               info->xmit_fifo_size = CYZ_FIFO_SIZE;
+                       else
+                               info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
+#ifdef CONFIG_CYZ_INTR
+                       setup_timer(&cyz_rx_full_timer[port],
+                               cyz_rx_restart, (unsigned long)info);
+#endif
+               } else {
+                       info->type = PORT_CIRRUS;
+                       info->xmit_fifo_size = CyMAX_CHAR_FIFO;
+                       info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
+                       info->cor2 = CyETC;
+                       info->cor3 = 0x08;      /* _very_ small rcv threshold */
+
+                       chip_number = (port - cinfo->first_line) / 4;
+                       if ((info->chip_rev = readb(cinfo->base_addr +
+                                     (cy_chip_offset[chip_number] <<
+                                      index) + (CyGFRCR << index))) >=
+                           CD1400_REV_J) {
+                               /* It is a CD1400 rev. J or later */
+                               info->tbpr = baud_bpr_60[13];   /* Tx BPR */
+                               info->tco = baud_co_60[13];     /* Tx CO */
+                               info->rbpr = baud_bpr_60[13];   /* Rx BPR */
+                               info->rco = baud_co_60[13];     /* Rx CO */
+                               info->rtsdtr_inv = 1;
+                       } else {
+                               info->tbpr = baud_bpr_25[13];   /* Tx BPR */
+                               info->tco = baud_co_25[13];     /* Tx CO */
+                               info->rbpr = baud_bpr_25[13];   /* Rx BPR */
+                               info->rco = baud_co_25[13];     /* Rx CO */
+                               info->rtsdtr_inv = 0;
+                       }
+                       info->read_status_mask = CyTIMEOUT | CySPECHAR |
+                               CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
+               }
+
+       }
+
+#ifndef CONFIG_CYZ_INTR
+       if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) {
+               mod_timer(&cyz_timerlist, jiffies + 1);
+#ifdef CY_PCI_DEBUG
+               printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
+#endif
+       }
+#endif
+       return 0;
+}
+
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
-static unsigned short __init
-cyy_init_card(void __iomem * true_base_addr, int index)
+static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
+               int index)
 {
        unsigned int chip_number;
        void __iomem *base_addr;
@@ -4544,7 +4544,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                base_addr =
                    true_base_addr + (cy_chip_offset[chip_number] << index);
                mdelay(1);
-               if (cy_readb(base_addr + (CyCCR << index)) != 0x00) {
+               if (readb(base_addr + (CyCCR << index)) != 0x00) {
                        /*************
                        printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
                        chip_number, (unsigned long)base_addr);
@@ -4561,7 +4561,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                   chip 4 GFRCR register appears at chip 0, there is no chip 4
                   and this must be a Cyclom-16Y, not a Cyclom-32Ye.
                 */
-               if (chip_number == 4 && cy_readb(true_base_addr +
+               if (chip_number == 4 && readb(true_base_addr +
                                (cy_chip_offset[0] << index) +
                                (CyGFRCR << index)) == 0) {
                        return chip_number;
@@ -4570,7 +4570,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
                mdelay(1);
 
-               if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) {
+               if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
                        /*
                           printk(" chip #%d at %#6lx is not responding ",
                           chip_number, (unsigned long)base_addr);
@@ -4578,7 +4578,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                         */
                        return chip_number;
                }
-               if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) !=
+               if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
                                0x40) {
                        /*
                        printk(" chip #%d at %#6lx is not valid (GFRCR == "
@@ -4589,7 +4589,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                        return chip_number;
                }
                cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
-               if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
+               if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
                        /* It is a CD1400 rev. J or later */
                        /* Impossible to reach 5ms with this chip.
                           Changed to 2ms instead (f = 500 Hz). */
@@ -4602,7 +4602,7 @@ cyy_init_card(void __iomem * true_base_addr, int index)
                /*
                   printk(" chip #%d at %#6lx is rev 0x%2x\n",
                   chip_number, (unsigned long)base_addr,
-                  cy_readb(base_addr+(CyGFRCR<<index)));
+                  readb(base_addr+(CyGFRCR<<index)));
                 */
        }
        return chip_number;
@@ -4647,9 +4647,15 @@ static int __init cy_detect_isa(void)
 
                /* probe for CD1400... */
                cy_isa_address = ioremap(isa_address, CyISA_Ywin);
+               if (cy_isa_address == NULL) {
+                       printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
+                                       "address\n");
+                       continue;
+               }
                cy_isa_nchan = CyPORTS_PER_CHIP *
                        cyy_init_card(cy_isa_address, 0);
                if (cy_isa_nchan == 0) {
+                       iounmap(cy_isa_address);
                        continue;
                }
 #ifdef MODULE
@@ -4660,40 +4666,42 @@ static int __init cy_detect_isa(void)
                        /* find out the board's irq by probing */
                        cy_isa_irq = detect_isa_irq(cy_isa_address);
                if (cy_isa_irq == 0) {
-                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                       printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
+                               "IRQ could not be detected.\n",
                                (unsigned long)cy_isa_address);
-                       printk("but the IRQ could not be detected.\n");
+                       iounmap(cy_isa_address);
                        continue;
                }
 
                if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
-                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                       printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
+                               "more channels are available. Change NR_PORTS "
+                               "in cyclades.c and recompile kernel.\n",
                                (unsigned long)cy_isa_address);
-                       printk("but no more channels are available.\n");
-                       printk("Change NR_PORTS in cyclades.c and recompile "
-                                       "kernel.\n");
+                       iounmap(cy_isa_address);
                        return nboard;
                }
                /* fill the next cy_card structure available */
                for (j = 0; j < NR_CARDS; j++) {
-                       if (cy_card[j].base_addr == 0)
+                       if (cy_card[j].base_addr == NULL)
                                break;
                }
                if (j == NR_CARDS) {    /* no more cy_cards available */
-                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                       printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
+                               "more cards can be used. Change NR_CARDS in "
+                               "cyclades.c and recompile kernel.\n",
                                (unsigned long)cy_isa_address);
-                       printk("but no more cards can be used .\n");
-                       printk("Change NR_CARDS in cyclades.c and recompile "
-                                       "kernel.\n");
+                       iounmap(cy_isa_address);
                        return nboard;
                }
 
                /* allocate IRQ */
                if (request_irq(cy_isa_irq, cyy_interrupt,
                                IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
-                       printk("Cyclom-Y/ISA found at 0x%lx ",
-                               (unsigned long)cy_isa_address);
-                       printk("but could not allocate IRQ#%d.\n", cy_isa_irq);
+                       printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
+                               "could not allocate IRQ#%d.\n",
+                               (unsigned long)cy_isa_address, cy_isa_irq);
+                       iounmap(cy_isa_address);
                        return nboard;
                }
 
@@ -4704,15 +4712,23 @@ static int __init cy_detect_isa(void)
                cy_card[j].bus_index = 0;
                cy_card[j].first_line = cy_next_channel;
                cy_card[j].num_chips = cy_isa_nchan / 4;
+               if (cy_init_card(&cy_card[j])) {
+                       cy_card[j].base_addr = NULL;
+                       free_irq(cy_isa_irq, &cy_card[j]);
+                       iounmap(cy_isa_address);
+                       continue;
+               }
                nboard++;
 
-               /* print message */
-               printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ",
+               printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
+                       "%d channels starting from port %d\n",
                        j + 1, (unsigned long)cy_isa_address,
                        (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
-                       cy_isa_irq);
-               printk("%d channels starting from port %d.\n",
-                       cy_isa_nchan, cy_next_channel);
+                       cy_isa_irq, cy_isa_nchan, cy_next_channel);
+
+               for (j = cy_next_channel;
+                               j < cy_next_channel + cy_isa_nchan; j++)
+                       tty_register_device(cy_serial_driver, j, NULL);
                cy_next_channel += cy_isa_nchan;
        }
        return nboard;
@@ -4721,510 +4737,310 @@ static int __init cy_detect_isa(void)
 #endif                         /* CONFIG_ISA */
 }                              /* cy_detect_isa */
 
-static void plx_init(void __iomem * addr, uclong initctl)
+#ifdef CONFIG_PCI
+static void __devinit plx_init(void __iomem * addr, __u32 initctl)
 {
        /* Reset PLX */
-       cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
+       cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000);
        udelay(100L);
-       cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
+       cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000);
 
        /* Reload Config. Registers from EEPROM */
-       cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
+       cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000);
        udelay(100L);
-       cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
+       cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000);
 }
 
-/*
- * ---------------------------------------------------------------------
- * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI.
- * sets global variables and return the number of PCI boards found.
- * ---------------------------------------------------------------------
- */
-static int __init cy_detect_pci(void)
+static int __devinit cy_pci_probe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
 {
-#ifdef CONFIG_PCI
-
-       struct pci_dev *pdev = NULL;
-       unsigned char cyy_rev_id;
-       unsigned char cy_pci_irq = 0;
-       uclong cy_pci_phys0, cy_pci_phys2;
-       void __iomem *cy_pci_addr0, *cy_pci_addr2;
-       unsigned short i, j, cy_pci_nchan, plx_ver;
-       unsigned short device_id, dev_index = 0;
-       uclong mailbox;
-       uclong ZeIndex = 0;
-       void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
-       uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
-       unsigned char Ze_irq[NR_CARDS];
-       struct pci_dev *Ze_pdev[NR_CARDS];
-
-       for (i = 0; i < NR_CARDS; i++) {
-               /* look for a Cyclades card by vendor and device id */
-               while ((device_id = cy_pci_dev_id[dev_index].device) != 0) {
-                       if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
-                                                  device_id, pdev)) == NULL) {
-                               dev_index++;    /* try next device id */
-                       } else {
-                               break;  /* found a board */
-                       }
-               }
-
-               if (device_id == 0)
-                       break;
-
-               if (pci_enable_device(pdev))
-                       continue;
-
-               /* read PCI configuration area */
-               cy_pci_irq = pdev->irq;
-               cy_pci_phys0 = pci_resource_start(pdev, 0);
-               cy_pci_phys2 = pci_resource_start(pdev, 2);
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
+       void __iomem *addr0 = NULL, *addr2 = NULL;
+       char *card_name = NULL;
+       u32 mailbox;
+       unsigned int device_id, nchan = 0, card_no, i;
+       unsigned char plx_ver;
+       int retval, irq;
+
+       retval = pci_enable_device(pdev);
+       if (retval) {
+               dev_err(&pdev->dev, "cannot enable device\n");
+               goto err;
+       }
 
-               device_id &= ~PCI_DEVICE_ID_MASK;
+       /* read PCI configuration area */
+       irq = pdev->irq;
+       device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
 
-               if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-                               device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-#ifdef CY_PCI_DEBUG
-                       printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-                               pdev->bus->number, pdev->devfn);
-                       printk("rev_id=%d) IRQ%d\n",
-                               cyy_rev_id, (int)cy_pci_irq);
-                       printk("Cyclom-Y/PCI:found  winaddr=0x%lx "
-                               "ctladdr=0x%lx\n",
-                               (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+#if defined(__alpha__)
+       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {   /* below 1M? */
+               dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
+                       "addresses on Alpha systems.\n");
+               retval = -EIO;
+               goto err_dis;
+       }
 #endif
+       if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
+               dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
+                       "addresses\n");
+               retval = -EIO;
+               goto err_dis;
+       }
 
-                       if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-                               printk("  Warning: PCI I/O bit incorrectly "
-                                       "set. Ignoring it...\n");
-                               pdev->resource[2].flags &= ~IORESOURCE_IO;
-                       }
+       if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+               dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
+                               "it...\n");
+               pdev->resource[2].flags &= ~IORESOURCE_IO;
+       }
 
-                       /* Although we don't use this I/O region, we should
-                          request it from the kernel anyway, to avoid problems
-                          with other drivers accessing it. */
-                       if (pci_request_regions(pdev, "Cyclom-Y") != 0) {
-                               printk(KERN_ERR "cyclades: failed to reserve "
-                                               "PCI resources\n");
-                               continue;
-                       }
-#if defined(__alpha__)
-                       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {   /* below 1M? */
-                               printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-                                       pdev->bus->number, pdev->devfn);
-                               printk("rev_id=%d) IRQ%d\n",
-                                       cyy_rev_id, (int)cy_pci_irq);
-                               printk("Cyclom-Y/PCI:found  winaddr=0x%lx "
-                                       "ctladdr=0x%lx\n",
-                                       (ulong)cy_pci_phys2,
-                                       (ulong)cy_pci_phys0);
-                               printk("Cyclom-Y/PCI not supported for low "
-                                       "addresses in Alpha systems.\n");
-                               i--;
-                               continue;
-                       }
-#endif
-                       cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
-                       cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
+       retval = pci_request_regions(pdev, "cyclades");
+       if (retval) {
+               dev_err(&pdev->dev, "failed to reserve resources\n");
+               goto err_dis;
+       }
 
-#ifdef CY_PCI_DEBUG
-                       printk("Cyclom-Y/PCI: relocate winaddr=0x%lx "
-                               "ctladdr=0x%lx\n",
-                               (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
-#endif
-                       cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP *
-                                       cyy_init_card(cy_pci_addr2, 1));
-                       if (cy_pci_nchan == 0) {
-                               printk("Cyclom-Y PCI host card with ");
-                               printk("no Serial-Modules at 0x%lx.\n",
-                                       (ulong) cy_pci_phys2);
-                               i--;
-                               continue;
-                       }
-                       if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
-                               printk("Cyclom-Y/PCI found at 0x%lx ",
-                                       (ulong) cy_pci_phys2);
-                               printk("but no channels are available.\n");
-                               printk("Change NR_PORTS in cyclades.c and "
-                                               "recompile kernel.\n");
-                               return i;
-                       }
-                       /* fill the next cy_card structure available */
-                       for (j = 0; j < NR_CARDS; j++) {
-                               if (cy_card[j].base_addr == 0)
-                                       break;
-                       }
-                       if (j == NR_CARDS) {    /* no more cy_cards available */
-                               printk("Cyclom-Y/PCI found at 0x%lx ",
-                                       (ulong) cy_pci_phys2);
-                               printk("but no more cards can be used.\n");
-                               printk("Change NR_CARDS in cyclades.c and "
-                                               "recompile kernel.\n");
-                               return i;
-                       }
+       retval = -EIO;
+       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+                       device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+               card_name = "Cyclom-Y";
 
-                       /* allocate IRQ */
-                       if (request_irq(cy_pci_irq, cyy_interrupt,
-                                       IRQF_SHARED, "Cyclom-Y", &cy_card[j])) {
-                               printk("Cyclom-Y/PCI found at 0x%lx ",
-                                       (ulong) cy_pci_phys2);
-                               printk("but could not allocate IRQ%d.\n",
-                                       cy_pci_irq);
-                               return i;
-                       }
+               addr0 = pci_iomap(pdev, 0, CyPCI_Yctl);
+               if (addr0 == NULL) {
+                       dev_err(&pdev->dev, "can't remap ctl region\n");
+                       goto err_reg;
+               }
+               addr2 = pci_iomap(pdev, 2, CyPCI_Ywin);
+               if (addr2 == NULL) {
+                       dev_err(&pdev->dev, "can't remap base region\n");
+                       goto err_unmap;
+               }
 
-                       /* set cy_card */
-                       cy_card[j].base_phys = (ulong) cy_pci_phys2;
-                       cy_card[j].ctl_phys = (ulong) cy_pci_phys0;
-                       cy_card[j].base_addr = cy_pci_addr2;
-                       cy_card[j].ctl_addr = cy_pci_addr0;
-                       cy_card[j].irq = (int)cy_pci_irq;
-                       cy_card[j].bus_index = 1;
-                       cy_card[j].first_line = cy_next_channel;
-                       cy_card[j].num_chips = cy_pci_nchan / 4;
-                       cy_card[j].pdev = pdev;
-
-                       /* enable interrupts in the PCI interface */
-                       plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
-                       switch (plx_ver) {
-                       case PLX_9050:
-
-                               cy_writeb(cy_pci_addr0 + 0x4c, 0x43);
-                               break;
+               nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
+               if (nchan == 0) {
+                       dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
+                                       "Serial-Modules\n");
+                       return -EIO;
+               }
+       } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
+               struct RUNTIME_9060 __iomem *ctl_addr;
 
-                       case PLX_9060:
-                       case PLX_9080:
-                       default:        /* Old boards, use PLX_9060 */
-
-                               plx_init(cy_pci_addr0, 0x6c);
-                       /* For some yet unknown reason, once the PLX9060 reloads
-                          the EEPROM, the IRQ is lost and, thus, we have to
-                          re-write it to the PCI config. registers.
-                          This will remain here until we find a permanent
-                          fix. */
-                               pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
-                                               cy_pci_irq);
-
-                               cy_writew(cy_pci_addr0 + 0x68,
-                                         cy_readw(cy_pci_addr0 +
-                                                  0x68) | 0x0900);
-                               break;
-                       }
+               ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl);
+               if (addr0 == NULL) {
+                       dev_err(&pdev->dev, "can't remap ctl region\n");
+                       goto err_reg;
+               }
 
-                       /* print message */
-                       printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
-                               j + 1, (ulong)cy_pci_phys2,
-                               (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1),
-                               (int)cy_pci_irq);
-                       printk("%d channels starting from port %d.\n",
-                               cy_pci_nchan, cy_next_channel);
-
-                       cy_next_channel += cy_pci_nchan;
-               } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
-                       /* print message */
-                       printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-                               pdev->bus->number, pdev->devfn);
-                       printk("rev_id=%d) IRQ%d\n",
-                               cyy_rev_id, (int)cy_pci_irq);
-                       printk("Cyclades-Z/PCI: found winaddr=0x%lx "
-                               "ctladdr=0x%lx\n",
-                               (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
-                       printk("Cyclades-Z/PCI not supported for low "
-                               "addresses\n");
-                       break;
-               } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
-#ifdef CY_PCI_DEBUG
-                       printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-                               pdev->bus->number, pdev->devfn);
-                       printk("rev_id=%d) IRQ%d\n",
-                               cyy_rev_id, (int)cy_pci_irq);
-                       printk("Cyclades-Z/PCI: found winaddr=0x%lx "
-                               "ctladdr=0x%lx\n",
-                               (ulong) cy_pci_phys2, (ulong) cy_pci_phys0);
-#endif
-                       cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
-
-                       /* Disable interrupts on the PLX before resetting it */
-                       cy_writew(cy_pci_addr0 + 0x68,
-                               cy_readw(cy_pci_addr0 + 0x68) & ~0x0900);
-
-                       plx_init(cy_pci_addr0, 0x6c);
-                       /* For some yet unknown reason, once the PLX9060 reloads
-                          the EEPROM, the IRQ is lost and, thus, we have to
-                          re-write it to the PCI config. registers.
-                          This will remain here until we find a permanent
-                          fix. */
-                       pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
-                                               cy_pci_irq);
-
-                       mailbox =
-                           (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
-                                               cy_pci_addr0)->mail_box_0);
-
-                       if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-                               printk("  Warning: PCI I/O bit incorrectly "
-                                       "set. Ignoring it...\n");
-                               pdev->resource[2].flags &= ~IORESOURCE_IO;
-                       }
+               /* Disable interrupts on the PLX before resetting it */
+               cy_writew(addr0 + 0x68,
+                       readw(addr0 + 0x68) & ~0x0900);
+
+               plx_init(addr0, 0x6c);
+               /* For some yet unknown reason, once the PLX9060 reloads
+                  the EEPROM, the IRQ is lost and, thus, we have to
+                  re-write it to the PCI config. registers.
+                  This will remain here until we find a permanent
+                  fix. */
+               pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+
+               mailbox = (u32)readl(&ctl_addr->mail_box_0);
+
+               addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ?
+                               CyPCI_Ze_win : CyPCI_Zwin);
+               if (addr2 == NULL) {
+                       dev_err(&pdev->dev, "can't remap base region\n");
+                       goto err_unmap;
+               }
 
-                       /* Although we don't use this I/O region, we should
-                          request it from the kernel anyway, to avoid problems
-                          with other drivers accessing it. */
-                       if (pci_request_regions(pdev, "Cyclades-Z") != 0) {
-                               printk(KERN_ERR "cyclades: failed to reserve "
-                                       "PCI resources\n");
-                               continue;
-                       }
+               if (mailbox == ZE_V1) {
+                       card_name = "Cyclades-Ze";
 
-                       if (mailbox == ZE_V1) {
-                               cy_pci_addr2 = ioremap(cy_pci_phys2,
-                                               CyPCI_Ze_win);
-                               if (ZeIndex == NR_CARDS) {
-                                       printk("Cyclades-Ze/PCI found at "
-                                               "0x%lx but no more cards can "
-                                               "be used.\nChange NR_CARDS in "
-                                               "cyclades.c and recompile "
-                                               "kernel.\n",
-                                               (ulong)cy_pci_phys2);
-                               } else {
-                                       Ze_phys0[ZeIndex] = cy_pci_phys0;
-                                       Ze_phys2[ZeIndex] = cy_pci_phys2;
-                                       Ze_addr0[ZeIndex] = cy_pci_addr0;
-                                       Ze_addr2[ZeIndex] = cy_pci_addr2;
-                                       Ze_irq[ZeIndex] = cy_pci_irq;
-                                       Ze_pdev[ZeIndex] = pdev;
-                                       ZeIndex++;
-                               }
-                               i--;
-                               continue;
-                       } else {
-                               cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin);
-                       }
+                       readl(&ctl_addr->mail_box_0);
+                       nchan = ZE_V1_NPORTS;
+               } else {
+                       card_name = "Cyclades-8Zo";
 
 #ifdef CY_PCI_DEBUG
-                       printk("Cyclades-Z/PCI: relocate winaddr=0x%lx "
-                               "ctladdr=0x%lx\n",
-                               (ulong) cy_pci_addr2, (ulong) cy_pci_addr0);
                        if (mailbox == ZO_V1) {
-                               cy_writel(&((struct RUNTIME_9060 *)
-                                       (cy_pci_addr0))->loc_addr_base,
-                                       WIN_CREG);
-                               PAUSE;
-                               printk("Cyclades-8Zo/PCI: FPGA id %lx, ver "
-                                       "%lx\n", (ulong) (0xff &
-                                       cy_readl(&((struct CUSTOM_REG *)
-                                               (cy_pci_addr2))->fpga_id)),
-                                       (ulong)(0xff &
-                                       cy_readl(&((struct CUSTOM_REG *)
-                                               (cy_pci_addr2))->
-                                                       fpga_version)));
-                               cy_writel(&((struct RUNTIME_9060 *)
-                                       (cy_pci_addr0))->loc_addr_base,
-                                       WIN_RAM);
+                               cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+                               dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
+                                       "id %lx, ver %lx\n", (ulong)(0xff &
+                                       readl(&((struct CUSTOM_REG *)addr2)->
+                                               fpga_id)), (ulong)(0xff &
+                                       readl(&((struct CUSTOM_REG *)addr2)->
+                                               fpga_version)));
+                               cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
                        } else {
-                               printk("Cyclades-Z/PCI: New Cyclades-Z board.  "
-                                               "FPGA not loaded\n");
+                               dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
+                                       "Cyclades-Z board.  FPGA not loaded\n");
                        }
 #endif
                        /* The following clears the firmware id word.  This
                           ensures that the driver will not attempt to talk to
                           the board until it has been properly initialized.
                         */
-                       PAUSE;
                        if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-                               cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
+                               cy_writel(addr2 + ID_ADDRESS, 0L);
 
                        /* This must be a Cyclades-8Zo/PCI.  The extendable
                           version will have a different device_id and will
                           be allocated its maximum number of ports. */
-                       cy_pci_nchan = 8;
-
-                       if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
-                               printk("Cyclades-8Zo/PCI found at 0x%lx but"
-                                       "no channels are available.\nChange "
-                                       "NR_PORTS in cyclades.c and recompile "
-                                       "kernel.\n", (ulong)cy_pci_phys2);
-                               return i;
-                       }
-
-                       /* fill the next cy_card structure available */
-                       for (j = 0; j < NR_CARDS; j++) {
-                               if (cy_card[j].base_addr == 0)
-                                       break;
-                       }
-                       if (j == NR_CARDS) {    /* no more cy_cards available */
-                               printk("Cyclades-8Zo/PCI found at 0x%lx but"
-                                       "no more cards can be used.\nChange "
-                                       "NR_CARDS in cyclades.c and recompile "
-                                       "kernel.\n", (ulong)cy_pci_phys2);
-                               return i;
-                       }
-#ifdef CONFIG_CYZ_INTR
-                       /* allocate IRQ only if board has an IRQ */
-                       if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
-                               if (request_irq(cy_pci_irq, cyz_interrupt,
-                                               IRQF_SHARED, "Cyclades-Z",
-                                               &cy_card[j])) {
-                                       printk("Cyclom-8Zo/PCI found at 0x%lx "
-                                               "but could not allocate "
-                                               "IRQ%d.\n", (ulong)cy_pci_phys2,
-                                               cy_pci_irq);
-                                       return i;
-                               }
-                       }
-#endif                         /* CONFIG_CYZ_INTR */
-
-                       /* set cy_card */
-                       cy_card[j].base_phys = cy_pci_phys2;
-                       cy_card[j].ctl_phys = cy_pci_phys0;
-                       cy_card[j].base_addr = cy_pci_addr2;
-                       cy_card[j].ctl_addr = cy_pci_addr0;
-                       cy_card[j].irq = (int)cy_pci_irq;
-                       cy_card[j].bus_index = 1;
-                       cy_card[j].first_line = cy_next_channel;
-                       cy_card[j].num_chips = -1;
-                       cy_card[j].pdev = pdev;
-
-                       /* print message */
-#ifdef CONFIG_CYZ_INTR
-                       /* don't report IRQ if board is no IRQ */
-                       if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
-                               printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, "
-                                       "IRQ%d, ", j + 1, (ulong)cy_pci_phys2,
-                                       (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1),
-                                       (int)cy_pci_irq);
-                       else
-#endif                         /* CONFIG_CYZ_INTR */
-                               printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
-                                       j + 1, (ulong)cy_pci_phys2,
-                                       (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1));
-
-                       printk("%d channels starting from port %d.\n",
-                                       cy_pci_nchan, cy_next_channel);
-                       cy_next_channel += cy_pci_nchan;
+                       nchan = 8;
                }
        }
 
-       for (; ZeIndex != 0 && i < NR_CARDS; i++) {
-               cy_pci_phys0 = Ze_phys0[0];
-               cy_pci_phys2 = Ze_phys2[0];
-               cy_pci_addr0 = Ze_addr0[0];
-               cy_pci_addr2 = Ze_addr2[0];
-               cy_pci_irq = Ze_irq[0];
-               pdev = Ze_pdev[0];
-               for (j = 0; j < ZeIndex - 1; j++) {
-                       Ze_phys0[j] = Ze_phys0[j + 1];
-                       Ze_phys2[j] = Ze_phys2[j + 1];
-                       Ze_addr0[j] = Ze_addr0[j + 1];
-                       Ze_addr2[j] = Ze_addr2[j + 1];
-                       Ze_irq[j] = Ze_irq[j + 1];
-                       Ze_pdev[j] = Ze_pdev[j + 1];
-               }
-               ZeIndex--;
-               mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
-                                               cy_pci_addr0)->mail_box_0);
-#ifdef CY_PCI_DEBUG
-               printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
-                       (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
-               printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not "
-                               "loaded\n");
-#endif
-               PAUSE;
-               /* This must be the new Cyclades-Ze/PCI. */
-               cy_pci_nchan = ZE_V1_NPORTS;
-
-               if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
-                       printk("Cyclades-Ze/PCI found at 0x%lx but no channels "
-                               "are available.\nChange NR_PORTS in cyclades.c "
-                               "and recompile kernel.\n",
-                               (ulong) cy_pci_phys2);
-                       return i;
-               }
+       if ((cy_next_channel + nchan) > NR_PORTS) {
+               dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
+                       "channels are available. Change NR_PORTS in "
+                       "cyclades.c and recompile kernel.\n");
+               goto err_unmap;
+       }
+       /* fill the next cy_card structure available */
+       for (card_no = 0; card_no < NR_CARDS; card_no++) {
+               if (cy_card[card_no].base_addr == NULL)
+                       break;
+       }
+       if (card_no == NR_CARDS) {      /* no more cy_cards available */
+               dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
+                       "more cards can be used. Change NR_CARDS in "
+                       "cyclades.c and recompile kernel.\n");
+               goto err_unmap;
+       }
 
-               /* fill the next cy_card structure available */
-               for (j = 0; j < NR_CARDS; j++) {
-                       if (cy_card[j].base_addr == 0)
-                               break;
-               }
-               if (j == NR_CARDS) {    /* no more cy_cards available */
-                       printk("Cyclades-Ze/PCI found at 0x%lx but no more "
-                               "cards can be used.\nChange NR_CARDS in "
-                               "cyclades.c and recompile kernel.\n",
-                               (ulong) cy_pci_phys2);
-                       return i;
+       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+                       device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+               /* allocate IRQ */
+               retval = request_irq(irq, cyy_interrupt,
+                               IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+               if (retval) {
+                       dev_err(&pdev->dev, "could not allocate IRQ\n");
+                       goto err_unmap;
                }
+               cy_card[card_no].num_chips = nchan / 4;
+       } else {
 #ifdef CONFIG_CYZ_INTR
                /* allocate IRQ only if board has an IRQ */
-               if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
-                       if (request_irq(cy_pci_irq, cyz_interrupt,
+               if (irq != 0 && irq != 255) {
+                       retval = request_irq(irq, cyz_interrupt,
                                        IRQF_SHARED, "Cyclades-Z",
-                                       &cy_card[j])) {
-                               printk("Cyclom-Ze/PCI found at 0x%lx ",
-                                       (ulong) cy_pci_phys2);
-                               printk("but could not allocate IRQ%d.\n",
-                                       cy_pci_irq);
-                               return i;
+                                       &cy_card[card_no]);
+                       if (retval) {
+                               dev_err(&pdev->dev, "could not allocate IRQ\n");
+                               goto err_unmap;
                        }
                }
 #endif                         /* CONFIG_CYZ_INTR */
+               cy_card[card_no].num_chips = -1;
+       }
 
-               /* set cy_card */
-               cy_card[j].base_phys = cy_pci_phys2;
-               cy_card[j].ctl_phys = cy_pci_phys0;
-               cy_card[j].base_addr = cy_pci_addr2;
-               cy_card[j].ctl_addr = cy_pci_addr0;
-               cy_card[j].irq = (int)cy_pci_irq;
-               cy_card[j].bus_index = 1;
-               cy_card[j].first_line = cy_next_channel;
-               cy_card[j].num_chips = -1;
-               cy_card[j].pdev = pdev;
+       /* set cy_card */
+       cy_card[card_no].base_addr = addr2;
+       cy_card[card_no].ctl_addr = addr0;
+       cy_card[card_no].irq = irq;
+       cy_card[card_no].bus_index = 1;
+       cy_card[card_no].first_line = cy_next_channel;
+       retval = cy_init_card(&cy_card[card_no]);
+       if (retval)
+               goto err_null;
 
-               /* print message */
-#ifdef CONFIG_CYZ_INTR
-               /* don't report IRQ if board is no IRQ */
-               if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
-                       printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
-                               j + 1, (ulong) cy_pci_phys2,
-                               (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1),
-                               (int)cy_pci_irq);
-               else
-#endif                         /* CONFIG_CYZ_INTR */
-                       printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
-                               j + 1, (ulong) cy_pci_phys2,
-                               (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1));
+       pci_set_drvdata(pdev, &cy_card[card_no]);
 
-               printk("%d channels starting from port %d.\n",
-                       cy_pci_nchan, cy_next_channel);
-               cy_next_channel += cy_pci_nchan;
-       }
-       if (ZeIndex != 0) {
-               printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be "
-                       "used.\nChange NR_CARDS in cyclades.c and recompile "
-                       "kernel.\n", (unsigned int)Ze_phys2[0]);
+       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+                       device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+               /* enable interrupts in the PCI interface */
+               plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
+               switch (plx_ver) {
+               case PLX_9050:
+
+                       cy_writeb(addr0 + 0x4c, 0x43);
+                       break;
+
+               case PLX_9060:
+               case PLX_9080:
+               default:        /* Old boards, use PLX_9060 */
+
+                       plx_init(addr0, 0x6c);
+               /* For some yet unknown reason, once the PLX9060 reloads
+                  the EEPROM, the IRQ is lost and, thus, we have to
+                  re-write it to the PCI config. registers.
+                  This will remain here until we find a permanent
+                  fix. */
+                       pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+
+                       cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
+                       break;
+               }
        }
-       return i;
-#else
+
+       dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
+               "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
+       for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
+               tty_register_device(cy_serial_driver, i, &pdev->dev);
+       cy_next_channel += nchan;
+
        return 0;
-#endif                         /* ifdef CONFIG_PCI */
-}                              /* cy_detect_pci */
+err_null:
+       cy_card[card_no].base_addr = NULL;
+       free_irq(irq, &cy_card[card_no]);
+err_unmap:
+       pci_iounmap(pdev, addr0);
+       if (addr2)
+               pci_iounmap(pdev, addr2);
+err_reg:
+       pci_release_regions(pdev);
+err_dis:
+       pci_disable_device(pdev);
+err:
+       return retval;
+}
 
-/*
- * This routine prints out the appropriate serial driver version number
- * and identifies which options were configured into this driver.
- */
-static inline void show_version(void)
+static void __devexit cy_pci_remove(struct pci_dev *pdev)
 {
-       printk("Cyclades driver " CY_VERSION "\n");
-       printk("        built %s %s\n", __DATE__, __TIME__);
-}                              /* show_version */
+       struct cyclades_card *cinfo = pci_get_drvdata(pdev);
+       unsigned int i;
+
+       /* non-Z with old PLX */
+       if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
+                       PLX_9050)
+               cy_writeb(cinfo->ctl_addr + 0x4c, 0);
+       else
+#ifndef CONFIG_CYZ_INTR
+               if (!IS_CYC_Z(*cinfo))
+#endif
+               cy_writew(cinfo->ctl_addr + 0x68,
+                               readw(cinfo->ctl_addr + 0x68) & ~0x0900);
+
+       pci_iounmap(pdev, cinfo->base_addr);
+       if (cinfo->ctl_addr)
+               pci_iounmap(pdev, cinfo->ctl_addr);
+       if (cinfo->irq
+#ifndef CONFIG_CYZ_INTR
+               && !IS_CYC_Z(*cinfo)
+#endif /* CONFIG_CYZ_INTR */
+               )
+               free_irq(cinfo->irq, cinfo);
+       pci_release_regions(pdev);
+
+       cinfo->base_addr = NULL;
+       for (i = cinfo->first_line; i < cinfo->first_line +
+                       cinfo->nports; i++)
+               tty_unregister_device(cy_serial_driver, i);
+       cinfo->nports = 0;
+       kfree(cinfo->ports);
+}
+
+static struct pci_driver cy_pci_driver = {
+       .name = "cyclades",
+       .id_table = cy_pci_dev_id,
+       .probe = cy_pci_probe,
+       .remove = __devexit_p(cy_pci_remove)
+};
+#endif
 
 static int
 cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
                int *eof, void *data)
 {
        struct cyclades_port *info;
-       int i;
+       unsigned int i, j;
        int len = 0;
        off_t begin = 0;
        off_t pos = 0;
@@ -5238,33 +5054,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
        len += size;
 
        /* Output one line for each known port */
-       for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
-               info = &cy_port[i];
-
-               if (info->count)
-                       size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
-                               "%8lu %9lu %6ld\n", info->line,
-                               (cur_jifs - info->idle_stats.in_use) / HZ,
-                               info->idle_stats.xmit_bytes,
-                               (cur_jifs - info->idle_stats.xmit_idle) / HZ,
-                               info->idle_stats.recv_bytes,
-                               (cur_jifs - info->idle_stats.recv_idle) / HZ,
-                               info->idle_stats.overruns,
-                               (long)info->tty->ldisc.num);
-               else
-                       size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
-                               "%8lu %9lu %6ld\n",
-                               info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
-               len += size;
-               pos = begin + len;
-
-               if (pos < offset) {
-                       len = 0;
-                       begin = pos;
+       for (i = 0; i < NR_CARDS; i++)
+               for (j = 0; j < cy_card[i].nports; j++) {
+                       info = &cy_card[i].ports[j];
+
+                       if (info->count)
+                               size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
+                                       "%10lu %8lu %9lu %6ld\n", info->line,
+                                       (cur_jifs - info->idle_stats.in_use) /
+                                       HZ, info->idle_stats.xmit_bytes,
+                                       (cur_jifs - info->idle_stats.xmit_idle)/
+                                       HZ, info->idle_stats.recv_bytes,
+                                       (cur_jifs - info->idle_stats.recv_idle)/
+                                       HZ, info->idle_stats.overruns,
+                                       (long)info->tty->ldisc.num);
+                       else
+                               size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
+                                       "%10lu %8lu %9lu %6ld\n",
+                                       info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+                       len += size;
+                       pos = begin + len;
+
+                       if (pos < offset) {
+                               len = 0;
+                               begin = pos;
+                       }
+                       if (pos > offset + length)
+                               goto done;
                }
-               if (pos > offset + length)
-                       goto done;
-       }
        *eof = 1;
 done:
        *start = buf + (offset - begin);        /* Start of wanted data */
@@ -5319,18 +5136,15 @@ static const struct tty_operations cy_ops = {
 
 static int __init cy_init(void)
 {
-       struct cyclades_port *info;
-       struct cyclades_card *cinfo;
-       int number_z_boards = 0;
-       int board, port, i, index;
-       unsigned long mailbox;
-       unsigned short chip_number;
-       int nports;
+       unsigned int nboards;
+       int retval = -ENOMEM;
 
        cy_serial_driver = alloc_tty_driver(NR_PORTS);
        if (!cy_serial_driver)
-               return -ENOMEM;
-       show_version();
+               goto err;
+
+       printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n",
+                       __DATE__, __TIME__);
 
        /* Initialize the tty_driver structure */
 
@@ -5344,15 +5158,13 @@ static int __init cy_init(void)
        cy_serial_driver->init_termios = tty_std_termios;
        cy_serial_driver->init_termios.c_cflag =
            B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+       cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        tty_set_operations(cy_serial_driver, &cy_ops);
 
-       if (tty_register_driver(cy_serial_driver))
-               panic("Couldn't register Cyclades serial driver\n");
-
-       for (i = 0; i < NR_CARDS; i++) {
-               /* base_addr=0 indicates board not found */
-               cy_card[i].base_addr = NULL;
+       retval = tty_register_driver(cy_serial_driver);
+       if (retval) {
+               printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
+               goto err_frtty;
        }
 
        /* the code below is responsible to find the boards. Each different
@@ -5363,223 +5175,68 @@ static int __init cy_init(void)
           the cy_next_channel. */
 
        /* look for isa boards */
-       cy_isa_nboard = cy_detect_isa();
+       nboards = cy_detect_isa();
 
+#ifdef CONFIG_PCI
        /* look for pci boards */
-       cy_pci_nboard = cy_detect_pci();
-
-       cy_nboard = cy_isa_nboard + cy_pci_nboard;
-
-       /* invalidate remaining cy_card structures */
-       for (i = 0; i < NR_CARDS; i++) {
-               if (cy_card[i].base_addr == 0) {
-                       cy_card[i].first_line = -1;
-                       cy_card[i].ctl_addr = NULL;
-                       cy_card[i].irq = 0;
-                       cy_card[i].bus_index = 0;
-                       cy_card[i].first_line = 0;
-                       cy_card[i].num_chips = 0;
-               }
-       }
-       /* invalidate remaining cy_port structures */
-       for (i = cy_next_channel; i < NR_PORTS; i++) {
-               cy_port[i].line = -1;
-               cy_port[i].magic = -1;
-       }
-
-       /* initialize per-port data structures for each valid board found */
-       for (board = 0; board < cy_nboard; board++) {
-               cinfo = &cy_card[board];
-               if (cinfo->num_chips == -1) {   /* Cyclades-Z */
-                       number_z_boards++;
-                       mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
-                                            cy_card[board].ctl_addr)->
-                                          mail_box_0);
-                       nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
-                       cinfo->intr_enabled = 0;
-                       cinfo->nports = 0;      /* Will be correctly set later, after 
-                                                  Z FW is loaded */
-                       spin_lock_init(&cinfo->card_lock);
-                       for (port = cinfo->first_line;
-                            port < cinfo->first_line + nports; port++) {
-                               info = &cy_port[port];
-                               info->magic = CYCLADES_MAGIC;
-                               info->type = PORT_STARTECH;
-                               info->card = board;
-                               info->line = port;
-                               info->chip_rev = 0;
-                               info->flags = STD_COM_FLAGS;
-                               info->tty = NULL;
-                               if (mailbox == ZO_V1)
-                                       info->xmit_fifo_size = CYZ_FIFO_SIZE;
-                               else
-                                       info->xmit_fifo_size =
-                                           4 * CYZ_FIFO_SIZE;
-                               info->cor1 = 0;
-                               info->cor2 = 0;
-                               info->cor3 = 0;
-                               info->cor4 = 0;
-                               info->cor5 = 0;
-                               info->tbpr = 0;
-                               info->tco = 0;
-                               info->rbpr = 0;
-                               info->rco = 0;
-                               info->custom_divisor = 0;
-                               info->close_delay = 5 * HZ / 10;
-                               info->closing_wait = CLOSING_WAIT_DELAY;
-                               info->icount.cts = info->icount.dsr =
-                                   info->icount.rng = info->icount.dcd = 0;
-                               info->icount.rx = info->icount.tx = 0;
-                               info->icount.frame = info->icount.parity = 0;
-                               info->icount.overrun = info->icount.brk = 0;
-                               info->x_char = 0;
-                               info->event = 0;
-                               info->count = 0;
-                               info->blocked_open = 0;
-                               info->default_threshold = 0;
-                               info->default_timeout = 0;
-                               INIT_WORK(&info->tqueue, do_softint);
-                               init_waitqueue_head(&info->open_wait);
-                               init_waitqueue_head(&info->close_wait);
-                               init_waitqueue_head(&info->shutdown_wait);
-                               init_waitqueue_head(&info->delta_msr_wait);
-                               /* info->session */
-                               /* info->pgrp */
-                               info->read_status_mask = 0;
-                               /* info->timeout */
-                               /* Bentson's vars */
-                               info->jiffies[0] = 0;
-                               info->jiffies[1] = 0;
-                               info->jiffies[2] = 0;
-                               info->rflush_count = 0;
-#ifdef CONFIG_CYZ_INTR
-                               init_timer(&cyz_rx_full_timer[port]);
-                               cyz_rx_full_timer[port].function = NULL;
+       retval = pci_register_driver(&cy_pci_driver);
+       if (retval && !nboards)
+               goto err_unr;
 #endif
-                       }
-                       continue;
-               } else {        /* Cyclom-Y of some kind */
-                       index = cinfo->bus_index;
-                       spin_lock_init(&cinfo->card_lock);
-                       cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
-                       for (port = cinfo->first_line;
-                            port < cinfo->first_line + cinfo->nports; port++) {
-                               info = &cy_port[port];
-                               info->magic = CYCLADES_MAGIC;
-                               info->type = PORT_CIRRUS;
-                               info->card = board;
-                               info->line = port;
-                               info->flags = STD_COM_FLAGS;
-                               info->tty = NULL;
-                               info->xmit_fifo_size = CyMAX_CHAR_FIFO;
-                               info->cor1 =
-                                   CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
-                               info->cor2 = CyETC;
-                               info->cor3 = 0x08;      /* _very_ small rcv threshold */
-                               info->cor4 = 0;
-                               info->cor5 = 0;
-                               info->custom_divisor = 0;
-                               info->close_delay = 5 * HZ / 10;
-                               info->closing_wait = CLOSING_WAIT_DELAY;
-                               info->icount.cts = info->icount.dsr =
-                                   info->icount.rng = info->icount.dcd = 0;
-                               info->icount.rx = info->icount.tx = 0;
-                               info->icount.frame = info->icount.parity = 0;
-                               info->icount.overrun = info->icount.brk = 0;
-                               chip_number = (port - cinfo->first_line) / 4;
-                               if ((info->chip_rev =
-                                    cy_readb(cinfo->base_addr +
-                                             (cy_chip_offset[chip_number] <<
-                                              index) + (CyGFRCR << index))) >=
-                                   CD1400_REV_J) {
-                                       /* It is a CD1400 rev. J or later */
-                                       info->tbpr = baud_bpr_60[13];   /* Tx BPR */
-                                       info->tco = baud_co_60[13];     /* Tx CO */
-                                       info->rbpr = baud_bpr_60[13];   /* Rx BPR */
-                                       info->rco = baud_co_60[13];     /* Rx CO */
-                                       info->rflow = 0;
-                                       info->rtsdtr_inv = 1;
-                               } else {
-                                       info->tbpr = baud_bpr_25[13];   /* Tx BPR */
-                                       info->tco = baud_co_25[13];     /* Tx CO */
-                                       info->rbpr = baud_bpr_25[13];   /* Rx BPR */
-                                       info->rco = baud_co_25[13];     /* Rx CO */
-                                       info->rflow = 0;
-                                       info->rtsdtr_inv = 0;
-                               }
-                               info->x_char = 0;
-                               info->event = 0;
-                               info->count = 0;
-                               info->blocked_open = 0;
-                               info->default_threshold = 0;
-                               info->default_timeout = 0;
-                               INIT_WORK(&info->tqueue, do_softint);
-                               init_waitqueue_head(&info->open_wait);
-                               init_waitqueue_head(&info->close_wait);
-                               init_waitqueue_head(&info->shutdown_wait);
-                               init_waitqueue_head(&info->delta_msr_wait);
-                               /* info->session */
-                               /* info->pgrp */
-                               info->read_status_mask =
-                                   CyTIMEOUT | CySPECHAR | CyBREAK
-                                   | CyPARITY | CyFRAME | CyOVERRUN;
-                               /* info->timeout */
-                       }
-               }
-       }
-
-#ifndef CONFIG_CYZ_INTR
-       if (number_z_boards && !cyz_timeron) {
-               cyz_timeron++;
-               cyz_timerlist.expires = jiffies + 1;
-               add_timer(&cyz_timerlist);
-#ifdef CY_PCI_DEBUG
-               printk("Cyclades-Z polling initialized\n");
-#endif
-       }
-#endif                         /* CONFIG_CYZ_INTR */
 
        return 0;
-
+err_unr:
+       tty_unregister_driver(cy_serial_driver);
+err_frtty:
+       put_tty_driver(cy_serial_driver);
+err:
+       return retval;
 }                              /* cy_init */
 
 static void __exit cy_cleanup_module(void)
 {
+       struct cyclades_card *card;
        int i, e1;
 
 #ifndef CONFIG_CYZ_INTR
-       if (cyz_timeron){
-               cyz_timeron = 0;
-               del_timer(&cyz_timerlist);
-       }
+       del_timer_sync(&cyz_timerlist);
 #endif /* CONFIG_CYZ_INTR */
 
        if ((e1 = tty_unregister_driver(cy_serial_driver)))
-               printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
-                       e1);
+               printk(KERN_ERR "failed to unregister Cyclades serial "
+                               "driver(%d)\n", e1);
 
-       put_tty_driver(cy_serial_driver);
+#ifdef CONFIG_PCI
+       pci_unregister_driver(&cy_pci_driver);
+#endif
 
        for (i = 0; i < NR_CARDS; i++) {
-               if (cy_card[i].base_addr) {
-                       iounmap(cy_card[i].base_addr);
-                       if (cy_card[i].ctl_addr)
-                               iounmap(cy_card[i].ctl_addr);
-                       if (cy_card[i].irq
+               card = &cy_card[i];
+               if (card->base_addr) {
+                       /* clear interrupt */
+                       cy_writeb(card->base_addr + Cy_ClrIntr, 0);
+                       iounmap(card->base_addr);
+                       if (card->ctl_addr)
+                               iounmap(card->ctl_addr);
+                       if (card->irq
 #ifndef CONFIG_CYZ_INTR
-                               && cy_card[i].num_chips != -1 /* not a Z card */
+                               && !IS_CYC_Z(*card)
 #endif /* CONFIG_CYZ_INTR */
                                )
-                               free_irq(cy_card[i].irq, &cy_card[i]);
-#ifdef CONFIG_PCI
-                       if (cy_card[i].pdev)
-                               pci_release_regions(cy_card[i].pdev);
-#endif
+                               free_irq(card->irq, card);
+                       for (e1 = card->first_line;
+                                       e1 < card->first_line +
+                                       card->nports; e1++)
+                               tty_unregister_device(cy_serial_driver, e1);
+                       kfree(card->ports);
                }
        }
+
+       put_tty_driver(cy_serial_driver);
 } /* cy_cleanup_module */
 
 module_init(cy_init);
 module_exit(cy_cleanup_module);
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CY_VERSION);
diff --git a/drivers/char/digi.h b/drivers/char/digi.h
deleted file mode 100644 (file)
index 19df0e8..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*          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 */
-#endif
-
-#if !defined(TIOCMSET)
-#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 */
-#endif
-
-#if !defined(TIOCSDTR)
-#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_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 */
-                                               /* control characters    */
-#define        DIGI_SETFLOW    (('e'<<8) | 100)                /* Set startc/stopc flow */
-                                               /* control characters    */
-#define        DIGI_GETAFLOW   (('e'<<8) | 101)                /* Get Aux. startc/stopc */
-                                               /* flow control chars    */
-#define        DIGI_SETAFLOW   (('e'<<8) | 102)                /* Set Aux. startc/stopc */
-                                               /* flow control chars    */
-
-struct digiflow_struct {
-       unsigned char   startc;                         /* flow cntl start char */
-       unsigned char   stopc;                          /* flow cntl stop char  */
-};
-
-typedef struct digiflow_struct digiflow_t;
-
-
-/************************************************************************
- * Values for digi_flags 
- ************************************************************************/
-#define DIGI_IXON      0x0001          /* Handle IXON in the FEP       */
-#define DIGI_FAST      0x0002          /* Fast baud rates              */
-#define RTSPACE                0x0004          /* RTS input flow control       */
-#define CTSPACE                0x0008          /* CTS output flow control      */
-#define DSRPACE                0x0010          /* DSR output flow control      */
-#define DCDPACE                0x0020          /* DCD output flow control      */
-#define DTRPACE                0x0040          /* DTR input flow control       */
-#define DIGI_FORCEDCD  0x0100          /* Force carrier                */
-#define        DIGI_ALTPIN     0x0200          /* Alternate RJ-45 pin config   */
-#define        DIGI_AIXON      0x0400          /* Aux flow control in fep      */
-
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_struct {
-       unsigned short  digi_flags;             /* Flags (see above)    */
-};
-
-typedef struct digi_struct digi_t;
index bd7be09ea53df24a7bea3301f579d18902fa79bb..5b91bc04ea4e806d0bbc30e8b2845d6cdc4e2020 100644 (file)
 
 #include "drmP.h"
 
-#if PAGE_SIZE == 65536
-# define ATI_PCIGART_TABLE_ORDER       0
-# define ATI_PCIGART_TABLE_PAGES       (1 << 0)
-#elif PAGE_SIZE == 16384
-# define ATI_PCIGART_TABLE_ORDER       1
-# define ATI_PCIGART_TABLE_PAGES       (1 << 1)
-#elif PAGE_SIZE == 8192
-# define ATI_PCIGART_TABLE_ORDER       2
-# define ATI_PCIGART_TABLE_PAGES       (1 << 2)
-#elif PAGE_SIZE == 4096
-# define ATI_PCIGART_TABLE_ORDER       3
-# define ATI_PCIGART_TABLE_PAGES       (1 << 3)
-#else
-# error - PAGE_SIZE not 64K, 16K, 8K or 4K
-#endif
-
-# define ATI_MAX_PCIGART_PAGES         8192    /**< 32 MB aperture, 4K pages */
 # define ATI_PCIGART_PAGE_SIZE         4096    /**< PCI GART page size */
 
-static void *drm_ati_alloc_pcigart_table(void)
+static void *drm_ati_alloc_pcigart_table(int order)
 {
        unsigned long address;
        struct page *page;
        int i;
-       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order);
 
        address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
-                                  ATI_PCIGART_TABLE_ORDER);
+                                  order);
        if (address == 0UL) {
                return NULL;
        }
 
        page = virt_to_page(address);
 
-       for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
+       for (i = 0; i < order; i++, page++)
                SetPageReserved(page);
 
        DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
        return (void *)address;
 }
 
-static void drm_ati_free_pcigart_table(void *address)
+static void drm_ati_free_pcigart_table(void *address, int order)
 {
        struct page *page;
        int i;
+       int num_pages = 1 << order;
        DRM_DEBUG("%s\n", __FUNCTION__);
 
        page = virt_to_page((unsigned long)address);
 
-       for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
+       for (i = 0; i < num_pages; i++, page++)
                ClearPageReserved(page);
 
-       free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER);
+       free_pages((unsigned long)address, order);
 }
 
 int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
@@ -93,6 +78,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
        drm_sg_mem_t *entry = dev->sg;
        unsigned long pages;
        int i;
+       int order;
+       int num_pages, max_pages;
 
        /* we need to support large memory configurations */
        if (!entry) {
@@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
                return 0;
        }
 
+       order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
+       num_pages = 1 << order;
+
        if (gart_info->bus_addr) {
                if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
                        pci_unmap_single(dev->pdev, gart_info->bus_addr,
-                                        ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+                                        num_pages * PAGE_SIZE,
                                         PCI_DMA_TODEVICE);
                }
 
-               pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
-                   ? entry->pages : ATI_MAX_PCIGART_PAGES;
+               max_pages = (gart_info->table_size / sizeof(u32));
+               pages = (entry->pages <= max_pages)
+                 ? entry->pages : max_pages;
 
                for (i = 0; i < pages; i++) {
                        if (!entry->busaddr[i])
@@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
 
        if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
            && gart_info->addr) {
-               drm_ati_free_pcigart_table(gart_info->addr);
+               drm_ati_free_pcigart_table(gart_info->addr, order);
                gart_info->addr = NULL;
        }
 
        return 1;
 }
-
 EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
 
 int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
@@ -139,6 +129,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
        unsigned long pages;
        u32 *pci_gart, page_base, bus_address = 0;
        int i, j, ret = 0;
+       int order;
+       int max_pages;
+       int num_pages;
 
        if (!entry) {
                DRM_ERROR("no scatter/gather memory!\n");
@@ -148,7 +141,10 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
        if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
                DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
 
-               address = drm_ati_alloc_pcigart_table();
+               order = drm_order((gart_info->table_size +
+                                  (PAGE_SIZE-1)) / PAGE_SIZE);
+               num_pages = 1 << order;
+               address = drm_ati_alloc_pcigart_table(order);
                if (!address) {
                        DRM_ERROR("cannot allocate PCI GART page!\n");
                        goto done;
@@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
                }
 
                bus_address = pci_map_single(dev->pdev, address,
-                                            ATI_PCIGART_TABLE_PAGES *
-                                            PAGE_SIZE, PCI_DMA_TODEVICE);
+                                            num_pages * PAGE_SIZE,
+                                            PCI_DMA_TODEVICE);
                if (bus_address == 0) {
                        DRM_ERROR("unable to map PCIGART pages!\n");
-                       drm_ati_free_pcigart_table(address);
+                       order = drm_order((gart_info->table_size +
+                                          (PAGE_SIZE-1)) / PAGE_SIZE);
+                       drm_ati_free_pcigart_table(address, order);
                        address = NULL;
                        goto done;
                }
@@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
 
        pci_gart = (u32 *) address;
 
-       pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
-           ? entry->pages : ATI_MAX_PCIGART_PAGES;
+       max_pages = (gart_info->table_size / sizeof(u32));
+       pages = (entry->pages <= max_pages)
+           ? entry->pages : max_pages;
 
-       memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32));
+       memset(pci_gart, 0, max_pages * sizeof(u32));
 
        for (i = 0; i < pages; i++) {
                /* we need to support large memory configurations */
@@ -198,10 +197,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
                page_base = (u32) entry->busaddr[i];
 
                for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
-                       if (gart_info->is_pcie)
+                       switch(gart_info->gart_reg_if) {
+                       case DRM_ATI_GART_IGP:
+                               *pci_gart = cpu_to_le32((page_base) | 0xc);
+                               break;
+                       case DRM_ATI_GART_PCIE:
                                *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
-                       else
+                               break;
+                       default:
+                       case DRM_ATI_GART_PCI:
                                *pci_gart = cpu_to_le32(page_base);
+                               break;
+                       }
                        pci_gart++;
                        page_base += ATI_PCIGART_PAGE_SIZE;
                }
@@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
        gart_info->bus_addr = bus_address;
        return ret;
 }
-
 EXPORT_SYMBOL(drm_ati_pcigart_init);
index 80041d5b792df40bfb7e027f76a235940575eebb..d494315752a2c1671d8b0074b4f45e4edfc14015 100644 (file)
@@ -519,12 +519,17 @@ typedef struct drm_vbl_sig {
 #define DRM_ATI_GART_MAIN 1
 #define DRM_ATI_GART_FB   2
 
+#define DRM_ATI_GART_PCI 1
+#define DRM_ATI_GART_PCIE 2
+#define DRM_ATI_GART_IGP 3
+
 typedef struct ati_pcigart_info {
        int gart_table_location;
-       int is_pcie;
+       int gart_reg_if;
        void *addr;
        dma_addr_t bus_addr;
        drm_local_map_t mapping;
+       int table_size;
 } drm_ati_pcigart_info;
 
 /*
index 892db7096986aaa9e0af7f111cfb614982e84686..32ed19c9ec1c0b1bb36c4e0f51811ca3814377e7 100644 (file)
@@ -65,7 +65,7 @@ int drm_dma_setup(drm_device_t * dev)
  * \param dev DRM device.
  *
  * Free all pages associated with DMA buffers, the buffers and pages lists, and
- * finally the the drm_device::dma structure itself.
+ * finally the drm_device::dma structure itself.
  */
 void drm_dma_takedown(drm_device_t * dev)
 {
index 26bec30ee86e1d75899789e837ef1af3d41ccbe1..8e77b7ed0f44bf2fcd860c08d7862bd821660ed0 100644 (file)
@@ -15,8 +15,6 @@
  * #define DRIVER_DESC         "Matrox G200/G400"
  * #define DRIVER_DATE         "20001127"
  *
- * #define DRIVER_IOCTL_COUNT  DRM_ARRAY_SIZE( mga_ioctls )
- *
  * #define drm_x               mga_##x
  * \endcode
  */
@@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 };
 
-#define DRIVER_IOCTL_COUNT     ARRAY_SIZE( drm_ioctls )
+#define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
 
 /**
  * Take down the DRM device.
@@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp,
                  (long)old_encode_dev(priv->head->device),
                  priv->authenticated);
 
-       if ((nr >= DRIVER_IOCTL_COUNT) &&
+       if ((nr >= DRM_CORE_IOCTL_COUNT) &&
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
                goto err_i1;
-       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
-                && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
                ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
        else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
                ioctl = &drm_ioctls[nr];
index 2908b72daa6e9a333c3ebfb46bf296f3596abd81..0fe7b449792797949cb7ca579a6cb39dffa19049 100644 (file)
@@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
 
 #endif
 
-/** Task queue handler arguments */
-#define DRM_TASKQUEUE_ARGS     void *arg
-
 /** For data going into the kernel through the ioctl argument */
 #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3)     \
        if ( copy_from_user(&arg1, arg2, arg3) )        \
index 01cf482d2d00f12f8291cf76e650d4d65b157536..31cdde83713b4e44c576424edcafb113b7b9652d 100644 (file)
        {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
        {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
        {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
index 35540cfb43dd0fecf5d3b8fac30cbea2236796ff..b5c5b9fa84c3cd55bf7e0c8343fe6e6dc15771c3 100644 (file)
@@ -157,7 +157,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
  * \param address access address.
  * \return pointer to the page structure.
  *
- * Get the the mapping, find the real physical page to map, get the page, and
+ * Get the mapping, find the real physical page to map, get the page, and
  * return it.
  */
 static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
index db5a60450e689c58f8df6c0ee6800bb8f4f78c0b..1014602c43a71910e4f7eba390e123c47670c3f2 100644 (file)
@@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
        if (dev_priv->is_pci) {
 #endif
                dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+               dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
                dev_priv->gart_info.addr = NULL;
                dev_priv->gart_info.bus_addr = 0;
-               dev_priv->gart_info.is_pcie = 0;
+               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
                if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
                        DRM_ERROR("failed to init PCI GART!\n");
                        dev->dev_private = (void *)dev_priv;
index f1efb49de8dfb289a880c1992015a79e6434451c..9086835686dc9a59ce96141507858c6c8163e5db 100644 (file)
@@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
 
 #define R128_PERFORMANCE_BOXES         0
 
+#define R128_PCIGART_TABLE_SIZE         32768
+
 #define R128_READ(reg)         DRM_READ32(  dev_priv->mmio, (reg) )
 #define R128_WRITE(reg,val)    DRM_WRITE32( dev_priv->mmio, (reg), (val) )
 #define R128_READ8(reg)                DRM_READ8(   dev_priv->mmio, (reg) )
index a881f96c983efbb2fc5ecc8e1f34f152044c64db..ecda760ae8c0596af1c04837768c5917cfd3548f 100644 (file)
@@ -293,7 +293,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
 #       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
 #       define R300_PVS_CNTL_1_POS_END_SHIFT         10
 #       define R300_PVS_CNTL_1_PROGRAM_END_SHIFT     20
-/* Addresses are relative the the vertex program parameters area. */
+/* Addresses are relative to the vertex program parameters area. */
 #define R300_VAP_PVS_CNTL_2                 0x22D4
 #       define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
 #       define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT  16
index c1850ecac302cdbb3ae0089ff778a14befadc0dc..68338389d836b244258e9db82406f8cb4dc5936b 100644 (file)
@@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
        return RADEON_READ(RADEON_PCIE_DATA);
 }
 
+static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f);
+       ret = RADEON_READ(RADEON_IGPGART_DATA);
+       RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f);
+       return ret;
+}
+
 #if RADEON_FIFO_DEBUG
 static void radeon_status(drm_radeon_private_t * dev_priv)
 {
@@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
        }
 }
 
-/* Enable or disable PCI-E GART on the chip */
+/* Enable or disable IGP GART on the chip */
+static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
+{
+       u32 temp, tmp;
+
+       tmp = RADEON_READ(RADEON_AIC_CNTL);
+       if (on) {
+               DRM_DEBUG("programming igpgart %08X %08lX %08X\n",
+                        dev_priv->gart_vm_start,
+                        (long)dev_priv->gart_info.bus_addr,
+                        dev_priv->gart_size);
+
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR,
+                                    dev_priv->gart_info.bus_addr);
+
+               temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp);
+
+               RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
+               dev_priv->gart_size = 32*1024*1024;
+               RADEON_WRITE(RADEON_MC_AGP_LOCATION,
+                            (((dev_priv->gart_vm_start - 1 +
+                              dev_priv->gart_size) & 0xffff0000) |
+                            (dev_priv->gart_vm_start >> 16)));
+
+               temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp);
+
+               RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1);
+               RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
+               RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0);
+       }
+}
+
 static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
@@ -1302,6 +1348,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp;
 
+       if (dev_priv->flags & RADEON_IS_IGPGART) {
+               radeon_set_igpgart(dev_priv, on);
+               return;
+       }
+
        if (dev_priv->flags & RADEON_IS_PCIE) {
                radeon_set_pciegart(dev_priv, on);
                return;
@@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
 #endif
        {
                /* if we have an offset set from userspace */
-               if (dev_priv->pcigart_offset) {
+               if (dev_priv->pcigart_offset_set) {
                        dev_priv->gart_info.bus_addr =
                            dev_priv->pcigart_offset + dev_priv->fb_location;
                        dev_priv->gart_info.mapping.offset =
                            dev_priv->gart_info.bus_addr;
                        dev_priv->gart_info.mapping.size =
-                           RADEON_PCIGART_TABLE_SIZE;
+                           dev_priv->gart_info.table_size;
 
                        drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
                        dev_priv->gart_info.addr =
                            dev_priv->gart_info.mapping.handle;
 
-                       dev_priv->gart_info.is_pcie =
-                           !!(dev_priv->flags & RADEON_IS_PCIE);
+                       if (dev_priv->flags & RADEON_IS_PCIE)
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
+                       else
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
                        dev_priv->gart_info.gart_table_location =
                            DRM_ATI_GART_FB;
 
@@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                                  dev_priv->gart_info.addr,
                                  dev_priv->pcigart_offset);
                } else {
+                       if (dev_priv->flags & RADEON_IS_IGPGART)
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
+                       else
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
                        dev_priv->gart_info.gart_table_location =
                            DRM_ATI_GART_MAIN;
                        dev_priv->gart_info.addr = NULL;
@@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
                if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
                {
                        drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
-                       dev_priv->gart_info.addr = NULL;
+                       dev_priv->gart_info.addr = 0;
                }
        }
        /* only clear to the start of flags */
@@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev)
        drm_local_map_t *map;
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
+       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+
        ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
                         drm_get_resource_len(dev, 2), _DRM_REGISTERS,
                         _DRM_READ_ONLY, &dev_priv->mmio);
index 8d6350dd53609407b3182a51b50b2a97ff5bef68..66c4b6fed04f092a1f20dfacb09374128b49a555 100644 (file)
@@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam {
 #define RADEON_SETPARAM_SWITCH_TILING  2       /* enable/disable color tiling */
 #define RADEON_SETPARAM_PCIGART_LOCATION 3     /* PCI Gart Location */
 #define RADEON_SETPARAM_NEW_MEMMAP 4           /* Use new memory map */
+#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
 
 /* 1.14: Clients can allocate/free a surface
  */
index 8b105f1460a72a9ac492be62bfe27f63155301fc..54f49ef4bef084b8ae816a301596b8833c58e961 100644 (file)
  * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
  * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
  *       new packet type)
+ * 1.26- Add support for variable size PCI(E) gart aperture
+ * 1.27- Add support for IGP GART
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           25
+#define DRIVER_MINOR           27
 #define DRIVER_PATCHLEVEL      0
 
 /*
@@ -143,6 +145,7 @@ enum radeon_chip_flags {
        RADEON_IS_PCIE = 0x00200000UL,
        RADEON_NEW_MEMMAP = 0x00400000UL,
        RADEON_IS_PCI = 0x00800000UL,
+       RADEON_IS_IGPGART = 0x01000000UL,
 };
 
 #define GET_RING_HEAD(dev_priv)        (dev_priv->writeback_works ? \
@@ -240,7 +243,6 @@ typedef struct drm_radeon_private {
 
        int do_boxes;
        int page_flipping;
-       int current_page;
 
        u32 color_fmt;
        unsigned int front_offset;
@@ -280,6 +282,7 @@ typedef struct drm_radeon_private {
        struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
 
        unsigned long pcigart_offset;
+       unsigned int pcigart_offset_set;
        drm_ati_pcigart_info gart_info;
 
        u32 scratch_ages[5];
@@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #define RADEON_PCIE_TX_GART_END_LO     0x16
 #define RADEON_PCIE_TX_GART_END_HI     0x17
 
+#define RADEON_IGPGART_INDEX            0x168
+#define RADEON_IGPGART_DATA             0x16c
+#define RADEON_IGPGART_UNK_18           0x18
+#define RADEON_IGPGART_CTRL             0x2b
+#define RADEON_IGPGART_BASE_ADDR        0x2c
+#define RADEON_IGPGART_FLUSH            0x2e
+#define RADEON_IGPGART_ENABLE           0x38
+#define RADEON_IGPGART_UNK_39           0x39
+
 #define RADEON_MPP_TB_CONFIG           0x01c0
 #define RADEON_MEM_CNTL                        0x0140
 #define RADEON_MEM_SDRAM_MODE_REG      0x0158
@@ -964,6 +976,14 @@ do {                                                                       \
        RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );                  \
 } while (0)
 
+#define RADEON_WRITE_IGPGART( addr, val )                              \
+do {                                                                   \
+       RADEON_WRITE( RADEON_IGPGART_INDEX,                             \
+                       ((addr) & 0x7f) | (1 << 8));                    \
+       RADEON_WRITE( RADEON_IGPGART_DATA, (val) );                     \
+       RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f );                     \
+} while (0)
+
 #define RADEON_WRITE_PCIE( addr, val )                                 \
 do {                                                                   \
        RADEON_WRITE8( RADEON_PCIE_INDEX,                               \
index 938eccb78cc05211d6d0ac41ad9ce11fbe8e890d..98c5f1d3a8e7282ba07e528ab1d96e8c3bd473a8 100644 (file)
@@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
                 RADEON_GMC_SRC_DATATYPE_COLOR |
                 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
 
-       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
                OUT_RING(dev_priv->front_pitch_offset);
        } else {
                OUT_RING(dev_priv->back_pitch_offset);
@@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
 
        dev_priv->stats.clears++;
 
-       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
                unsigned int tmp = flags;
 
                flags &= ~(RADEON_FRONT | RADEON_BACK);
@@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
                /* Make this work even if front & back are flipped:
                 */
                OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
-               if (dev_priv->current_page == 0) {
+               if (dev_priv->sarea_priv->pfCurrentPage == 0) {
                        OUT_RING(dev_priv->back_pitch_offset);
                        OUT_RING(dev_priv->front_pitch_offset);
                } else {
@@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
-       int offset = (dev_priv->current_page == 1)
+       int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
            ? dev_priv->front_offset : dev_priv->back_offset;
        RING_LOCALS;
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+       DRM_DEBUG("%s: pfCurrentPage=%d\n",
                  __FUNCTION__,
-                 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+                 dev_priv->sarea_priv->pfCurrentPage);
 
        /* Do some trivial performance monitoring...
         */
@@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
         * performing the swapbuffer ioctl.
         */
        dev_priv->sarea_priv->last_frame++;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
-           1 - dev_priv->current_page;
+       dev_priv->sarea_priv->pfCurrentPage =
+               1 - dev_priv->sarea_priv->pfCurrentPage;
 
        BEGIN_RING(2);
 
@@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
        ADVANCE_RING();
 
        dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
 
-       return 0;
-}
-
-/* Called whenever a client dies, from drm_release.
- * NOTE:  Lock isn't necessarily held when this is called!
- */
-static int radeon_do_cleanup_pageflip(drm_device_t * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       if (dev_priv->current_page != 0)
-               radeon_cp_dispatch_flip(dev);
+       if (dev_priv->sarea_priv->pfCurrentPage != 1)
+               dev_priv->sarea_priv->pfCurrentPage = 0;
 
-       dev_priv->page_flipping = 0;
        return 0;
 }
 
@@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
                break;
        case RADEON_SETPARAM_PCIGART_LOCATION:
                dev_priv->pcigart_offset = sp.value;
+               dev_priv->pcigart_offset_set = 1;
                break;
        case RADEON_SETPARAM_NEW_MEMMAP:
                dev_priv->new_memmap = sp.value;
                break;
+       case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
+               dev_priv->gart_info.table_size = sp.value;
+               if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
+                       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+               break;
        default:
                DRM_DEBUG("Invalid parameter %d\n", sp.param);
                return DRM_ERR(EINVAL);
@@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
 {
        if (dev->dev_private) {
                drm_radeon_private_t *dev_priv = dev->dev_private;
-               if (dev_priv->page_flipping) {
-                       radeon_do_cleanup_pageflip(dev);
-               }
+               dev_priv->page_flipping = 0;
                radeon_mem_release(filp, dev_priv->gart_heap);
                radeon_mem_release(filp, dev_priv->fb_heap);
                radeon_surfaces_release(filp, dev_priv);
@@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
 
 void radeon_driver_lastclose(drm_device_t * dev)
 {
+       if (dev->dev_private) {
+               drm_radeon_private_t *dev_priv = dev->dev_private;
+
+               if (dev_priv->sarea_priv &&
+                   dev_priv->sarea_priv->pfCurrentPage != 0)
+                       radeon_cp_dispatch_flip(dev);
+       }
+
        radeon_do_release(dev);
 }
 
index c0539c6299cf422aea627e0b170fe7b007b4beac..13a9c5ca4593546f5eeb504158bf6da9221b51f3 100644 (file)
@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
                break;
        case VIA_DMA_INITIALIZED:
                retcode = (dev_priv->ring.virtual_start != NULL) ?
-                   0 : DRM_ERR(EFAULT);
+                       0 : DRM_ERR(EFAULT);
                break;
        default:
                retcode = DRM_ERR(EINVAL);
@@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
 {
        int paused, count;
        volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+       uint32_t reader,ptr;
 
+       paused = 0;
        via_flush_write_combine();
-       while (!*(via_get_dma(dev_priv) - 1)) ;
-       *dev_priv->last_pause_ptr = pause_addr_lo;
+       (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
+       *paused_at = pause_addr_lo;
        via_flush_write_combine();
-
-       /*
-        * The below statement is inserted to really force the flush.
-        * Not sure it is needed.
-        */
-
-       while (!*dev_priv->last_pause_ptr) ;
+       (void) *paused_at;
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
        dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
-       while (!*dev_priv->last_pause_ptr) ;
 
-       paused = 0;
-       count = 20;
-
-       while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
-       if ((count <= 8) && (count >= 0)) {
-               uint32_t rgtr, ptr;
-               rgtr = *(dev_priv->hw_addr_ptr);
-               ptr = ((volatile char *)dev_priv->last_pause_ptr -
-                     dev_priv->dma_ptr) + dev_priv->dma_offset +
-                     (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
-               if (rgtr <= ptr) {
-                       DRM_ERROR
-                           ("Command regulator\npaused at count %d, address %x, "
-                            "while current pause address is %x.\n"
-                            "Please mail this message to "
-                            "<unichrome-devel@lists.sourceforge.net>\n", count,
-                            rgtr, ptr);
-               }
+       if ((ptr - reader) <= dev_priv->dma_diff ) {
+               count = 10000000;
+               while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
        }
 
        if (paused && !no_pci_fire) {
-               uint32_t rgtr, ptr;
-               uint32_t ptr_low;
+               reader = *(dev_priv->hw_addr_ptr);
+               if ((ptr - reader) == dev_priv->dma_diff) {
 
-               count = 1000000;
-               while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
-                      && count--) ;
+                       /*
+                        * There is a concern that these writes may stall the PCI bus
+                        * if the GPU is not idle. However, idling the GPU first
+                        * doesn't make a difference.
+                        */
 
-               rgtr = *(dev_priv->hw_addr_ptr);
-               ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
-                   dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-               ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
-                   ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
-               if (rgtr <= ptr && rgtr >= ptr_low) {
                        VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
                        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
                        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
@@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
 static int via_wait_idle(drm_via_private_t * dev_priv)
 {
        int count = 10000000;
+
+       while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
+
        while (count-- && (VIA_READ(VIA_REG_STATUS) &
                           (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
                            VIA_3D_ENG_BUSY))) ;
@@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
        uint32_t end_addr, end_addr_lo;
        uint32_t command;
        uint32_t agp_base;
+       uint32_t ptr;
+       uint32_t reader;
+       int count;
 
        dev_priv->dma_low = 0;
 
@@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
                          &pause_addr_hi, &pause_addr_lo, 1) - 1;
 
        via_flush_write_combine();
-       while (!*dev_priv->last_pause_ptr) ;
+       (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
 
        VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
        VIA_WRITE(VIA_REG_TRANSPACE, command);
@@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
        DRM_WRITEMEMORYBARRIER();
        VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
        VIA_READ(VIA_REG_TRANSPACE);
+
+       dev_priv->dma_diff = 0;
+
+       count = 10000000;
+       while (!(VIA_READ(0x41c) & 0x80000000) && count--);
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       /*
+        * This is the difference between where we tell the
+        * command reader to pause and where it actually pauses.
+        * This differs between hw implementation so we need to
+        * detect it.
+        */
+
+       dev_priv->dma_diff = ptr - reader;
 }
 
 static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
@@ -592,7 +594,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
        uint32_t pause_addr_lo, pause_addr_hi;
        uint32_t jump_addr_lo, jump_addr_hi;
        volatile uint32_t *last_pause_ptr;
-       uint32_t dma_low_save1, dma_low_save2;
 
        agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
        via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
@@ -619,31 +620,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
                      &pause_addr_lo, 0);
 
        *last_pause_ptr = pause_addr_lo;
-       dma_low_save1 = dev_priv->dma_low;
-
-       /*
-        * Now, set a trap that will pause the regulator if it tries to rerun the old
-        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
-        * and reissues the jump command over PCI, while the regulator has already taken the jump
-        * and actually paused at the current buffer end).
-        * There appears to be no other way to detect this condition, since the hw_addr_pointer
-        * does not seem to get updated immediately when a jump occurs.
-        */
 
-       last_pause_ptr =
-           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                         &pause_addr_lo, 0) - 1;
-       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                     &pause_addr_lo, 0);
-       *last_pause_ptr = pause_addr_lo;
-
-       dma_low_save2 = dev_priv->dma_low;
-       dev_priv->dma_low = dma_low_save1;
-       via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
-       dev_priv->dma_low = dma_low_save2;
-       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+       via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
 }
 
+
 static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
 {
        via_cmdbuf_jump(dev_priv);
index 8b8778d4a423e805ee85164dc60b47e0dc007c6d..b46ca8e6306de4dcc176a04fec81dbf399b3f4cd 100644 (file)
 
 #define DRIVER_NAME            "via"
 #define DRIVER_DESC            "VIA Unichrome / Pro"
-#define DRIVER_DATE            "20061227"
+#define DRIVER_DATE            "20070202"
 
 #define DRIVER_MAJOR           2
 #define DRIVER_MINOR           11
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_PATCHLEVEL      1
 
 #include "via_verifier.h"
 
@@ -93,6 +93,7 @@ typedef struct drm_via_private {
        unsigned long vram_offset;
        unsigned long agp_offset;
        drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+       uint32_t dma_diff;
 } drm_via_private_t;
 
 enum via_family {
index 3d7efc26aad61338818a1416ff4d344ad4227a76..334ad5bbe6b62a244eed91b9731d121244ea4780 100644 (file)
@@ -4,7 +4,6 @@
  */
 #include <linux/module.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/capability.h>
index db984e481d4ca42908fffee5fb426528d119e82b..9b8278e1f4f85ba0363ef0e65f7b41d04e84f0a6 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 
 #include <asm/atarihw.h>
index d8dbdb9162329c62bcb8821547cb70c2c94102ee..abde6ddefe696e7e0af352e918085c68a83f4d89 100644 (file)
@@ -62,7 +62,6 @@
 #include <linux/init.h>                /* for __init, module_{init,exit} */
 #include <linux/poll.h>                /* for POLLIN, etc. */
 #include <linux/dtlk.h>                /* local header file for DoubleTalk values */
-#include <linux/smp_lock.h>
 
 #ifdef TRACING
 #define TRACE_TEXT(str) printk(str);
@@ -325,16 +324,22 @@ static int dtlk_release(struct inode *inode, struct file *file)
 
 static int __init dtlk_init(void)
 {
+       int err;
+
        dtlk_port_lpc = 0;
        dtlk_port_tts = 0;
        dtlk_busy = 0;
        dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);
-       if (dtlk_major == 0) {
+       if (dtlk_major < 0) {
                printk(KERN_ERR "DoubleTalk PC - cannot register device\n");
-               return 0;
+               return dtlk_major;
+       }
+       err = dtlk_dev_probe();
+       if (err) {
+               unregister_chrdev(dtlk_major, "dtlk");
+               return err;
        }
-       if (dtlk_dev_probe() == 0)
-               printk(", MAJOR %d\n", dtlk_major);
+       printk(", MAJOR %d\n", dtlk_major);
 
        init_waitqueue_head(&dtlk_process_list);
 
index 77f58ed6d59af01b9688c6ce9851ffc5a7ce80cb..020011495d9193f2710971db586b1d1304e9a881 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/kbd_kern.h>
-#include <linux/smp_lock.h>
 #include <linux/bitops.h>
 
 #include <asm/keyboard.h>
index de5be30484ad3d9f8b91b8f0699ca39c97647d99..c6c56fb8ba5098f341692d16c698e39a383abda1 100644 (file)
@@ -949,7 +949,7 @@ static int block_til_ready(struct tty_struct *tty,
 
        } /* End forever while  */
 
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&ch->open_wait, &wait);
        if (!tty_hung_up_p(filp))
                ch->count++;
index 23b25ada65ea3c5b02405b1cf955afd17051d5f1..9e1fc02967ffe7c73739dc5634d2e11f73998e50 100644 (file)
@@ -12,7 +12,7 @@
  *
  *     This driver allows use of the real time clock (built into
  *     nearly all computers) from user space. It exports the /dev/rtc
- *     interface supporting various ioctl() and also the /proc/dev/rtc
+ *     interface supporting various ioctl() and also the /proc/driver/rtc
  *     pseudo-file for status information.
  *
  *     The ioctls can be used to set the interrupt behaviour where
@@ -207,7 +207,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
                        sizeof(unsigned long);
        }
  out:
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&gen_rtc_wait, &wait);
 
        return retval;
@@ -377,7 +377,7 @@ static int gen_rtc_release(struct inode *inode, struct file *file)
 #ifdef CONFIG_PROC_FS
 
 /*
- *     Info exported via "/proc/rtc".
+ *     Info exported via "/proc/driver/rtc".
  */
 
 static int gen_rtc_proc_output(char *buf)
index ae76a9ffe89f56481dc0cb851e3e0687b66b8694..f0e7263dfcde0f5a3ba3cf56bb73637893314d84 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
index 0f9ed7b46a6df81bb1332b1a048a2c475028cb00..322bc5f7d86b791dd8350642c1b390fe6b54784c 100644 (file)
@@ -111,7 +111,7 @@ static int last_hvc = -1;
  * lock held.  If successful, this function increments the kobject reference
  * count against the target hvc_struct so it should be released when finished.
  */
-struct hvc_struct *hvc_get_by_index(int index)
+static struct hvc_struct *hvc_get_by_index(int index)
 {
        struct hvc_struct *hp;
        unsigned long flags;
@@ -150,7 +150,8 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
  * hvc_console_setup() finds adapters.
  */
 
-void hvc_console_print(struct console *co, const char *b, unsigned count)
+static void hvc_console_print(struct console *co, const char *b,
+                             unsigned count)
 {
        char c[N_OUTBUF] __ALIGNED__;
        unsigned i = 0, n = 0;
@@ -208,7 +209,7 @@ static int __init hvc_console_setup(struct console *co, char *options)
        return 0;
 }
 
-struct console hvc_con_driver = {
+static struct console hvc_con_driver = {
        .name           = "hvc",
        .write          = hvc_console_print,
        .device         = hvc_console_device,
@@ -278,7 +279,6 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
 
        return 0;
 }
-EXPORT_SYMBOL(hvc_instantiate);
 
 /* Wake the sleeping khvcd */
 static void hvc_kick(void)
@@ -792,7 +792,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
 
        return hp;
 }
-EXPORT_SYMBOL(hvc_alloc);
 
 int __devexit hvc_remove(struct hvc_struct *hp)
 {
@@ -828,11 +827,10 @@ int __devexit hvc_remove(struct hvc_struct *hp)
                tty_hangup(tty);
        return 0;
 }
-EXPORT_SYMBOL(hvc_remove);
 
 /* Driver initialization.  Follow console initialization.  This is where the TTY
  * interfaces start to become available. */
-int __init hvc_init(void)
+static int __init hvc_init(void)
 {
        struct tty_driver *drv;
 
index ec420fe8a9089f5a2f4be1201b6dbd5d7307fb8c..b37f1d5a5be6e19e9604e80b36988573f500d58f 100644 (file)
@@ -579,7 +579,7 @@ static int hvc_find_vtys(void)
                if (!vtermno)
                        continue;
 
-               if (!device_is_compatible(vty, "IBM,iSeries-vty"))
+               if (!of_device_is_compatible(vty, "IBM,iSeries-vty"))
                        continue;
 
                if (num_found == 0)
index 94a542e20efb02eb07beb1266567e444b396219f..79711aa4b41d4ae85de49cf8bddad9a0c50ded18 100644 (file)
@@ -157,7 +157,7 @@ static int hvc_find_vtys(void)
                if (!vtermno)
                        continue;
 
-               if (device_is_compatible(vty, "hvterm1")) {
+               if (of_device_is_compatible(vty, "hvterm1")) {
                        hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
                        ++num_found;
                }
index 5f3acd8e64b86d9e6ac8e685b61329322aada8c6..7cda04b335343aeb52e94b7007c38a3e3fae0c35 100644 (file)
@@ -91,3 +91,17 @@ config HW_RANDOM_OMAP
          module will be called omap-rng.
 
          If unsure, say Y.
+
+config HW_RANDOM_PASEMI
+       tristate "PA Semi HW Random Number Generator support"
+       depends on HW_RANDOM && PPC_PASEMI
+       default HW_RANDOM
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on PA6T-1682M processor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pasemi-rng.
+
+         If unsure, say Y.
+
index c41fa19454e3910dfce0a1bbe4d7d33eddca77fe..c8b7300e2fb183f6ed6c6d1eb4f6ccfa358fb6bc 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
 obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
 obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
+obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
index cc1046e6ee02d55a68bfff65a304430a20e8cb47..4ae9811d1a6c20a2f8f6a61b5affdaf0a5b15aa5 100644 (file)
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/module.h>
+#include <linux/hw_random.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/hw_random.h>
+#include <linux/stop_machine.h>
 #include <asm/io.h>
 
 
@@ -217,30 +218,117 @@ static struct hwrng intel_rng = {
        .data_read      = intel_rng_data_read,
 };
 
+struct intel_rng_hw {
+       struct pci_dev *dev;
+       void __iomem *mem;
+       u8 bios_cntl_off;
+       u8 bios_cntl_val;
+       u8 fwh_dec_en1_off;
+       u8 fwh_dec_en1_val;
+};
 
-#ifdef CONFIG_SMP
-static char __initdata waitflag;
+static int __init intel_rng_hw_init(void *_intel_rng_hw)
+{
+       struct intel_rng_hw *intel_rng_hw = _intel_rng_hw;
+       u8 mfc, dvc;
+
+       /* interrupts disabled in stop_machine_run call */
+
+       if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK))
+               pci_write_config_byte(intel_rng_hw->dev,
+                                     intel_rng_hw->fwh_dec_en1_off,
+                                     intel_rng_hw->fwh_dec_en1_val |
+                                     FWH_F8_EN_MASK);
+       if (!(intel_rng_hw->bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
+               pci_write_config_byte(intel_rng_hw->dev,
+                                     intel_rng_hw->bios_cntl_off,
+                                     intel_rng_hw->bios_cntl_val |
+                                     BIOS_CNTL_WRITE_ENABLE_MASK);
+
+       writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem);
+       writeb(INTEL_FWH_READ_ID_CMD, intel_rng_hw->mem);
+       mfc = readb(intel_rng_hw->mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
+       dvc = readb(intel_rng_hw->mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
+       writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem);
+
+       if (!(intel_rng_hw->bios_cntl_val &
+             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+               pci_write_config_byte(intel_rng_hw->dev,
+                                     intel_rng_hw->bios_cntl_off,
+                                     intel_rng_hw->bios_cntl_val);
+       if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK))
+               pci_write_config_byte(intel_rng_hw->dev,
+                                     intel_rng_hw->fwh_dec_en1_off,
+                                     intel_rng_hw->fwh_dec_en1_val);
 
-static void __init intel_init_wait(void *unused)
+       if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
+           (dvc != INTEL_FWH_DEVICE_CODE_8M &&
+            dvc != INTEL_FWH_DEVICE_CODE_4M)) {
+               printk(KERN_ERR PFX "FWH not detected\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw,
+                                       struct pci_dev *dev)
 {
-       while (waitflag)
-               cpu_relax();
+       intel_rng_hw->bios_cntl_val = 0xff;
+       intel_rng_hw->fwh_dec_en1_val = 0xff;
+       intel_rng_hw->dev = dev;
+
+       /* Check for Intel 82802 */
+       if (dev->device < 0x2640) {
+               intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
+               intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_OLD;
+       } else {
+               intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
+               intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_NEW;
+       }
+
+       pci_read_config_byte(dev, intel_rng_hw->fwh_dec_en1_off,
+                            &intel_rng_hw->fwh_dec_en1_val);
+       pci_read_config_byte(dev, intel_rng_hw->bios_cntl_off,
+                            &intel_rng_hw->bios_cntl_val);
+
+       if ((intel_rng_hw->bios_cntl_val &
+            (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
+           == BIOS_CNTL_LOCK_ENABLE_MASK) {
+               static __initdata /*const*/ char warning[] =
+                       KERN_WARNING PFX "Firmware space is locked read-only. "
+                       KERN_WARNING PFX "If you can't or\n don't want to "
+                       KERN_WARNING PFX "disable this in firmware setup, and "
+                       KERN_WARNING PFX "if\n you are certain that your "
+                       KERN_WARNING PFX "system has a functional\n RNG, try"
+                       KERN_WARNING PFX "using the 'no_fwh_detect' option.\n";
+
+               if (no_fwh_detect)
+                       return -ENODEV;
+               printk(warning);
+               return -EBUSY;
+       }
+
+       intel_rng_hw->mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
+       if (intel_rng_hw->mem == NULL)
+               return -EBUSY;
+
+       return 0;
 }
-#endif
+
 
 static int __init mod_init(void)
 {
        int err = -ENODEV;
-       unsigned i;
+       int i;
        struct pci_dev *dev = NULL;
-       void __iomem *mem;
-       unsigned long flags;
-       u8 bios_cntl_off, fwh_dec_en1_off;
-       u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff;
-       u8 hw_status, mfc, dvc;
+       void __iomem *mem = mem;
+       u8 hw_status;
+       struct intel_rng_hw *intel_rng_hw;
 
        for (i = 0; !dev && pci_tbl[i].vendor; ++i)
-               dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
+               dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device,
+                                    NULL);
 
        if (!dev)
                goto out; /* Device not found. */
@@ -250,39 +338,18 @@ static int __init mod_init(void)
                goto fwh_done;
        }
 
-       /* Check for Intel 82802 */
-       if (dev->device < 0x2640) {
-               fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
-               bios_cntl_off = BIOS_CNTL_REG_OLD;
-       } else {
-               fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
-               bios_cntl_off = BIOS_CNTL_REG_NEW;
-       }
-
-       pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
-       pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
-
-       if ((bios_cntl_val &
-            (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
-           == BIOS_CNTL_LOCK_ENABLE_MASK) {
-               static __initdata /*const*/ char warning[] =
-                       KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
-                       KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
-                       KERN_WARNING PFX "you are certain that your system has a functional\n"
-                       KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
-
+       intel_rng_hw = kmalloc(sizeof(*intel_rng_hw), GFP_KERNEL);
+       if (!intel_rng_hw) {
                pci_dev_put(dev);
-               if (no_fwh_detect)
-                       goto fwh_done;
-               printk(warning);
-               err = -EBUSY;
                goto out;
        }
 
-       mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
-       if (mem == NULL) {
+       err = intel_init_hw_struct(intel_rng_hw, dev);
+       if (err) {
                pci_dev_put(dev);
-               err = -EBUSY;
+               kfree(intel_rng_hw);
+               if (err == -ENODEV)
+                       goto fwh_done;
                goto out;
        }
 
@@ -290,59 +357,18 @@ static int __init mod_init(void)
         * Since the BIOS code/data is going to disappear from its normal
         * location with the Read ID command, all activity on the system
         * must be stopped until the state is back to normal.
+        *
+        * Use stop_machine_run because IPIs can be blocked by disabling
+        * interrupts.
         */
-#ifdef CONFIG_SMP
-       set_mb(waitflag, 1);
-       if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) {
-               set_mb(waitflag, 0);
-               pci_dev_put(dev);
-               printk(KERN_ERR PFX "cannot run on all processors\n");
-               err = -EAGAIN;
-               goto err_unmap;
-       }
-#endif
-       local_irq_save(flags);
-
-       if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
-               pci_write_config_byte(dev,
-                                     fwh_dec_en1_off,
-                                     fwh_dec_en1_val | FWH_F8_EN_MASK);
-       if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
-               pci_write_config_byte(dev,
-                                     bios_cntl_off,
-                                     bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
-
-       writeb(INTEL_FWH_RESET_CMD, mem);
-       writeb(INTEL_FWH_READ_ID_CMD, mem);
-       mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
-       dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
-       writeb(INTEL_FWH_RESET_CMD, mem);
-
-       if (!(bios_cntl_val &
-             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
-               pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val);
-       if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
-               pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val);
-
-       local_irq_restore(flags);
-#ifdef CONFIG_SMP
-       /* Tell other CPUs to resume. */
-       set_mb(waitflag, 0);
-#endif
-
-       iounmap(mem);
+       err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS);
        pci_dev_put(dev);
-
-       if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
-           (dvc != INTEL_FWH_DEVICE_CODE_8M &&
-            dvc != INTEL_FWH_DEVICE_CODE_4M)) {
-               printk(KERN_ERR PFX "FWH not detected\n");
-               err = -ENODEV;
+       iounmap(intel_rng_hw->mem);
+       kfree(intel_rng_hw);
+       if (err)
                goto out;
-       }
 
 fwh_done:
-
        err = -ENOMEM;
        mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
        if (!mem)
@@ -352,22 +378,21 @@ fwh_done:
        /* Check for Random Number Generator */
        err = -ENODEV;
        hw_status = hwstatus_get(mem);
-       if ((hw_status & INTEL_RNG_PRESENT) == 0)
-               goto err_unmap;
+       if ((hw_status & INTEL_RNG_PRESENT) == 0) {
+               iounmap(mem);
+               goto out;
+       }
 
        printk(KERN_INFO "Intel 82802 RNG detected\n");
        err = hwrng_register(&intel_rng);
        if (err) {
                printk(KERN_ERR PFX "RNG registering failed (%d)\n",
                       err);
-               goto err_unmap;
+               iounmap(mem);
        }
 out:
        return err;
 
-err_unmap:
-       iounmap(mem);
-       goto out;
 }
 
 static void __exit mod_exit(void)
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
new file mode 100644 (file)
index 0000000..fa6040b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Driver for the PWRficient onchip rng
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <asm/of_platform.h>
+#include <asm/io.h>
+
+#define SDCRNG_CTL_REG                 0x00
+#define   SDCRNG_CTL_FVLD_M            0x0000f000
+#define   SDCRNG_CTL_FVLD_S            12
+#define   SDCRNG_CTL_KSZ               0x00000800
+#define   SDCRNG_CTL_RSRC_CRG          0x00000010
+#define   SDCRNG_CTL_RSRC_RRG          0x00000000
+#define   SDCRNG_CTL_CE                        0x00000004
+#define   SDCRNG_CTL_RE                        0x00000002
+#define   SDCRNG_CTL_DR                        0x00000001
+#define   SDCRNG_CTL_SELECT_RRG_RNG    (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
+#define   SDCRNG_CTL_SELECT_CRG_RNG    (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
+#define SDCRNG_VAL_REG                 0x20
+
+#define MODULE_NAME "pasemi_rng"
+
+static int pasemi_rng_data_present(struct hwrng *rng)
+{
+       void __iomem *rng_regs = (void __iomem *)rng->priv;
+
+       return (in_le32(rng_regs + SDCRNG_CTL_REG)
+               & SDCRNG_CTL_FVLD_M) ? 1 : 0;
+}
+
+static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       void __iomem *rng_regs = (void __iomem *)rng->priv;
+       *data = in_le32(rng_regs + SDCRNG_VAL_REG);
+       return 4;
+}
+
+static int pasemi_rng_init(struct hwrng *rng)
+{
+       void __iomem *rng_regs = (void __iomem *)rng->priv;
+       u32 ctl;
+
+       ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ;
+       out_le32(rng_regs + SDCRNG_CTL_REG, ctl);
+       out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR);
+
+       return 0;
+}
+
+static void pasemi_rng_cleanup(struct hwrng *rng)
+{
+       void __iomem *rng_regs = (void __iomem *)rng->priv;
+       u32 ctl;
+
+       ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE;
+       out_le32(rng_regs + SDCRNG_CTL_REG,
+                in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl);
+}
+
+static struct hwrng pasemi_rng = {
+       .name           = MODULE_NAME,
+       .init           = pasemi_rng_init,
+       .cleanup        = pasemi_rng_cleanup,
+       .data_present   = pasemi_rng_data_present,
+       .data_read      = pasemi_rng_data_read,
+};
+
+static int __devinit rng_probe(struct of_device *ofdev,
+                              const struct of_device_id *match)
+{
+       void __iomem *rng_regs;
+       struct device_node *rng_np = ofdev->node;
+       struct resource res;
+       int err = 0;
+
+       err = of_address_to_resource(rng_np, 0, &res);
+       if (err)
+               return -ENODEV;
+
+       rng_regs = ioremap(res.start, 0x100);
+
+       if (!rng_regs)
+               return -ENOMEM;
+
+       pasemi_rng.priv = (unsigned long)rng_regs;
+
+       printk(KERN_INFO "Registering PA Semi RNG\n");
+
+       err = hwrng_register(&pasemi_rng);
+
+       if (err)
+               iounmap(rng_regs);
+
+       return err;
+}
+
+static int __devexit rng_remove(struct of_device *dev)
+{
+       void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
+
+       hwrng_unregister(&pasemi_rng);
+       iounmap(rng_regs);
+
+       return 0;
+}
+
+static struct of_device_id rng_match[] = {
+       {
+               .compatible      = "1682m-rng",
+       },
+       {},
+};
+
+static struct of_platform_driver rng_driver = {
+       .name           = "pasemi-rng",
+       .match_table    = rng_match,
+       .probe          = rng_probe,
+       .remove         = rng_remove,
+};
+
+static int __init rng_init(void)
+{
+       return of_register_platform_driver(&rng_driver);
+}
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+       of_unregister_platform_driver(&rng_driver);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
+MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor");
index 353d9f3cf8d786cda5ae06f29a25c3d63b099057..0289705967de3921b7834fefa38d5bb03aa55ae9 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/dmi.h>
+#include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
index a48da02aad2f3ae1480cb0df48b78ae4bcbb8e50..932264a657d0da57a0567f428d88d07e01445b5a 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 
 #include <asm/m48t35.h>
 #include <asm/sn/ioc3.h>
index e22146546adde92de6b01f15f98ebcf1ff02767c..6c5d15de331749520036df62d646901190435312 100644 (file)
@@ -9,6 +9,7 @@
  *         source@mvista.com
  *
  * Copyright 2002 MontaVista Software Inc.
+ * Copyright 2006 IBM Corp., Christian Krafft <krafft@de.ibm.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
 #include <linux/string.h>
 #include <linux/ctype.h>
 
+#ifdef CONFIG_PPC_OF
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#endif
+
 #define PFX "ipmi_si: "
 
 /* Measure times between events in the driver. */
 #define SI_SHORT_TIMEOUT_USEC  250 /* .25ms when the SM request a
                                        short timeout */
 
+/* Bit for BMC global enables. */
+#define IPMI_BMC_RCV_MSG_INTR     0x01
+#define IPMI_BMC_EVT_MSG_INTR     0x02
+#define IPMI_BMC_EVT_MSG_BUFF     0x04
+#define IPMI_BMC_SYS_LOG          0x08
+
 enum si_intf_state {
        SI_NORMAL,
        SI_GETTING_FLAGS,
@@ -84,7 +96,9 @@ enum si_intf_state {
        SI_CLEARING_FLAGS_THEN_SET_IRQ,
        SI_GETTING_MESSAGES,
        SI_ENABLE_INTERRUPTS1,
-       SI_ENABLE_INTERRUPTS2
+       SI_ENABLE_INTERRUPTS2,
+       SI_DISABLE_INTERRUPTS1,
+       SI_DISABLE_INTERRUPTS2
        /* FIXME - add watchdog stuff. */
 };
 
@@ -333,6 +347,17 @@ static void start_enable_irq(struct smi_info *smi_info)
        smi_info->si_state = SI_ENABLE_INTERRUPTS1;
 }
 
+static void start_disable_irq(struct smi_info *smi_info)
+{
+       unsigned char msg[2];
+
+       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
+       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
+
+       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+       smi_info->si_state = SI_DISABLE_INTERRUPTS1;
+}
+
 static void start_clear_flags(struct smi_info *smi_info)
 {
        unsigned char msg[3];
@@ -353,7 +378,7 @@ static void start_clear_flags(struct smi_info *smi_info)
 static inline void disable_si_irq(struct smi_info *smi_info)
 {
        if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
-               disable_irq_nosync(smi_info->irq);
+               start_disable_irq(smi_info);
                smi_info->interrupt_disabled = 1;
        }
 }
@@ -361,7 +386,7 @@ static inline void disable_si_irq(struct smi_info *smi_info)
 static inline void enable_si_irq(struct smi_info *smi_info)
 {
        if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
-               enable_irq(smi_info->irq);
+               start_enable_irq(smi_info);
                smi_info->interrupt_disabled = 0;
        }
 }
@@ -583,7 +608,9 @@ static void handle_transaction_done(struct smi_info *smi_info)
                } else {
                        msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
                        msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
-                       msg[2] = msg[3] | 1; /* enable msg queue int */
+                       msg[2] = (msg[3] |
+                                 IPMI_BMC_RCV_MSG_INTR |
+                                 IPMI_BMC_EVT_MSG_INTR);
                        smi_info->handlers->start_transaction(
                                smi_info->si_sm, msg, 3);
                        smi_info->si_state = SI_ENABLE_INTERRUPTS2;
@@ -605,6 +632,45 @@ static void handle_transaction_done(struct smi_info *smi_info)
                smi_info->si_state = SI_NORMAL;
                break;
        }
+
+       case SI_DISABLE_INTERRUPTS1:
+       {
+               unsigned char msg[4];
+
+               /* We got the flags from the SMI, now handle them. */
+               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
+               if (msg[2] != 0) {
+                       printk(KERN_WARNING
+                              "ipmi_si: Could not disable interrupts"
+                              ", failed get.\n");
+                       smi_info->si_state = SI_NORMAL;
+               } else {
+                       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
+                       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
+                       msg[2] = (msg[3] &
+                                 ~(IPMI_BMC_RCV_MSG_INTR |
+                                   IPMI_BMC_EVT_MSG_INTR));
+                       smi_info->handlers->start_transaction(
+                               smi_info->si_sm, msg, 3);
+                       smi_info->si_state = SI_DISABLE_INTERRUPTS2;
+               }
+               break;
+       }
+
+       case SI_DISABLE_INTERRUPTS2:
+       {
+               unsigned char msg[4];
+
+               /* We got the flags from the SMI, now handle them. */
+               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
+               if (msg[2] != 0) {
+                       printk(KERN_WARNING
+                              "ipmi_si: Could not disable interrupts"
+                              ", failed set.\n");
+               }
+               smi_info->si_state = SI_NORMAL;
+               break;
+       }
        }
 }
 
@@ -858,9 +924,6 @@ static void smi_timeout(unsigned long data)
        struct timeval    t;
 #endif
 
-       if (atomic_read(&smi_info->stop_operation))
-               return;
-
        spin_lock_irqsave(&(smi_info->si_lock), flags);
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
@@ -916,15 +979,11 @@ static irqreturn_t si_irq_handler(int irq, void *data)
        smi_info->interrupts++;
        spin_unlock(&smi_info->count_lock);
 
-       if (atomic_read(&smi_info->stop_operation))
-               goto out;
-
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
        printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
        smi_event_handler(smi_info, 0);
- out:
        spin_unlock_irqrestore(&(smi_info->si_lock), flags);
        return IRQ_HANDLED;
 }
@@ -1006,6 +1065,7 @@ static DEFINE_MUTEX(smi_infos_lock);
 static int smi_num; /* Used to sequence the SMIs */
 
 #define DEFAULT_REGSPACING     1
+#define DEFAULT_REGSIZE                1
 
 static int           si_trydefaults = 1;
 static char          *si_type[SI_MAX_PARMS];
@@ -1111,7 +1171,7 @@ static int std_irq_setup(struct smi_info *info)
        if (info->si_type == SI_BT) {
                rv = request_irq(info->irq,
                                 si_bt_irq_handler,
-                                IRQF_DISABLED,
+                                IRQF_SHARED | IRQF_DISABLED,
                                 DEVICE_NAME,
                                 info);
                if (!rv)
@@ -1121,7 +1181,7 @@ static int std_irq_setup(struct smi_info *info)
        } else
                rv = request_irq(info->irq,
                                 si_irq_handler,
-                                IRQF_DISABLED,
+                                IRQF_SHARED | IRQF_DISABLED,
                                 DEVICE_NAME,
                                 info);
        if (rv) {
@@ -1701,15 +1761,11 @@ static u32 ipmi_acpi_gpe(void *context)
        smi_info->interrupts++;
        spin_unlock(&smi_info->count_lock);
 
-       if (atomic_read(&smi_info->stop_operation))
-               goto out;
-
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
        printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
        smi_event_handler(smi_info, 0);
- out:
        spin_unlock_irqrestore(&(smi_info->si_lock), flags);
 
        return ACPI_INTERRUPT_HANDLED;
@@ -2133,12 +2189,15 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
                info->irq_setup = std_irq_setup;
 
        info->dev = &pdev->dev;
+       pci_set_drvdata(pdev, info);
 
        return try_smi_init(info);
 }
 
 static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
 {
+       struct smi_info *info = pci_get_drvdata(pdev);
+       cleanup_one_si(info);
 }
 
 #ifdef CONFIG_PM
@@ -2172,6 +2231,99 @@ static struct pci_driver ipmi_pci_driver = {
 #endif /* CONFIG_PCI */
 
 
+#ifdef CONFIG_PPC_OF
+static int __devinit ipmi_of_probe(struct of_device *dev,
+                        const struct of_device_id *match)
+{
+       struct smi_info *info;
+       struct resource resource;
+       const int *regsize, *regspacing, *regshift;
+       struct device_node *np = dev->node;
+       int ret;
+       int proplen;
+
+       dev_info(&dev->dev, PFX "probing via device tree\n");
+
+       ret = of_address_to_resource(np, 0, &resource);
+       if (ret) {
+               dev_warn(&dev->dev, PFX "invalid address from OF\n");
+               return ret;
+       }
+
+       regsize = get_property(np, "reg-size", &proplen);
+       if (regsize && proplen != 4) {
+               dev_warn(&dev->dev, PFX "invalid regsize from OF\n");
+               return -EINVAL;
+       }
+
+       regspacing = get_property(np, "reg-spacing", &proplen);
+       if (regspacing && proplen != 4) {
+               dev_warn(&dev->dev, PFX "invalid regspacing from OF\n");
+               return -EINVAL;
+       }
+
+       regshift = get_property(np, "reg-shift", &proplen);
+       if (regshift && proplen != 4) {
+               dev_warn(&dev->dev, PFX "invalid regshift from OF\n");
+               return -EINVAL;
+       }
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+       if (!info) {
+               dev_err(&dev->dev,
+                       PFX "could not allocate memory for OF probe\n");
+               return -ENOMEM;
+       }
+
+       info->si_type           = (enum si_type) match->data;
+       info->addr_source       = "device-tree";
+       info->io_setup          = mem_setup;
+       info->irq_setup         = std_irq_setup;
+
+       info->io.addr_type      = IPMI_MEM_ADDR_SPACE;
+       info->io.addr_data      = resource.start;
+
+       info->io.regsize        = regsize ? *regsize : DEFAULT_REGSIZE;
+       info->io.regspacing     = regspacing ? *regspacing : DEFAULT_REGSPACING;
+       info->io.regshift       = regshift ? *regshift : 0;
+
+       info->irq               = irq_of_parse_and_map(dev->node, 0);
+       info->dev               = &dev->dev;
+
+       dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n",
+               info->io.addr_data, info->io.regsize, info->io.regspacing,
+               info->irq);
+
+       dev->dev.driver_data = (void*) info;
+
+       return try_smi_init(info);
+}
+
+static int __devexit ipmi_of_remove(struct of_device *dev)
+{
+       cleanup_one_si(dev->dev.driver_data);
+       return 0;
+}
+
+static struct of_device_id ipmi_match[] =
+{
+       { .type = "ipmi", .compatible = "ipmi-kcs",  .data = (void *)(unsigned long) SI_KCS },
+       { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC },
+       { .type = "ipmi", .compatible = "ipmi-bt",   .data = (void *)(unsigned long) SI_BT },
+       {},
+};
+
+static struct of_platform_driver ipmi_of_platform_driver =
+{
+       .name           = "ipmi",
+       .match_table    = ipmi_match,
+       .probe          = ipmi_of_probe,
+       .remove         = __devexit_p(ipmi_of_remove),
+};
+#endif /* CONFIG_PPC_OF */
+
+
 static int try_get_dev_id(struct smi_info *smi_info)
 {
        unsigned char         msg[2];
@@ -2801,6 +2953,10 @@ static __devinit int init_ipmi_si(void)
        }
 #endif
 
+#ifdef CONFIG_PPC_OF
+       of_register_platform_driver(&ipmi_of_platform_driver);
+#endif
+
        if (si_trydefaults) {
                mutex_lock(&smi_infos_lock);
                if (list_empty(&smi_infos)) {
@@ -2838,28 +2994,33 @@ static void cleanup_one_si(struct smi_info *to_clean)
 
        list_del(&to_clean->link);
 
-       /* Tell the timer and interrupt handlers that we are shutting
-          down. */
-       spin_lock_irqsave(&(to_clean->si_lock), flags);
-       spin_lock(&(to_clean->msg_lock));
-
+       /* Tell the driver that we are shutting down. */
        atomic_inc(&to_clean->stop_operation);
 
-       if (to_clean->irq_cleanup)
-               to_clean->irq_cleanup(to_clean);
-
-       spin_unlock(&(to_clean->msg_lock));
-       spin_unlock_irqrestore(&(to_clean->si_lock), flags);
-
-       /* Wait until we know that we are out of any interrupt
-          handlers might have been running before we freed the
-          interrupt. */
-       synchronize_sched();
-
+       /* Make sure the timer and thread are stopped and will not run
+          again. */
        wait_for_timer_and_thread(to_clean);
 
-       /* Interrupts and timeouts are stopped, now make sure the
-          interface is in a clean state. */
+       /* Timeouts are stopped, now make sure the interrupts are off
+          for the device.  A little tricky with locks to make sure
+          there are no races. */
+       spin_lock_irqsave(&to_clean->si_lock, flags);
+       while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
+               spin_unlock_irqrestore(&to_clean->si_lock, flags);
+               poll(to_clean);
+               schedule_timeout_uninterruptible(1);
+               spin_lock_irqsave(&to_clean->si_lock, flags);
+       }
+       disable_si_irq(to_clean);
+       spin_unlock_irqrestore(&to_clean->si_lock, flags);
+       while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
+               poll(to_clean);
+               schedule_timeout_uninterruptible(1);
+       }
+
+       /* Clean up interrupts and make sure that everything is done. */
+       if (to_clean->irq_cleanup)
+               to_clean->irq_cleanup(to_clean);
        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                poll(to_clean);
                schedule_timeout_uninterruptible(1);
@@ -2898,6 +3059,10 @@ static __exit void cleanup_ipmi_si(void)
        pci_unregister_driver(&ipmi_pci_driver);
 #endif
 
+#ifdef CONFIG_PPC_OF
+       of_unregister_platform_driver(&ipmi_of_platform_driver);
+#endif
+
        mutex_lock(&smi_infos_lock);
        list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
                cleanup_one_si(e);
index 6b634e8d95191369649538f55ae9b666cc7acf73..147c12047cf3d83b6b345c4b8348f43e4ffc6a5d 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #include <linux/completion.h>
+#include <linux/kdebug.h>
 #include <linux/rwsem.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 #include <asm/atomic.h>
-#ifdef CONFIG_X86_LOCAL_APIC
-#include <asm/apic.h>
+
+#ifdef CONFIG_X86
+/* This is ugly, but I've determined that x86 is the only architecture
+   that can reasonably support the IPMI NMI watchdog timeout at this
+   time.  If another architecture adds this capability somehow, it
+   will have to be a somewhat different mechanism and I have no idea
+   how it will work.  So in the unlikely event that another
+   architecture supports this, we can figure out a good generic
+   mechanism for it at that time. */
+#define HAVE_DIE_NMI_POST
 #endif
 
 #define        PFX "IPMI Watchdog: "
@@ -317,6 +327,11 @@ static unsigned char ipmi_version_minor;
 /* If a pretimeout occurs, this is used to allow only one panic to happen. */
 static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
 
+#ifdef HAVE_DIE_NMI_POST
+static int testing_nmi;
+static int nmi_handler_registered;
+#endif
+
 static int ipmi_heartbeat(void);
 static void panic_halt_ipmi_heartbeat(void);
 
@@ -358,6 +373,10 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
        int                               hbnow = 0;
 
 
+       /* These can be cleared as we are setting the timeout. */
+       ipmi_start_timer_on_heartbeat = 0;
+       pretimeout_since_last_heartbeat = 0;
+
        data[0] = 0;
        WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
 
@@ -432,13 +451,12 @@ static int ipmi_set_timeout(int do_heartbeat)
 
        wait_for_completion(&set_timeout_wait);
 
+       mutex_unlock(&set_timeout_lock);
+
        if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
            || ((send_heartbeat_now)
                && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
-       {
                rv = ipmi_heartbeat();
-       }
-       mutex_unlock(&set_timeout_lock);
 
 out:
        return rv;
@@ -518,12 +536,10 @@ static int ipmi_heartbeat(void)
        int                               rv;
        struct ipmi_system_interface_addr addr;
 
-       if (ipmi_ignore_heartbeat) {
+       if (ipmi_ignore_heartbeat)
                return 0;
-       }
 
        if (ipmi_start_timer_on_heartbeat) {
-               ipmi_start_timer_on_heartbeat = 0;
                ipmi_watchdog_state = action_val;
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
        } else if (pretimeout_since_last_heartbeat) {
@@ -531,7 +547,6 @@ static int ipmi_heartbeat(void)
                   We don't want to set the action, though, we want to
                   leave that alone (thus it can't be combined with the
                   above operation. */
-               pretimeout_since_last_heartbeat = 0;
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
@@ -919,6 +934,45 @@ static void ipmi_register_watchdog(int ipmi_intf)
                printk(KERN_CRIT PFX "Unable to register misc device\n");
        }
 
+#ifdef HAVE_DIE_NMI_POST
+       if (nmi_handler_registered) {
+               int old_pretimeout = pretimeout;
+               int old_timeout = timeout;
+               int old_preop_val = preop_val;
+
+               /* Set the pretimeout to go off in a second and give
+                  ourselves plenty of time to stop the timer. */
+               ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
+               preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
+               pretimeout = 99;
+               timeout = 100;
+
+               testing_nmi = 1;
+
+               rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
+               if (rv) {
+                       printk(KERN_WARNING PFX "Error starting timer to"
+                              " test NMI: 0x%x.  The NMI pretimeout will"
+                              " likely not work\n", rv);
+                       rv = 0;
+                       goto out_restore;
+               }
+
+               msleep(1500);
+
+               if (testing_nmi != 2) {
+                       printk(KERN_WARNING PFX "IPMI NMI didn't seem to"
+                              " occur.  The NMI pretimeout will"
+                              " likely not work\n");
+               }
+       out_restore:
+               testing_nmi = 0;
+               preop_val = old_preop_val;
+               pretimeout = old_pretimeout;
+               timeout = old_timeout;
+       }
+#endif
+
  out:
        up_write(&register_sem);
 
@@ -928,6 +982,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
                ipmi_watchdog_state = action_val;
                ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
                printk(KERN_INFO PFX "Starting now!\n");
+       } else {
+               /* Stop the timer now. */
+               ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
+               ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
        }
 }
 
@@ -964,17 +1022,28 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
        up_write(&register_sem);
 }
 
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI_POST
 static int
-ipmi_nmi(void *dev_id, int cpu, int handled)
+ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
 {
+       if (val != DIE_NMI_POST)
+               return NOTIFY_OK;
+
+       if (testing_nmi) {
+               testing_nmi = 2;
+               return NOTIFY_STOP;
+       }
+
         /* If we are not expecting a timeout, ignore it. */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
-               return NOTIFY_DONE;
+               return NOTIFY_OK;
+
+       if (preaction_val != WDOG_PRETIMEOUT_NMI)
+               return NOTIFY_OK;
 
        /* If no one else handled the NMI, we assume it was the IPMI
            watchdog. */
-       if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
+       if (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. */
@@ -983,18 +1052,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled)
                        panic(PFX "pre-timeout");
        }
 
-       return NOTIFY_DONE;
+       return NOTIFY_STOP;
 }
 
-static struct nmi_handler ipmi_nmi_handler =
-{
-       .link     = LIST_HEAD_INIT(ipmi_nmi_handler.link),
-       .dev_name = "ipmi_watchdog",
-       .dev_id   = NULL,
-       .handler  = ipmi_nmi,
-       .priority = 0, /* Call us last. */
+static struct notifier_block ipmi_nmi_handler = {
+       .notifier_call = ipmi_nmi
 };
-int nmi_handler_registered;
 #endif
 
 static int wdog_reboot_handler(struct notifier_block *this,
@@ -1111,7 +1174,7 @@ static int preaction_op(const char *inval, char *outval)
                preaction_val = WDOG_PRETIMEOUT_NONE;
        else if (strcmp(inval, "pre_smi") == 0)
                preaction_val = WDOG_PRETIMEOUT_SMI;
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI_POST
        else if (strcmp(inval, "pre_nmi") == 0)
                preaction_val = WDOG_PRETIMEOUT_NMI;
 #endif
@@ -1145,7 +1208,7 @@ static int preop_op(const char *inval, char *outval)
 
 static void check_parms(void)
 {
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI_POST
        int do_nmi = 0;
        int rv;
 
@@ -1158,20 +1221,9 @@ static void check_parms(void)
                        preop_op("preop_none", NULL);
                        do_nmi = 0;
                }
-#ifdef CONFIG_X86_LOCAL_APIC
-               if (nmi_watchdog == NMI_IO_APIC) {
-                       printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
-                              " mode (value is %d), that is incompatible"
-                              " with using NMI in the IPMI watchdog."
-                              " Disabling IPMI nmi pretimeout.\n",
-                              nmi_watchdog);
-                       preaction_val = WDOG_PRETIMEOUT_NONE;
-                       do_nmi = 0;
-               }
-#endif
        }
        if (do_nmi && !nmi_handler_registered) {
-               rv = request_nmi(&ipmi_nmi_handler);
+               rv = register_die_notifier(&ipmi_nmi_handler);
                if (rv) {
                        printk(KERN_WARNING PFX
                               "Can't register nmi handler\n");
@@ -1179,7 +1231,7 @@ static void check_parms(void)
                } else
                        nmi_handler_registered = 1;
        } else if (!do_nmi && nmi_handler_registered) {
-               release_nmi(&ipmi_nmi_handler);
+               unregister_die_notifier(&ipmi_nmi_handler);
                nmi_handler_registered = 0;
        }
 #endif
@@ -1215,9 +1267,9 @@ static int __init ipmi_wdog_init(void)
 
        rv = ipmi_smi_watcher_register(&smi_watcher);
        if (rv) {
-#ifdef HAVE_NMI_HANDLER
-               if (preaction_val == WDOG_PRETIMEOUT_NMI)
-                       release_nmi(&ipmi_nmi_handler);
+#ifdef HAVE_DIE_NMI_POST
+               if (nmi_handler_registered)
+                       unregister_die_notifier(&ipmi_nmi_handler);
 #endif
                atomic_notifier_chain_unregister(&panic_notifier_list,
                                                 &wdog_panic_notifier);
@@ -1236,9 +1288,9 @@ static void __exit ipmi_wdog_exit(void)
        ipmi_smi_watcher_unregister(&smi_watcher);
        ipmi_unregister_watchdog(watchdog_ifnum);
 
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI_POST
        if (nmi_handler_registered)
-               release_nmi(&ipmi_nmi_handler);
+               unregister_die_notifier(&ipmi_nmi_handler);
 #endif
 
        atomic_notifier_chain_unregister(&panic_notifier_list,
index 43ab9edc76f540ce254f07f827e00414bd70abc2..761f77740d67dda027d8ff82ea6effc1b77f31ee 100644 (file)
 #define InterruptTheCard(base) outw(0, (base) + 0xc)
 #define ClearInterrupt(base) inw((base) + 0x0a)
 
+#define pr_dbg(str...) pr_debug("ISICOM: " str)
 #ifdef DEBUG
-#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str)
 #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
 #else
-#define pr_dbg(str...) do { } while (0)
 #define isicom_paranoia_check(a, b, c) 0
 #endif
 
index c06e86ad1dabb2da719a5c77ef8aa6f4965b641c..1b094509b1d2fdb5acaebb980a7e157c3b592b2e 100644 (file)
@@ -109,7 +109,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 static struct kbd_struct *kbd = kbd_table;
 
 struct vt_spawn_console vt_spawn_con = {
-       .lock = SPIN_LOCK_UNLOCKED,
+       .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
        .pid  = NULL,
        .sig  = 0,
 };
index b51d08be0bcfe5b908b6f4145823005657140e27..62051f8b0910cb97c04fc58e364f0996437c60be 100644 (file)
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
 
-/* ROUND_UP macro from fs/select.c */
-#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-
 static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
@@ -652,7 +648,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                            (par_timeout.tv_usec < 0)) {
                                return -EINVAL;
                        }
-                       to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
+                       to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
                        to_jiffies += par_timeout.tv_sec * (long) HZ;
                        if (to_jiffies <= 0) {
                                return -EINVAL;
@@ -803,7 +799,7 @@ static int lp_register(int nr, struct parport *port)
        if (reset)
                lp_reset(nr);
 
-       class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
+       class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev,
                                "lp%d", nr);
 
        printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
index 5f066963f171b5c9ff3a321b77e32798ee14be39..cc9a9d0df979f5dcf69b4e70d4f7945aae68a490 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/raw.h>
 #include <linux/tty.h>
 #include <linux/capability.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/device.h>
 #include <linux/highmem.h>
@@ -552,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
        return virtr + wrote;
 }
 
-#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
+#ifdef CONFIG_DEVPORT
 static ssize_t read_port(struct file * file, char __user * buf,
                         size_t count, loff_t *ppos)
 {
@@ -835,7 +834,7 @@ static const struct file_operations null_fops = {
        .splice_write   = splice_write_null,
 };
 
-#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
+#ifdef CONFIG_DEVPORT
 static const struct file_operations port_fops = {
        .llseek         = memory_lseek,
        .read           = read_port,
@@ -913,7 +912,7 @@ static int memory_open(struct inode * inode, struct file * filp)
                case 3:
                        filp->f_op = &null_fops;
                        break;
-#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
+#ifdef CONFIG_DEVPORT
                case 4:
                        filp->f_op = &port_fops;
                        break;
@@ -960,7 +959,7 @@ static const struct {
        {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
        {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
        {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
-#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
+#ifdef CONFIG_DEVPORT
        {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
        {5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
index 7e975f606924e04b6d24eef36707cbc97723cebc..4e6fb9651a16435e5a4e3a9fd829ac14d4b5058d 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/stat.h>
@@ -53,7 +54,7 @@
  * Head entry for the doubly linked miscdevice list
  */
 static LIST_HEAD(misc_list);
-static DECLARE_MUTEX(misc_sem);
+static DEFINE_MUTEX(misc_mtx);
 
 /*
  * Assigned numbers, used for dynamic minors
@@ -69,7 +70,7 @@ static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
        struct miscdevice *p;
        loff_t off = 0;
 
-       down(&misc_sem);
+       mutex_lock(&misc_mtx);
        list_for_each_entry(p, &misc_list, list) {
                if (*pos == off++) 
                        return p;
@@ -89,7 +90,7 @@ static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 static void misc_seq_stop(struct seq_file *seq, void *v)
 {
-       up(&misc_sem);
+       mutex_unlock(&misc_mtx);
 }
 
 static int misc_seq_show(struct seq_file *seq, void *v)
@@ -129,7 +130,7 @@ static int misc_open(struct inode * inode, struct file * file)
        int err = -ENODEV;
        const struct file_operations *old_fops, *new_fops = NULL;
        
-       down(&misc_sem);
+       mutex_lock(&misc_mtx);
        
        list_for_each_entry(c, &misc_list, list) {
                if (c->minor == minor) {
@@ -139,9 +140,9 @@ static int misc_open(struct inode * inode, struct file * file)
        }
                
        if (!new_fops) {
-               up(&misc_sem);
+               mutex_unlock(&misc_mtx);
                request_module("char-major-%d-%d", MISC_MAJOR, minor);
-               down(&misc_sem);
+               mutex_lock(&misc_mtx);
 
                list_for_each_entry(c, &misc_list, list) {
                        if (c->minor == minor) {
@@ -165,7 +166,7 @@ static int misc_open(struct inode * inode, struct file * file)
        }
        fops_put(old_fops);
 fail:
-       up(&misc_sem);
+       mutex_unlock(&misc_mtx);
        return err;
 }
 
@@ -201,10 +202,10 @@ int misc_register(struct miscdevice * misc)
 
        INIT_LIST_HEAD(&misc->list);
 
-       down(&misc_sem);
+       mutex_lock(&misc_mtx);
        list_for_each_entry(c, &misc_list, list) {
                if (c->minor == misc->minor) {
-                       up(&misc_sem);
+                       mutex_unlock(&misc_mtx);
                        return -EBUSY;
                }
        }
@@ -215,7 +216,7 @@ int misc_register(struct miscdevice * misc)
                        if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
                                break;
                if (i<0) {
-                       up(&misc_sem);
+                       mutex_unlock(&misc_mtx);
                        return -EBUSY;
                }
                misc->minor = i;
@@ -238,7 +239,7 @@ int misc_register(struct miscdevice * misc)
         */
        list_add(&misc->list, &misc_list);
  out:
-       up(&misc_sem);
+       mutex_unlock(&misc_mtx);
        return err;
 }
 
@@ -259,13 +260,13 @@ int misc_deregister(struct miscdevice * misc)
        if (list_empty(&misc->list))
                return -EINVAL;
 
-       down(&misc_sem);
+       mutex_lock(&misc_mtx);
        list_del(&misc->list);
        device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
        if (i < DYNAMIC_MINORS && i>0) {
                misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
        }
-       up(&misc_sem);
+       mutex_unlock(&misc_mtx);
        return 0;
 }
 
index 7dbaee8d940296a5617af40e029b39ff2824d4e7..e0d35c20c04fe3d5ceb7030d60077bd6cfdc2152 100644 (file)
@@ -1582,7 +1582,7 @@ copy:
 
        if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
                return -EFAULT;
-       if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS)
+       if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0)
                return -EINVAL;
 
        switch(cmd)
@@ -2529,6 +2529,8 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
        void __iomem *baseAddr;
        int i;
 
+       if(len < 0 || len > sizeof(moxaBuff))
+               return -EINVAL;
        if(copy_from_user(moxaBuff, tmp, len))
                return -EFAULT;
        baseAddr = moxa_boards[cardno].basemem;
@@ -2576,7 +2578,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
        void __iomem *baseAddr;
        int i;
 
-       if(len > sizeof(moxaBuff))
+       if(len < 0 || len > sizeof(moxaBuff))
                return -EINVAL;
        if(copy_from_user(moxaBuff, tmp, len))
                return -EFAULT;
@@ -2596,6 +2598,8 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
        void __iomem *baseAddr, *ofsAddr;
        int retval, port, i;
 
+       if(len < 0 || len > sizeof(moxaBuff))
+               return -EINVAL;
        if(copy_from_user(moxaBuff, tmp, len))
                return -EFAULT;
        baseAddr = moxa_boards[cardno].basemem;
index 80a01150b86c40674d9f0158062b2e91bdbff676..5953a45d7e96026340a120721e426ba9605c0258 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/gfp.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 
index f7603b6aeb87e3ec526d6550ce9ce2d1e42aa600..6cde448cd5b2177479e46ccd634e1a8335fb720a 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/gfp.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 
index 65f2d3a96b85dd80e9400e9c730482596f009e9f..14557a4822c0354047b804a2287846a725297955 100644 (file)
@@ -1088,13 +1088,13 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
                        /* block until there is a message: */
                        add_wait_queue(&pInfo->read_wait, &wait);
 repeat:
-                       current->state = TASK_INTERRUPTIBLE;
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        pMsg = remove_msg(pInfo, pClient);
                        if (!pMsg && !signal_pending(current)) {
                                schedule();
                                goto repeat;
                        }
-                       current->state = TASK_RUNNING;
+                       __set_current_state(TASK_RUNNING);
                        remove_wait_queue(&pInfo->read_wait, &wait);
                }
 
index 27c1179ee52749a7062c597e71f506321eeb7287..f25facd97bb45a7af74e1268c45dec99f2cb04a0 100644 (file)
@@ -21,6 +21,7 @@ config SYNCLINK_CS
 config CARDMAN_4000
        tristate "Omnikey Cardman 4000 support"
        depends on PCMCIA
+       select BITREVERSE
        help
          Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard
          reader.
index e91b43a014b09edf096ce80e8d40ec2f1fee4880..fee58e03dbe2bb30e5d8d715e9fab42be3b04e85 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
+#include <linux/bitrev.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -194,41 +195,17 @@ static inline unsigned char xinb(unsigned short port)
 }
 #endif
 
-#define        b_0000  15
-#define        b_0001  14
-#define        b_0010  13
-#define        b_0011  12
-#define        b_0100  11
-#define        b_0101  10
-#define        b_0110  9
-#define        b_0111  8
-#define        b_1000  7
-#define        b_1001  6
-#define        b_1010  5
-#define        b_1011  4
-#define        b_1100  3
-#define        b_1101  2
-#define        b_1110  1
-#define        b_1111  0
-
-static unsigned char irtab[16] = {
-       b_0000, b_1000, b_0100, b_1100,
-       b_0010, b_1010, b_0110, b_1110,
-       b_0001, b_1001, b_0101, b_1101,
-       b_0011, b_1011, b_0111, b_1111
-};
+static inline unsigned char invert_revert(unsigned char ch)
+{
+       return bitrev8(~ch);
+}
 
 static void str_invert_revert(unsigned char *b, int len)
 {
        int i;
 
        for (i = 0; i < len; i++)
-               b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4];
-}
-
-static unsigned char invert_revert(unsigned char ch)
-{
-       return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4];
+               b[i] = invert_revert(b[i]);
 }
 
 #define        ATRLENCK(dev,pos) \
@@ -1114,7 +1091,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
        /*
         * wait for atr to become valid.
         * note: it is important to lock this code. if we dont, the monitor
-        * could be run between test_bit and the the call the sleep on the
+        * could be run between test_bit and the call to sleep on the
         * atr-queue.  if *then* the monitor detects atr valid, it will wake up
         * any process on the atr-queue, *but* since we have been interrupted,
         * we do not yet sleep on this queue. this would result in a missed
@@ -1881,8 +1858,11 @@ static int cm4000_probe(struct pcmcia_device *link)
        init_waitqueue_head(&dev->readq);
 
        ret = cm4000_config(link, i);
-       if (ret)
+       if (ret) {
+               dev_table[i] = NULL;
+               kfree(dev);
                return ret;
+       }
 
        class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
                            "cmm%d", i);
@@ -1907,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link)
        cm4000_release(link);
 
        dev_table[devno] = NULL;
-       kfree(dev);
+       kfree(dev);
 
        class_device_destroy(cmm_class, MKDEV(major, devno));
 
@@ -1956,12 +1936,14 @@ static int __init cmm_init(void)
        if (major < 0) {
                printk(KERN_WARNING MODULE_NAME
                        ": could not get major number\n");
+               class_destroy(cmm_class);
                return major;
        }
 
        rc = pcmcia_register_driver(&cm4000_driver);
        if (rc < 0) {
                unregister_chrdev(major, DEVICE_NAME);
+               class_destroy(cmm_class);
                return rc;
        }
 
index f2e4ec4fd407968b7322dac8664b5fdcb6fff9e0..af88181a17f477cd01e5a1f2644a9c8039619262 100644 (file)
@@ -636,8 +636,11 @@ static int reader_probe(struct pcmcia_device *link)
        setup_timer(&dev->poll_timer, cm4040_do_poll, 0);
 
        ret = reader_config(link, i);
-       if (ret)
+       if (ret) {
+               dev_table[i] = NULL;
+               kfree(dev);
                return ret;
+       }
 
        class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
                            "cmx%d", i);
@@ -708,12 +711,14 @@ static int __init cm4040_init(void)
        if (major < 0) {
                printk(KERN_WARNING MODULE_NAME
                        ": could not get major number\n");
+               class_destroy(cmx_class);
                return major;
        }
 
        rc = pcmcia_register_driver(&reader_driver);
        if (rc < 0) {
                unregister_chrdev(major, DEVICE_NAME);
+               class_destroy(cmx_class);
                return rc;
        }
 
index 4abd1eff61d667c79297e59235437405b3f6b451..84ac64fc48a1a72f4d3aebbf5fffac70e2200ae1 100644 (file)
@@ -66,7 +66,6 @@
 #include <linux/poll.h>
 #include <linux/major.h>
 #include <linux/ppdev.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <asm/uaccess.h>
 
@@ -752,7 +751,7 @@ static const struct file_operations pp_fops = {
 
 static void pp_attach(struct parport *port)
 {
-       device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
+       device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
                        "parport%d", port->number);
 }
 
index 70145254fb9dff9af8acedcc169f791acdc00446..3494e3fc44bfb49f0886fe13d45324547eff8f7d 100644 (file)
@@ -980,7 +980,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                }
                schedule();
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->open_wait, &wait);
        if (!tty_hung_up_p(filp))
                port->count++;
index 76357c855ce3b0324c5dd26873ec85cf3971cc78..61a63da420c29ee02c1c9118c04a2454817245d9 100644 (file)
 
 /****** Kernel includes ******/
 
-#ifdef MODVERSIONS
-#include <config/modversions.h>
-#endif                         
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/major.h>
@@ -85,6 +81,7 @@
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
+#include <linux/mutex.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
@@ -93,7 +90,6 @@
 #include <asm/atomic.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
-#include <asm/semaphore.h>
 #include <linux/init.h>
 
 /****** RocketPort includes ******/
@@ -702,7 +698,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
                }
        }
        spin_lock_init(&info->slock);
-       sema_init(&info->write_sem, 1);
+       mutex_init(&info->write_mtx);
        rp_table[line] = info;
        if (pci_dev)
                tty_register_device(rocket_driver, line, &pci_dev->dev);
@@ -947,7 +943,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 #endif
                schedule();     /*  Don't hold spinlock here, will hang PC */
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->open_wait, &wait);
 
        spin_lock_irqsave(&info->slock, flags);
@@ -1602,7 +1598,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
                if (signal_pending(current))
                        break;
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
 #endif
@@ -1661,8 +1657,11 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch)
        if (rocket_paranoia_check(info, "rp_put_char"))
                return;
 
-       /*  Grab the port write semaphore, locking out other processes that try to write to this port */
-       down(&info->write_sem);
+       /*
+        * Grab the port write mutex, locking out other processes that try to
+        * write to this port
+        */
+       mutex_lock(&info->write_mtx);
 
 #ifdef ROCKET_DEBUG_WRITE
        printk(KERN_INFO "rp_put_char %c...", ch);
@@ -1684,12 +1683,12 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch)
                info->xmit_fifo_room--;
        }
        spin_unlock_irqrestore(&info->slock, flags);
-       up(&info->write_sem);
+       mutex_unlock(&info->write_mtx);
 }
 
 /*
  *  Exception handler - write routine, called when user app writes to the device.
- *  A per port write semaphore is used to protect from another process writing to
+ *  A per port write mutex is used to protect from another process writing to
  *  this port at the same time.  This other process could be running on the other CPU
  *  or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). 
  *  Spinlocks protect the info xmit members.
@@ -1706,7 +1705,7 @@ static int rp_write(struct tty_struct *tty,
        if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
                return 0;
 
-       down_interruptible(&info->write_sem);
+       mutex_lock_interruptible(&info->write_mtx);
 
 #ifdef ROCKET_DEBUG_WRITE
        printk(KERN_INFO "rp_write %d chars...", count);
@@ -1777,7 +1776,7 @@ end:
                wake_up_interruptible(&tty->poll_wait);
 #endif
        }
-       up(&info->write_sem);
+       mutex_unlock(&info->write_mtx);
        return retval;
 }
 
@@ -1852,6 +1851,12 @@ static void rp_flush_buffer(struct tty_struct *tty)
 
 #ifdef CONFIG_PCI
 
+static struct pci_device_id __devinitdata rocket_pci_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
+
 /*
  *  Called when a PCI card is found.  Retrieves and stores model information,
  *  init's aiopic and serial port hardware.
index 3a8bcc85bc14c8bbedbf552a379d0c89cca35b1b..89b4d7b10d12584c630f17b95615b533a0182d04 100644 (file)
@@ -15,6 +15,8 @@
 #define ROCKET_TYPE_MODEMIII   3
 #define ROCKET_TYPE_PC104       4
 
+#include <linux/mutex.h>
+
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -1171,7 +1173,7 @@ struct r_port {
        struct wait_queue *close_wait;
 #endif
        spinlock_t slock;
-       struct semaphore write_sem;
+       struct mutex write_mtx;
 };
 
 #define RPORT_MAGIC 0x525001
index c7dac9b13351d2585aa6e911f7bf873cd89c0547..20380a2c4dee400c877a44bdc92010b467130c7d 100644 (file)
@@ -388,7 +388,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
        if (!retval)
                retval = count;
  out:
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&rtc_wait, &wait);
 
        return retval;
index 74cff839c8572c9bf560640b0ea513938627fd54..a69f094d1ed3d8778d6c05506a346e1a56280f04 100644 (file)
@@ -299,7 +299,7 @@ int paste_selection(struct tty_struct *tty)
                pasted += count;
        }
        remove_wait_queue(&vc->paste_wait, &wait);
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
 
        tty_ldisc_deref(ld);
        return 0;
index 5fd314adc1f28d864805bea180d2f87a77d06741..c585b4738f86c2b670a46e54c4b5a154a2c5ed5d 100644 (file)
@@ -1892,7 +1892,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 #endif
                    schedule();
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->open_wait, &wait);
        if (!tty_hung_up_p(filp)) {
                info->count++;
index ce4db6f523627ebf0f1ca7841e65a30922c12204..f02a0795983ffc70d945aaa070234f5a4b3da96b 100644 (file)
@@ -4010,8 +4010,13 @@ static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
        for ( i=0; i<info->num_tx_holding_buffers; ++i) {
                info->tx_holding_buffers[i].buffer =
                        kmalloc(info->max_frame_size, GFP_KERNEL);
-               if ( info->tx_holding_buffers[i].buffer == NULL )
+               if (info->tx_holding_buffers[i].buffer == NULL) {
+                       for (--i; i >= 0; i--) {
+                               kfree(info->tx_holding_buffers[i].buffer);
+                               info->tx_holding_buffers[i].buffer = NULL;
+                       }
                        return -ENOMEM;
+               }
        }
 
        return 0;
index 0a367cd4121ffc0ab127bcc64e4838da82d98c79..2a7736b5f2f73889643e8b797500eb1e2c34f31b 100644 (file)
@@ -3415,6 +3415,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
                        }
                }
        }
+
+       for (i=0; i < port_count; ++i)
+               tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
 }
 
 static int __devinit init_one(struct pci_dev *dev,
@@ -3466,6 +3469,8 @@ static void slgt_cleanup(void)
        printk("unload %s %s\n", driver_name, driver_version);
 
        if (serial_driver) {
+               for (info=slgt_device_list ; info != NULL ; info=info->next_device)
+                       tty_unregister_device(serial_driver, info->line);
                if ((rc = tty_unregister_driver(serial_driver)))
                        DBGERR(("tty_unregister_driver error=%d\n", rc));
                put_tty_driver(serial_driver);
@@ -3506,23 +3511,10 @@ static int __init slgt_init(void)
 
        printk("%s %s\n", driver_name, driver_version);
 
-       slgt_device_count = 0;
-       if ((rc = pci_register_driver(&pci_driver)) < 0) {
-               printk("%s pci_register_driver error=%d\n", driver_name, rc);
-               return rc;
-       }
-       pci_registered = 1;
-
-       if (!slgt_device_list) {
-               printk("%s no devices found\n",driver_name);
-               pci_unregister_driver(&pci_driver);
-               return -ENODEV;
-       }
-
        serial_driver = alloc_tty_driver(MAX_DEVICES);
        if (!serial_driver) {
-               rc = -ENOMEM;
-               goto error;
+               printk("%s can't allocate tty driver\n", driver_name);
+               return -ENOMEM;
        }
 
        /* Initialize the tty_driver structure */
@@ -3539,7 +3531,7 @@ static int __init slgt_init(void)
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
        serial_driver->init_termios.c_ispeed = 9600;
        serial_driver->init_termios.c_ospeed = 9600;
-       serial_driver->flags = TTY_DRIVER_REAL_RAW;
+       serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        tty_set_operations(serial_driver, &ops);
        if ((rc = tty_register_driver(serial_driver)) < 0) {
                DBGERR(("%s can't register serial driver\n", driver_name));
@@ -3552,6 +3544,16 @@ static int __init slgt_init(void)
                driver_name, driver_version,
                serial_driver->major);
 
+       slgt_device_count = 0;
+       if ((rc = pci_register_driver(&pci_driver)) < 0) {
+               printk("%s pci_register_driver error=%d\n", driver_name, rc);
+               goto error;
+       }
+       pci_registered = 1;
+
+       if (!slgt_device_list)
+               printk("%s no devices found\n",driver_name);
+
        return 0;
 
 error:
index 1d8c4ae615513e9d6dd54875ba2dbae57a87e0fb..39cc318011ea69330744b42b0df4477e0d87d55a 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/sysrq.h>
 #include <linux/kbd_kern.h>
 #include <linux/quotaops.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/suspend.h>
index 47fb20f696953391c7ce1b10bf248c68a3b60028..35b40b9965344877e113210a7725f6657912abdd 100644 (file)
@@ -442,7 +442,7 @@ tipar_register(int nr, struct parport *port)
        }
 
        class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
-                       TIPAR_MINOR + nr), NULL, "par%d", nr);
+                       TIPAR_MINOR + nr), port->dev, "par%d", nr);
 
        /* Display informations */
        pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq ==
index fe00c7dfb649bf054376aa30522cb6c1ed2098e7..11089be0691bab5d9c5156a06f6819cc238d3ca8 100644 (file)
@@ -33,7 +33,7 @@ config TCG_NSC
        tristate "National Semiconductor TPM Interface"
        depends on TCG_TPM && PNPACPI
        ---help---
-         If you have a TPM security chip from National Semicondutor 
+         If you have a TPM security chip from National Semiconductor 
          say Yes and it will be accessible from within Linux.  To 
          compile this driver as a module, choose M here; the module 
          will be called tpm_nsc.
index e5a254a434f8345696c806b35a8d4b2539ed44fe..9bb542913b864f44631665e8fb8e2496cef8eff5 100644 (file)
@@ -24,7 +24,9 @@
  */
 
 #include <linux/poll.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
+
 #include "tpm.h"
 
 enum tpm_const {
@@ -328,10 +330,10 @@ static void timeout_work(struct work_struct *work)
 {
        struct tpm_chip *chip = container_of(work, struct tpm_chip, work);
 
-       down(&chip->buffer_mutex);
+       mutex_lock(&chip->buffer_mutex);
        atomic_set(&chip->data_pending, 0);
        memset(chip->data_buffer, 0, TPM_BUFSIZE);
-       up(&chip->buffer_mutex);
+       mutex_unlock(&chip->buffer_mutex);
 }
 
 /*
@@ -380,7 +382,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
                return -E2BIG;
        }
 
-       down(&chip->tpm_mutex);
+       mutex_lock(&chip->tpm_mutex);
 
        if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
                dev_err(chip->dev,
@@ -419,7 +421,7 @@ out_recv:
                dev_err(chip->dev,
                        "tpm_transmit: tpm_recv: error %zd\n", rc);
 out:
-       up(&chip->tpm_mutex);
+       mutex_unlock(&chip->tpm_mutex);
        return rc;
 }
 
@@ -942,12 +944,12 @@ int tpm_release(struct inode *inode, struct file *file)
 {
        struct tpm_chip *chip = file->private_data;
 
+       flush_scheduled_work();
        spin_lock(&driver_lock);
        file->private_data = NULL;
-       chip->num_opens--;
        del_singleshot_timer_sync(&chip->user_read_timer);
-       flush_scheduled_work();
        atomic_set(&chip->data_pending, 0);
+       chip->num_opens--;
        put_device(chip->dev);
        kfree(chip->data_buffer);
        spin_unlock(&driver_lock);
@@ -966,14 +968,14 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
        while (atomic_read(&chip->data_pending) != 0)
                msleep(TPM_TIMEOUT);
 
-       down(&chip->buffer_mutex);
+       mutex_lock(&chip->buffer_mutex);
 
        if (in_size > TPM_BUFSIZE)
                in_size = TPM_BUFSIZE;
 
        if (copy_from_user
            (chip->data_buffer, (void __user *) buf, in_size)) {
-               up(&chip->buffer_mutex);
+               mutex_unlock(&chip->buffer_mutex);
                return -EFAULT;
        }
 
@@ -981,7 +983,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
        out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
 
        atomic_set(&chip->data_pending, out_size);
-       up(&chip->buffer_mutex);
+       mutex_unlock(&chip->buffer_mutex);
 
        /* Set a timeout by which the reader must come claim the result */
        mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
@@ -1004,10 +1006,10 @@ ssize_t tpm_read(struct file *file, char __user *buf,
                if (size < ret_size)
                        ret_size = size;
 
-               down(&chip->buffer_mutex);
+               mutex_lock(&chip->buffer_mutex);
                if (copy_to_user(buf, chip->data_buffer, ret_size))
                        ret_size = -EFAULT;
-               up(&chip->buffer_mutex);
+               mutex_unlock(&chip->buffer_mutex);
        }
 
        return ret_size;
@@ -1097,11 +1099,16 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
 
        /* Driver specific per-device data */
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
+       devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+
+       if (chip == NULL || devname == NULL) {
+               kfree(chip);
+               kfree(devname);
                return NULL;
+       }
 
-       init_MUTEX(&chip->buffer_mutex);
-       init_MUTEX(&chip->tpm_mutex);
+       mutex_init(&chip->buffer_mutex);
+       mutex_init(&chip->tpm_mutex);
        INIT_LIST_HEAD(&chip->list);
 
        INIT_WORK(&chip->work, timeout_work);
@@ -1124,7 +1131,6 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
 
        set_bit(chip->dev_num, dev_mask);
 
-       devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
        scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
        chip->vendor.miscdev.name = devname;
 
index 9f273f032b0f9a276c9f52c2594f6be17c5bc814..b2e2b002a1bbce7e48b2c8b62e131aeeceb5ba72 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
@@ -94,11 +95,11 @@ struct tpm_chip {
        /* Data passed to and from the tpm via the read/write calls */
        u8 *data_buffer;
        atomic_t data_pending;
-       struct semaphore buffer_mutex;
+       struct mutex buffer_mutex;
 
        struct timer_list user_read_timer;      /* user needs to claim result */
        struct work_struct work;
-       struct semaphore tpm_mutex;     /* tpm is processing */
+       struct mutex tpm_mutex; /* tpm is processing */
 
        struct tpm_vendor_specific vendor;
 
index 3c852009196eab09c2cd97adec699771ca408536..c912d8691cbd202d036f3593b3451d11020a7dcf 100644 (file)
@@ -47,12 +47,12 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
        if (!dn)
                return NULL;
 
-       if (!device_is_compatible(dn, "AT97SC3201")) {
+       if (!of_device_is_compatible(dn, "AT97SC3201")) {
                of_node_put(dn);
                return NULL;
        }
 
-       reg = get_property(dn, "reg", &reglen);
+       reg = of_get_property(dn, "reg", &reglen);
        naddrc = of_n_addr_cells(dn);
        nsizec = of_n_size_cells(dn);
 
index 1353b5a6bae8eb13a6f5ccc20ebe227ab7f2b8cb..967002a5a1e56dae86010e8af334a2b814fe9a4c 100644 (file)
 #define        TPM_MAX_TRIES           5000
 #define        TPM_INFINEON_DEV_VEN_VALUE      0x15D1
 
-/* These values will be filled after PnP-call */
-static int TPM_INF_DATA;
-static int TPM_INF_ADDR;
-static int TPM_INF_BASE;
-static int TPM_INF_ADDR_LEN;
-static int TPM_INF_PORT_LEN;
+#define TPM_INF_IO_PORT                0x0
+#define TPM_INF_IO_MEM         0x1
+
+#define TPM_INF_ADDR           0x0
+#define TPM_INF_DATA           0x1
+
+struct tpm_inf_dev {
+       int iotype;
+
+       void __iomem *mem_base;         /* MMIO ioremap'd addr */
+       unsigned long map_base;         /* phys MMIO base */
+       unsigned long map_size;         /* MMIO region size */
+       unsigned int index_off;         /* index register offset */
+
+       unsigned int data_regs;         /* Data registers */
+       unsigned int data_size;
+
+       unsigned int config_port;       /* IO Port config index reg */
+       unsigned int config_size;
+};
+
+static struct tpm_inf_dev tpm_dev;
+
+static inline void tpm_data_out(unsigned char data, unsigned char offset)
+{
+       if (tpm_dev.iotype == TPM_INF_IO_PORT)
+               outb(data, tpm_dev.data_regs + offset);
+       else
+               writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset);
+}
+
+static inline unsigned char tpm_data_in(unsigned char offset)
+{
+       if (tpm_dev.iotype == TPM_INF_IO_PORT)
+               return inb(tpm_dev.data_regs + offset);
+       else
+               return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset);
+}
+
+static inline void tpm_config_out(unsigned char data, unsigned char offset)
+{
+       if (tpm_dev.iotype == TPM_INF_IO_PORT)
+               outb(data, tpm_dev.config_port + offset);
+       else
+               writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset);
+}
+
+static inline unsigned char tpm_config_in(unsigned char offset)
+{
+       if (tpm_dev.iotype == TPM_INF_IO_PORT)
+               return inb(tpm_dev.config_port + offset);
+       else
+               return readb(tpm_dev.mem_base + tpm_dev.index_off + offset);
+}
 
 /* TPM header definitions */
 enum infineon_tpm_header {
@@ -105,7 +153,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
 
        if (clear_wrfifo) {
                for (i = 0; i < 4096; i++) {
-                       status = inb(chip->vendor.base + WRFIFO);
+                       status = tpm_data_in(WRFIFO);
                        if (status == 0xff) {
                                if (check == 5)
                                        break;
@@ -125,8 +173,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
         */
        i = 0;
        do {
-               status = inb(chip->vendor.base + RDFIFO);
-               status = inb(chip->vendor.base + STAT);
+               status = tpm_data_in(RDFIFO);
+               status = tpm_data_in(STAT);
                i++;
                if (i == TPM_MAX_TRIES)
                        return -EIO;
@@ -139,7 +187,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
        int status;
        int i;
        for (i = 0; i < TPM_MAX_TRIES; i++) {
-               status = inb(chip->vendor.base + STAT);
+               status = tpm_data_in(STAT);
                /* check the status-register if wait_for_bit is set */
                if (status & 1 << wait_for_bit)
                        break;
@@ -158,7 +206,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
 static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
 {
        wait(chip, STAT_XFE);
-       outb(sendbyte, chip->vendor.base + WRFIFO);
+       tpm_data_out(sendbyte, WRFIFO);
 }
 
     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -205,7 +253,7 @@ recv_begin:
                ret = wait(chip, STAT_RDA);
                if (ret)
                        return -EIO;
-               buf[i] = inb(chip->vendor.base + RDFIFO);
+               buf[i] = tpm_data_in(RDFIFO);
        }
 
        if (buf[0] != TPM_VL_VER) {
@@ -220,7 +268,7 @@ recv_begin:
 
                for (i = 0; i < size; i++) {
                        wait(chip, STAT_RDA);
-                       buf[i] = inb(chip->vendor.base + RDFIFO);
+                       buf[i] = tpm_data_in(RDFIFO);
                }
 
                if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -269,7 +317,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
        u8 count_high, count_low, count_4, count_3, count_2, count_1;
 
        /* Disabling Reset, LP and IRQC */
-       outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
+       tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
 
        ret = empty_fifo(chip, 1);
        if (ret) {
@@ -320,7 +368,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip)
 
 static u8 tpm_inf_status(struct tpm_chip *chip)
 {
-       return inb(chip->vendor.base + STAT);
+       return tpm_data_in(STAT);
 }
 
 static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -381,51 +429,88 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
        /* read IO-ports through PnP */
        if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
            !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
-               TPM_INF_ADDR = pnp_port_start(dev, 0);
-               TPM_INF_ADDR_LEN = pnp_port_len(dev, 0);
-               TPM_INF_DATA = (TPM_INF_ADDR + 1);
-               TPM_INF_BASE = pnp_port_start(dev, 1);
-               TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
-               if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) {
+
+               tpm_dev.iotype = TPM_INF_IO_PORT;
+
+               tpm_dev.config_port = pnp_port_start(dev, 0);
+               tpm_dev.config_size = pnp_port_len(dev, 0);
+               tpm_dev.data_regs = pnp_port_start(dev, 1);
+               tpm_dev.data_size = pnp_port_len(dev, 1);
+               if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
                        rc = -EINVAL;
                        goto err_last;
                }
                dev_info(&dev->dev, "Found %s with ID %s\n",
                         dev->name, dev_id->id);
-               if (!((TPM_INF_BASE >> 8) & 0xff)) {
+               if (!((tpm_dev.data_regs >> 8) & 0xff)) {
                        rc = -EINVAL;
                        goto err_last;
                }
                /* publish my base address and request region */
-               if (request_region
-                   (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+               if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
+                                  "tpm_infineon0") == NULL) {
                        rc = -EINVAL;
                        goto err_last;
                }
-               if (request_region
-                   (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
+               if (request_region(tpm_dev.config_port, tpm_dev.config_size,
+                                  "tpm_infineon0") == NULL) {
+                       release_region(tpm_dev.data_regs, tpm_dev.data_size);
                        rc = -EINVAL;
                        goto err_last;
                }
+       } else if (pnp_mem_valid(dev, 0) &&
+                  !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
+
+               tpm_dev.iotype = TPM_INF_IO_MEM;
+
+               tpm_dev.map_base = pnp_mem_start(dev, 0);
+               tpm_dev.map_size = pnp_mem_len(dev, 0);
+
+               dev_info(&dev->dev, "Found %s with ID %s\n",
+                        dev->name, dev_id->id);
+
+               /* publish my base address and request region */
+               if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
+                                      "tpm_infineon0") == NULL) {
+                       rc = -EINVAL;
+                       goto err_last;
+               }
+
+               tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
+               if (tpm_dev.mem_base == NULL) {
+                       release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
+                       rc = -EINVAL;
+                       goto err_last;
+               }
+
+               /*
+                * The only known MMIO based Infineon TPM system provides
+                * a single large mem region with the device config
+                * registers at the default TPM_ADDR.  The data registers
+                * seem like they could be placed anywhere within the MMIO
+                * region, but lets just put them at zero offset.
+                */
+               tpm_dev.index_off = TPM_ADDR;
+               tpm_dev.data_regs = 0x0;
        } else {
                rc = -EINVAL;
                goto err_last;
        }
 
        /* query chip for its vendor, its version number a.s.o. */
-       outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
-       outb(IDVENL, TPM_INF_ADDR);
-       vendorid[1] = inb(TPM_INF_DATA);
-       outb(IDVENH, TPM_INF_ADDR);
-       vendorid[0] = inb(TPM_INF_DATA);
-       outb(IDPDL, TPM_INF_ADDR);
-       productid[1] = inb(TPM_INF_DATA);
-       outb(IDPDH, TPM_INF_ADDR);
-       productid[0] = inb(TPM_INF_DATA);
-       outb(CHIP_ID1, TPM_INF_ADDR);
-       version[1] = inb(TPM_INF_DATA);
-       outb(CHIP_ID2, TPM_INF_ADDR);
-       version[0] = inb(TPM_INF_DATA);
+       tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
+       tpm_config_out(IDVENL, TPM_INF_ADDR);
+       vendorid[1] = tpm_config_in(TPM_INF_DATA);
+       tpm_config_out(IDVENH, TPM_INF_ADDR);
+       vendorid[0] = tpm_config_in(TPM_INF_DATA);
+       tpm_config_out(IDPDL, TPM_INF_ADDR);
+       productid[1] = tpm_config_in(TPM_INF_DATA);
+       tpm_config_out(IDPDH, TPM_INF_ADDR);
+       productid[0] = tpm_config_in(TPM_INF_DATA);
+       tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
+       version[1] = tpm_config_in(TPM_INF_DATA);
+       tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
+       version[0] = tpm_config_in(TPM_INF_DATA);
 
        switch ((productid[0] << 8) | productid[1]) {
        case 6:
@@ -442,51 +527,54 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
        if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
 
                /* configure TPM with IO-ports */
-               outb(IOLIMH, TPM_INF_ADDR);
-               outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
-               outb(IOLIML, TPM_INF_ADDR);
-               outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
+               tpm_config_out(IOLIMH, TPM_INF_ADDR);
+               tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
+               tpm_config_out(IOLIML, TPM_INF_ADDR);
+               tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
 
                /* control if IO-ports are set correctly */
-               outb(IOLIMH, TPM_INF_ADDR);
-               ioh = inb(TPM_INF_DATA);
-               outb(IOLIML, TPM_INF_ADDR);
-               iol = inb(TPM_INF_DATA);
+               tpm_config_out(IOLIMH, TPM_INF_ADDR);
+               ioh = tpm_config_in(TPM_INF_DATA);
+               tpm_config_out(IOLIML, TPM_INF_ADDR);
+               iol = tpm_config_in(TPM_INF_DATA);
 
-               if ((ioh << 8 | iol) != TPM_INF_BASE) {
+               if ((ioh << 8 | iol) != tpm_dev.data_regs) {
                        dev_err(&dev->dev,
-                               "Could not set IO-ports to 0x%x\n",
-                               TPM_INF_BASE);
+                               "Could not set IO-data registers to 0x%x\n",
+                               tpm_dev.data_regs);
                        rc = -EIO;
                        goto err_release_region;
                }
 
                /* activate register */
-               outb(TPM_DAR, TPM_INF_ADDR);
-               outb(0x01, TPM_INF_DATA);
-               outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
+               tpm_config_out(TPM_DAR, TPM_INF_ADDR);
+               tpm_config_out(0x01, TPM_INF_DATA);
+               tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 
                /* disable RESET, LP and IRQC */
-               outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
+               tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
 
                /* Finally, we're done, print some infos */
                dev_info(&dev->dev, "TPM found: "
-                        "config base 0x%x, "
-                        "io base 0x%x, "
+                        "config base 0x%lx, "
+                        "data base 0x%lx, "
                         "chip version 0x%02x%02x, "
                         "vendor id 0x%x%x (Infineon), "
                         "product id 0x%02x%02x"
                         "%s\n",
-                        TPM_INF_ADDR,
-                        TPM_INF_BASE,
+                        tpm_dev.iotype == TPM_INF_IO_PORT ?
+                               tpm_dev.config_port :
+                               tpm_dev.map_base + tpm_dev.index_off,
+                        tpm_dev.iotype == TPM_INF_IO_PORT ?
+                               tpm_dev.data_regs :
+                               tpm_dev.map_base + tpm_dev.data_regs,
                         version[0], version[1],
                         vendorid[0], vendorid[1],
                         productid[0], productid[1], chipname);
 
-               if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
+               if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf)))
                        goto err_release_region;
-               }
-               chip->vendor.base = TPM_INF_BASE;
+
                return 0;
        } else {
                rc = -ENODEV;
@@ -494,8 +582,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
        }
 
 err_release_region:
-       release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
-       release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+       if (tpm_dev.iotype == TPM_INF_IO_PORT) {
+               release_region(tpm_dev.data_regs, tpm_dev.data_size);
+               release_region(tpm_dev.config_port, tpm_dev.config_size);
+       } else {
+               iounmap(tpm_dev.mem_base);
+               release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
+       }
 
 err_last:
        return rc;
@@ -506,8 +599,14 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
        struct tpm_chip *chip = pnp_get_drvdata(dev);
 
        if (chip) {
-               release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
-               release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+               if (tpm_dev.iotype == TPM_INF_IO_PORT) {
+                       release_region(tpm_dev.data_regs, tpm_dev.data_size);
+                       release_region(tpm_dev.config_port,
+                                      tpm_dev.config_size);
+               } else {
+                       iounmap(tpm_dev.mem_base);
+                       release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
+               }
                tpm_remove_hardware(chip->dev);
        }
 }
@@ -539,5 +638,5 @@ module_exit(cleanup_inf);
 
 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.8");
+MODULE_VERSION("1.9");
 MODULE_LICENSE("GPL");
index 389da364e6b6ebb2a70e732927e3e6e92f01243e..fc662e4ce58aebd0f4995c2b880b417549b294fe 100644 (file)
@@ -141,8 +141,6 @@ static DECLARE_MUTEX(allocated_ptys_lock);
 static int ptmx_open(struct inode *, struct file *);
 #endif
 
-extern void disable_early_printk(void);
-
 static void initialize_tty_struct(struct tty_struct *tty);
 
 static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
@@ -155,8 +153,8 @@ 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);
 static void release_tty(struct tty_struct *tty, int idx);
-static struct pid *__proc_set_tty(struct task_struct *tsk,
-                               struct tty_struct *tty);
+static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 
 /**
  *     alloc_tty_struct        -       allocate a tty object
@@ -935,13 +933,6 @@ restart:
        if (ld == NULL)
                return -EINVAL;
 
-       /*
-        *      No more input please, we are switching. The new ldisc
-        *      will update this value in the ldisc open function
-        */
-
-       tty->receive_room = 0;
-
        /*
         *      Problem: What do we do if this blocks ?
         */
@@ -953,6 +944,13 @@ restart:
                return 0;
        }
 
+       /*
+        *      No more input please, we are switching. The new ldisc
+        *      will update this value in the ldisc open function
+        */
+
+       tty->receive_room = 0;
+
        o_ldisc = tty->ldisc;
        o_tty = tty->link;
 
@@ -1534,10 +1532,9 @@ void disassociate_ctty(int on_exit)
        }
 
        spin_lock_irq(&current->sighand->siglock);
-       tty_pgrp = current->signal->tty_old_pgrp;
+       put_pid(current->signal->tty_old_pgrp);
        current->signal->tty_old_pgrp = NULL;
        spin_unlock_irq(&current->sighand->siglock);
-       put_pid(tty_pgrp);
 
        mutex_lock(&tty_mutex);
        /* It is possible that do_tty_hangup has free'd this tty */
@@ -1562,13 +1559,25 @@ void disassociate_ctty(int on_exit)
        unlock_kernel();
 }
 
+/**
+ *
+ *     no_tty  - Ensure the current process does not have a controlling tty
+ */
+void no_tty(void)
+{
+       struct task_struct *tsk = current;
+       if (tsk->signal->leader)
+               disassociate_ctty(0);
+       proc_clear_tty(tsk);
+}
+
 
 /**
- *     stop_tty        -       propogate flow control
+ *     stop_tty        -       propagate flow control
  *     @tty: tty to stop
  *
  *     Perform flow control to the driver. For PTY/TTY pairs we
- *     must also propogate the TIOCKPKT status. May be called
+ *     must also propagate the TIOCKPKT status. May be called
  *     on an already stopped device and will not re-call the driver
  *     method.
  *
@@ -1598,11 +1607,11 @@ void stop_tty(struct tty_struct *tty)
 EXPORT_SYMBOL(stop_tty);
 
 /**
- *     start_tty       -       propogate flow control
+ *     start_tty       -       propagate flow control
  *     @tty: tty to start
  *
  *     Start a tty that has been stopped if at all possible. Perform
- *     any neccessary wakeups and propogate the TIOCPKT status. If this
+ *     any neccessary wakeups and propagate the TIOCPKT status. If this
  *     is the tty was previous stopped and is being started then the
  *     driver start method is invoked and the line discipline woken.
  *
@@ -2508,7 +2517,6 @@ static int tty_open(struct inode * inode, struct file * filp)
        int index;
        dev_t device = inode->i_rdev;
        unsigned short saved_flags = filp->f_flags;
-       struct pid *old_pgrp;
 
        nonseekable_open(inode, filp);
        
@@ -2602,17 +2610,15 @@ got_driver:
                goto retry_open;
        }
 
-       old_pgrp = NULL;
        mutex_lock(&tty_mutex);
        spin_lock_irq(&current->sighand->siglock);
        if (!noctty &&
            current->signal->leader &&
            !current->signal->tty &&
            tty->session == NULL)
-               old_pgrp = __proc_set_tty(current, tty);
+               __proc_set_tty(current, tty);
        spin_unlock_irq(&current->sighand->siglock);
        mutex_unlock(&tty_mutex);
-       put_pid(old_pgrp);
        return 0;
 }
 
@@ -3287,9 +3293,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
                case TIOCNOTTY:
                        if (current->signal->tty != tty)
                                return -ENOTTY;
-                       if (current->signal->leader)
-                               disassociate_ctty(0);
-                       proc_clear_tty(current);
+                       no_tty();
                        return 0;
                case TIOCSCTTY:
                        return tiocsctty(tty, arg);
@@ -3766,7 +3770,9 @@ int tty_register_driver(struct tty_driver *driver)
        if (!driver->put_char)
                driver->put_char = tty_default_put_char;
        
+       mutex_lock(&tty_mutex);
        list_add(&driver->tty_drivers, &tty_drivers);
+       mutex_unlock(&tty_mutex);
        
        if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) {
                for(i = 0; i < driver->num; i++)
@@ -3792,8 +3798,9 @@ int tty_unregister_driver(struct tty_driver *driver)
 
        unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
                                driver->num);
-
+       mutex_lock(&tty_mutex);
        list_del(&driver->tty_drivers);
+       mutex_unlock(&tty_mutex);
 
        /*
         * Free the termios and termios_locked structures because
@@ -3836,11 +3843,9 @@ void proc_clear_tty(struct task_struct *p)
        p->signal->tty = NULL;
        spin_unlock_irq(&p->sighand->siglock);
 }
-EXPORT_SYMBOL(proc_clear_tty);
 
-static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
-       struct pid *old_pgrp;
        if (tty) {
                /* We should not have a session or pgrp to here but.... */
                put_pid(tty->session);
@@ -3848,21 +3853,16 @@ static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tt
                tty->session = get_pid(task_session(tsk));
                tty->pgrp = get_pid(task_pgrp(tsk));
        }
-       old_pgrp = tsk->signal->tty_old_pgrp;
+       put_pid(tsk->signal->tty_old_pgrp);
        tsk->signal->tty = tty;
        tsk->signal->tty_old_pgrp = NULL;
-       return old_pgrp;
 }
 
-void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
-       struct pid *old_pgrp;
-
        spin_lock_irq(&tsk->sighand->siglock);
-       old_pgrp = __proc_set_tty(tsk, tty);
+       __proc_set_tty(tsk, tty);
        spin_unlock_irq(&tsk->sighand->siglock);
-
-       put_pid(old_pgrp);
 }
 
 struct tty_struct *get_current_tty(void)
@@ -3897,9 +3897,6 @@ void __init console_init(void)
         * set up the console device so that later boot sequences can 
         * inform about problems etc..
         */
-#ifdef CONFIG_EARLY_PRINTK
-       disable_early_printk();
-#endif
        call = __con_initcall_start;
        while (call < __con_initcall_end) {
                (*call)();
index 791930320a13c21e2a33c2f81b0c18b233463dba..83aeedda200cfccc6724be4eaf8ce3c715b1c2d7 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/kbd_kern.h>
 #include <linux/console.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
+
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -70,11 +71,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 {
        int size;
 
-       down(&con_buf_sem);
+       mutex_lock(&con_buf_mtx);
        size = vcs_size(file->f_path.dentry->d_inode);
        switch (orig) {
                default:
-                       up(&con_buf_sem);
+                       mutex_unlock(&con_buf_mtx);
                        return -EINVAL;
                case 2:
                        offset += size;
@@ -85,11 +86,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
                        break;
        }
        if (offset < 0 || offset > size) {
-               up(&con_buf_sem);
+               mutex_unlock(&con_buf_mtx);
                return -EINVAL;
        }
        file->f_pos = offset;
-       up(&con_buf_sem);
+       mutex_unlock(&con_buf_mtx);
        return file->f_pos;
 }
 
@@ -106,7 +107,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        unsigned short *org = NULL;
        ssize_t ret;
 
-       down(&con_buf_sem);
+       mutex_lock(&con_buf_mtx);
 
        pos = *ppos;
 
@@ -263,7 +264,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                ret = read;
 unlock_out:
        release_console_sem();
-       up(&con_buf_sem);
+       mutex_unlock(&con_buf_mtx);
        return ret;
 }
 
@@ -280,7 +281,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
        u16 *org0 = NULL, *org = NULL;
        size_t ret;
 
-       down(&con_buf_sem);
+       mutex_lock(&con_buf_mtx);
 
        pos = *ppos;
 
@@ -450,7 +451,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 unlock_out:
        release_console_sem();
 
-       up(&con_buf_sem);
+       mutex_unlock(&con_buf_mtx);
 
        return ret;
 }
index 1bbb45b937fd2abbfe028ab47807d49384ee0419..bbd9fc412877a035d7ee13154361836e23b5c3fa 100644 (file)
@@ -86,6 +86,7 @@
 #include <linux/mm.h>
 #include <linux/console.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/tiocl.h>
@@ -157,6 +158,8 @@ static void blank_screen_t(unsigned long dummy);
 static void set_palette(struct vc_data *vc);
 
 static int printable;          /* Is console ready for printing? */
+static int default_utf8;
+module_param(default_utf8, int, S_IRUGO | S_IWUSR);
 
 /*
  * ignore_poke: don't unblank the screen when things are typed.  This is
@@ -348,10 +351,12 @@ void update_region(struct vc_data *vc, unsigned long start, int count)
 
 /* Structure of attributes is hardware-dependent */
 
-static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
+static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
+    u8 _underline, u8 _reverse, u8 _italic)
 {
        if (vc->vc_sw->con_build_attr)
-               return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse);
+               return vc->vc_sw->con_build_attr(vc, _color, _intensity,
+                      _blink, _underline, _reverse, _italic);
 
 #ifndef VT_BUF_VRAM_ONLY
 /*
@@ -368,10 +373,13 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8
        u8 a = vc->vc_color;
        if (!vc->vc_can_do_color)
                return _intensity |
+                      (_italic ? 2 : 0) |
                       (_underline ? 4 : 0) |
                       (_reverse ? 8 : 0) |
                       (_blink ? 0x80 : 0);
-       if (_underline)
+       if (_italic)
+               a = (a & 0xF0) | vc->vc_itcolor;
+       else if (_underline)
                a = (a & 0xf0) | vc->vc_ulcolor;
        else if (_intensity == 0)
                a = (a & 0xf0) | vc->vc_ulcolor;
@@ -392,8 +400,10 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8
 
 static void update_attr(struct vc_data *vc)
 {
-       vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm);
-       vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' ';
+       vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity,
+                     vc->vc_blink, vc->vc_underline,
+                     vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
+       vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -934,6 +944,10 @@ int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
 int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
     0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
 
+module_param_array(default_red, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(default_grn, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(default_blu, int, NULL, S_IRUGO | S_IWUSR);
+
 /*
  * gotoxy() must verify all boundaries, because the arguments
  * might also be negative. If the given position is out of
@@ -1132,6 +1146,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi
 static void default_attr(struct vc_data *vc)
 {
        vc->vc_intensity = 1;
+       vc->vc_italic = 0;
        vc->vc_underline = 0;
        vc->vc_reverse = 0;
        vc->vc_blink = 0;
@@ -1154,6 +1169,9 @@ static void csi_m(struct vc_data *vc)
                        case 2:
                                vc->vc_intensity = 0;
                                break;
+                       case 3:
+                               vc->vc_italic = 1;
+                               break;
                        case 4:
                                vc->vc_underline = 1;
                                break;
@@ -1194,6 +1212,9 @@ static void csi_m(struct vc_data *vc)
                        case 22:
                                vc->vc_intensity = 1;
                                break;
+                       case 23:
+                               vc->vc_italic = 0;
+                               break;
                        case 24:
                                vc->vc_underline = 0;
                                break;
@@ -1454,6 +1475,7 @@ static void save_cur(struct vc_data *vc)
        vc->vc_saved_x          = vc->vc_x;
        vc->vc_saved_y          = vc->vc_y;
        vc->vc_s_intensity      = vc->vc_intensity;
+       vc->vc_s_italic         = vc->vc_italic;
        vc->vc_s_underline      = vc->vc_underline;
        vc->vc_s_blink          = vc->vc_blink;
        vc->vc_s_reverse        = vc->vc_reverse;
@@ -1468,6 +1490,7 @@ static void restore_cur(struct vc_data *vc)
 {
        gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
        vc->vc_intensity        = vc->vc_s_intensity;
+       vc->vc_italic           = vc->vc_s_italic;
        vc->vc_underline        = vc->vc_s_underline;
        vc->vc_blink            = vc->vc_s_blink;
        vc->vc_reverse          = vc->vc_s_reverse;
@@ -1497,7 +1520,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        vc->vc_charset          = 0;
        vc->vc_need_wrap        = 0;
        vc->vc_report_mouse     = 0;
-       vc->vc_utf              = 0;
+       vc->vc_utf              = default_utf8;
        vc->vc_utf_count        = 0;
 
        vc->vc_disp_ctrl        = 0;
@@ -1930,7 +1953,47 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
  * kernel memory allocation is available.
  */
 char con_buf[CON_BUF_SIZE];
-DECLARE_MUTEX(con_buf_sem);
+DEFINE_MUTEX(con_buf_mtx);
+
+/* is_double_width() is based on the wcwidth() implementation by
+ * Markus Kuhn -- 2003-05-20 (Unicode 4.0)
+ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+struct interval {
+       uint32_t first;
+       uint32_t last;
+};
+
+static int bisearch(uint32_t ucs, const struct interval *table, int max)
+{
+       int min = 0;
+       int mid;
+
+       if (ucs < table[0].first || ucs > table[max].last)
+               return 0;
+       while (max >= min) {
+               mid = (min + max) / 2;
+               if (ucs > table[mid].last)
+                       min = mid + 1;
+               else if (ucs < table[mid].first)
+                       max = mid - 1;
+               else
+                       return 1;
+       }
+       return 0;
+}
+
+static int is_double_width(uint32_t ucs)
+{
+       static const struct interval double_width[] = {
+               { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
+               { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
+               { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 },
+               { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
+       };
+       return bisearch(ucs, double_width,
+               sizeof(double_width) / sizeof(*double_width) - 1);
+}
 
 /* acquires console_sem */
 static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1948,6 +2011,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
        unsigned int currcons;
        unsigned long draw_from = 0, draw_to = 0;
        struct vc_data *vc;
+       unsigned char vc_attr;
+       uint8_t rescan;
+       uint8_t inverse;
+       uint8_t width;
        u16 himask, charmask;
        const unsigned char *orig_buf = NULL;
        int orig_count;
@@ -1983,7 +2050,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
 
        /* At this point 'buf' is guaranteed to be a kernel buffer
         * and therefore no access to userspace (and therefore sleeping)
-        * will be needed.  The con_buf_sem serializes all tty based
+        * will be needed.  The con_buf_mtx serializes all tty based
         * console rendering and vcs write/read operations.  We hold
         * the console spinlock during the entire write.
         */
@@ -2010,53 +2077,86 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
                buf++;
                n++;
                count--;
+               rescan = 0;
+               inverse = 0;
+               width = 1;
 
                /* Do no translation at all in control states */
                if (vc->vc_state != ESnormal) {
                        tc = c;
                } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
-                   /* Combine UTF-8 into Unicode */
-                   /* Malformed sequences as sequences of replacement glyphs */
+                   /* Combine UTF-8 into Unicode in vc_utf_char.
+                    * vc_utf_count is the number of continuation bytes still
+                    * expected to arrive.
+                    * vc_npar is the number of continuation bytes arrived so
+                    * far
+                    */
 rescan_last_byte:
-                   if(c > 0x7f) {
+                   if ((c & 0xc0) == 0x80) {
+                       /* Continuation byte received */
+                       static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff };
                        if (vc->vc_utf_count) {
-                              if ((c & 0xc0) == 0x80) {
-                                      vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
-                                              if (--vc->vc_utf_count) {
-                                              vc->vc_npar++;
-                                              continue;
-                                              }
-                                      tc = c = vc->vc_utf_char;
-                              } else
-                                      goto replacement_glyph;
-                       } else {
-                               vc->vc_npar = 0;
-                               if ((c & 0xe0) == 0xc0) {
-                                   vc->vc_utf_count = 1;
-                                   vc->vc_utf_char = (c & 0x1f);
-                               } else if ((c & 0xf0) == 0xe0) {
-                                   vc->vc_utf_count = 2;
-                                   vc->vc_utf_char = (c & 0x0f);
-                               } else if ((c & 0xf8) == 0xf0) {
-                                   vc->vc_utf_count = 3;
-                                   vc->vc_utf_char = (c & 0x07);
-                               } else if ((c & 0xfc) == 0xf8) {
-                                   vc->vc_utf_count = 4;
-                                   vc->vc_utf_char = (c & 0x03);
-                               } else if ((c & 0xfe) == 0xfc) {
-                                   vc->vc_utf_count = 5;
-                                   vc->vc_utf_char = (c & 0x01);
-                               } else
-                                   goto replacement_glyph;
+                           vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+                           vc->vc_npar++;
+                           if (--vc->vc_utf_count) {
+                               /* Still need some bytes */
                                continue;
-                             }
+                           }
+                           /* Got a whole character */
+                           c = vc->vc_utf_char;
+                           /* Reject overlong sequences */
+                           if (c <= utf8_length_changes[vc->vc_npar - 1] ||
+                                       c > utf8_length_changes[vc->vc_npar])
+                               c = 0xfffd;
+                       } else {
+                           /* Unexpected continuation byte */
+                           vc->vc_utf_count = 0;
+                           c = 0xfffd;
+                       }
                    } else {
-                     if (vc->vc_utf_count)
-                             goto replacement_glyph;
-                     tc = c;
+                       /* Single ASCII byte or first byte of a sequence received */
+                       if (vc->vc_utf_count) {
+                           /* Continuation byte expected */
+                           rescan = 1;
+                           vc->vc_utf_count = 0;
+                           c = 0xfffd;
+                       } else if (c > 0x7f) {
+                           /* First byte of a multibyte sequence received */
+                           vc->vc_npar = 0;
+                           if ((c & 0xe0) == 0xc0) {
+                               vc->vc_utf_count = 1;
+                               vc->vc_utf_char = (c & 0x1f);
+                           } else if ((c & 0xf0) == 0xe0) {
+                               vc->vc_utf_count = 2;
+                               vc->vc_utf_char = (c & 0x0f);
+                           } else if ((c & 0xf8) == 0xf0) {
+                               vc->vc_utf_count = 3;
+                               vc->vc_utf_char = (c & 0x07);
+                           } else if ((c & 0xfc) == 0xf8) {
+                               vc->vc_utf_count = 4;
+                               vc->vc_utf_char = (c & 0x03);
+                           } else if ((c & 0xfe) == 0xfc) {
+                               vc->vc_utf_count = 5;
+                               vc->vc_utf_char = (c & 0x01);
+                           } else {
+                               /* 254 and 255 are invalid */
+                               c = 0xfffd;
+                           }
+                           if (vc->vc_utf_count) {
+                               /* Still need some bytes */
+                               continue;
+                           }
+                       }
+                       /* Nothing to do if an ASCII byte was received */
                    }
+                   /* End of UTF-8 decoding. */
+                   /* c is the received character, or U+FFFD for invalid sequences. */
+                   /* Replace invalid Unicode code points with U+FFFD too */
+                   if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
+                       c = 0xfffd;
+                   tc = c;
                } else {        /* no utf or alternate charset mode */
-                 tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
+                   tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
                }
 
                 /* If the original code was a control character we
@@ -2076,56 +2176,80 @@ rescan_last_byte:
                        && (c != 128+27);
 
                if (vc->vc_state == ESnormal && ok) {
+                       if (vc->vc_utf && !vc->vc_disp_ctrl) {
+                               if (is_double_width(c))
+                                       width = 2;
+                       }
                        /* Now try to find out how to display it */
                        tc = conv_uni_to_pc(vc, tc);
                        if (tc & ~charmask) {
-                               if ( tc == -4 ) {
-                                /* If we got -4 (not found) then see if we have
-                                   defined a replacement character (U+FFFD) */
-replacement_glyph:
-                                       tc = conv_uni_to_pc(vc, 0xfffd);
-                                       if (!(tc & ~charmask))
-                                               goto display_glyph;
-                               } else if ( tc != -3 )
-                                       continue; /* nothing to display */
-                                /* no hash table or no replacement --
-                                * hope for the best */
-                               if ( c & ~charmask )
-                                       tc = '?';
-                               else
-                                       tc = c;
+                               if (tc == -1 || tc == -2) {
+                                   continue; /* nothing to display */
+                               }
+                               /* Glyph not found */
+                               if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) {
+                                   /* In legacy mode use the glyph we get by a 1:1 mapping.
+                                      This would make absolutely no sense with Unicode in mind. */
+                                   tc = c;
+                               } else {
+                                   /* Display U+FFFD. If it's not found, display an inverse question mark. */
+                                   tc = conv_uni_to_pc(vc, 0xfffd);
+                                   if (tc < 0) {
+                                       inverse = 1;
+                                       tc = conv_uni_to_pc(vc, '?');
+                                       if (tc < 0) tc = '?';
+                                   }
+                               }
                        }
 
-display_glyph:
-                       if (vc->vc_need_wrap || vc->vc_decim)
-                               FLUSH
-                       if (vc->vc_need_wrap) {
-                               cr(vc);
-                               lf(vc);
-                       }
-                       if (vc->vc_decim)
-                               insert_char(vc, 1);
-                       scr_writew(himask ?
-                                    ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
-                                    (vc->vc_attr << 8) + tc,
-                                  (u16 *) vc->vc_pos);
-                       if (DO_UPDATE(vc) && draw_x < 0) {
-                               draw_x = vc->vc_x;
-                               draw_from = vc->vc_pos;
-                       }
-                       if (vc->vc_x == vc->vc_cols - 1) {
-                               vc->vc_need_wrap = vc->vc_decawm;
-                               draw_to = vc->vc_pos + 2;
+                       if (!inverse) {
+                               vc_attr = vc->vc_attr;
                        } else {
-                               vc->vc_x++;
-                               draw_to = (vc->vc_pos += 2);
+                               /* invert vc_attr */
+                               if (!vc->vc_can_do_color) {
+                                       vc_attr = (vc->vc_attr) ^ 0x08;
+                               } else if (vc->vc_hi_font_mask == 0x100) {
+                                       vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4);
+                               } else {
+                                       vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
+                               }
                        }
-                       if (vc->vc_utf_count) {
-                               if (vc->vc_npar) {
-                                       vc->vc_npar--;
-                                       goto display_glyph;
+
+                       while (1) {
+                               if (vc->vc_need_wrap || vc->vc_decim)
+                                       FLUSH
+                               if (vc->vc_need_wrap) {
+                                       cr(vc);
+                                       lf(vc);
+                               }
+                               if (vc->vc_decim)
+                                       insert_char(vc, 1);
+                               scr_writew(himask ?
+                                            ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+                                            (vc_attr << 8) + tc,
+                                          (u16 *) vc->vc_pos);
+                               if (DO_UPDATE(vc) && draw_x < 0) {
+                                       draw_x = vc->vc_x;
+                                       draw_from = vc->vc_pos;
+                               }
+                               if (vc->vc_x == vc->vc_cols - 1) {
+                                       vc->vc_need_wrap = vc->vc_decawm;
+                                       draw_to = vc->vc_pos + 2;
+                               } else {
+                                       vc->vc_x++;
+                                       draw_to = (vc->vc_pos += 2);
                                }
-                               vc->vc_utf_count = 0;
+
+                               if (!--width) break;
+
+                               tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
+                               if (tc < 0) tc = ' ';
+                       }
+
+                       if (rescan) {
+                               rescan = 0;
+                               inverse = 0;
+                               width = 1;
                                c = orig;
                                goto rescan_last_byte;
                        }
@@ -2581,6 +2705,11 @@ static void con_close(struct tty_struct *tty, struct file *filp)
        mutex_unlock(&tty_mutex);
 }
 
+static int default_italic_color    = 2; // green (ASCII)
+static int default_underline_color = 3; // cyan (ASCII)
+module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
+module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
+
 static void vc_init(struct vc_data *vc, unsigned int rows,
                    unsigned int cols, int do_clear)
 {
@@ -2600,7 +2729,8 @@ static void vc_init(struct vc_data *vc, unsigned int rows,
                vc->vc_palette[k++] = default_blu[j] ;
        }
        vc->vc_def_color       = 0x07;   /* white */
-       vc->vc_ulcolor          = 0x0f;   /* bold white */
+       vc->vc_ulcolor         = default_underline_color;
+       vc->vc_itcolor         = default_italic_color;
        vc->vc_halfcolor       = 0x08;   /* grey */
        init_waitqueue_head(&vc->paste_wait);
        reset_terminal(vc, do_clear);
index c9f2dd620e877391373034eba491fb0789a2c425..c6f6f42097391b20f434a669ae6b0f263fda63ee 100644 (file)
@@ -1061,7 +1061,7 @@ int vt_waitactive(int vt)
                schedule();
        }
        remove_wait_queue(&vt_activate_queue, &wait);
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        return retval;
 }
 
index 84074a697dce54dc2124aba8484f5efc969de594..b36fa8de2131813940aee9151c84729e16705a76 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
index 893dbaf386fbf41e755239f9538332fbdbd73681..eb37fba9b7efccf163badc70450aee38873b60d3 100644 (file)
@@ -1685,9 +1685,11 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
        if (sys_dev) {
                switch (action) {
                case CPU_ONLINE:
+               case CPU_ONLINE_FROZEN:
                        cpufreq_add_dev(sys_dev);
                        break;
                case CPU_DOWN_PREPARE:
+               case CPU_DOWN_PREPARE_FROZEN:
                        if (unlikely(lock_policy_rwsem_write(cpu)))
                                BUG();
 
@@ -1699,6 +1701,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
                        __cpufreq_remove_dev(sys_dev);
                        break;
                case CPU_DOWN_FAILED:
+               case CPU_DOWN_FAILED_FROZEN:
                        cpufreq_add_dev(sys_dev);
                        break;
                }
index 8d053f500fc25907d9f1d6f1691297199ecaa62a..8532bb79e5fc52dfc8d45ac3aba16b3f6ecd796f 100644 (file)
@@ -470,7 +470,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
        dbs_info->enable = 1;
        ondemand_powersave_bias_init();
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-       INIT_DELAYED_WORK(&dbs_info->work, do_dbs_timer);
+       INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
        queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
                              delay);
 }
index d1c7cac9316cc4e7729f8445c9ba8ebc07d858b7..d2f0cbd8b8f3f294ef7a1f834d52bbfcb2bf02c3 100644 (file)
@@ -313,9 +313,11 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cpufreq_update_policy(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                cpufreq_stats_free_table(cpu);
                break;
        }
index f21fe66c9eefd4590adc9ee2b9dc63bd6ead0493..f4c634504d1adac8ae847e95d5970bec6f3a3ead 100644 (file)
@@ -51,7 +51,7 @@ config CRYPTO_DEV_GEODE
        default m
        help
          Say 'Y' here to use the AMD Geode LX processor on-board AES
-         engine for the CryptoAPI AES alogrithm.
+         engine for the CryptoAPI AES algorithm.
 
          To compile this driver as a module, choose M here: the module
          will be called geode-aes.
index 161fe09a6d3871200dd353b272b6b70f3413c9c9..2800b3e614a97864ee3874d8b7841ccd298b23c7 100644 (file)
@@ -261,10 +261,6 @@ static void i82875p_check(struct mem_ctl_info *mci)
        i82875p_process_error_info(mci, &info, 1);
 }
 
-#ifdef CONFIG_PROC_FS
-extern int pci_proc_attach_device(struct pci_dev *);
-#endif
-
 /* Return 0 on success or 1 on failure. */
 static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
                struct pci_dev **ovrfl_pdev, void __iomem **ovrfl_window)
@@ -287,17 +283,12 @@ static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
 
                if (dev == NULL)
                        return 1;
+
+               pci_bus_add_device(dev);
        }
 
        *ovrfl_pdev = dev;
 
-#ifdef CONFIG_PROC_FS
-       if ((dev->procent == NULL) && pci_proc_attach_device(dev)) {
-               i82875p_printk(KERN_ERR, "%s(): Failed to attach overflow "
-                              "device\n", __func__);
-               return 1;
-       }
-#endif  /* CONFIG_PROC_FS */
        if (pci_enable_device(dev)) {
                i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow "
                               "device\n", __func__);
index 9b4fcac03ad5fee8a87922ffd9c2cab2525ffda3..3074879f231f26d9df3b5219e69a49bfcf8704d5 100644 (file)
@@ -47,7 +47,7 @@ static void virtual_eisa_release (struct device *dev)
        /* nothing really to do here */
 }
 
-static int virtual_eisa_root_init (void)
+static int __init virtual_eisa_root_init (void)
 {
        int r;
        
index 62e21cc739381e314908bbd0d6e971a303a11c56..6ec04e79f6856c0340f20a31f0b08bb9b6afeeb6 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
index 6d105a1d41b17976d92aead0e127698d548ec2aa..3ba3a5221c41776f75f07706a4d20effbca452c4 100644 (file)
@@ -2,9 +2,7 @@
 # Hardware monitoring chip drivers configuration
 #
 
-menu "Hardware Monitoring support"
-
-config HWMON
+menuconfig HWMON
        tristate "Hardware Monitoring support"
        default y
        help
@@ -23,13 +21,15 @@ config HWMON
          This support can also be built as a module.  If so, the module
          will be called hwmon.
 
+if HWMON
+
 config HWMON_VID
        tristate
        default n
 
 config SENSORS_ABITUGURU
        tristate "Abit uGuru"
-       depends on HWMON && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for the Abit uGuru chips
          sensor part. The voltage and frequency control parts of the Abit
@@ -39,9 +39,19 @@ config SENSORS_ABITUGURU
          This driver can also be built as a module.  If so, the module
          will be called abituguru.
 
+config SENSORS_AD7418
+       tristate "Analog Devices AD7416, AD7417 and AD7418"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the Analog Devices
+         AD7416, AD7417 and AD7418 temperature monitoring chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called ad7418.
+
 config SENSORS_ADM1021
        tristate "Analog Devices ADM1021 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for Analog Devices ADM1021
          and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -53,7 +63,7 @@ config SENSORS_ADM1021
 
 config SENSORS_ADM1025
        tristate "Analog Devices ADM1025 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM1025
@@ -64,7 +74,7 @@ config SENSORS_ADM1025
 
 config SENSORS_ADM1026
        tristate "Analog Devices ADM1026 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM1026
@@ -75,7 +85,7 @@ config SENSORS_ADM1026
 
 config SENSORS_ADM1029
        tristate "Analog Devices ADM1029"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        help
          If you say yes here you get support for Analog Devices ADM1029
          sensor chip.
@@ -86,7 +96,7 @@ config SENSORS_ADM1029
 
 config SENSORS_ADM1031
        tristate "Analog Devices ADM1031 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        help
          If you say yes here you get support for Analog Devices ADM1031
          and ADM1030 sensor chips.
@@ -96,7 +106,7 @@ config SENSORS_ADM1031
 
 config SENSORS_ADM9240
        tristate "Analog Devices ADM9240 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM9240,
@@ -107,7 +117,7 @@ config SENSORS_ADM9240
 
 config SENSORS_K8TEMP
        tristate "AMD Athlon64/FX or Opteron temperature sensor"
-       depends on HWMON && X86 && PCI && EXPERIMENTAL
+       depends on X86 && PCI && EXPERIMENTAL
        help
          If you say yes here you get support for the temperature
          sensor(s) inside your CPU. Supported is whole AMD K8
@@ -119,7 +129,7 @@ config SENSORS_K8TEMP
 
 config SENSORS_AMS
        tristate "Apple Motion Sensor driver"
-       depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
+       depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
        help
          Support for the motion sensor included in PowerBooks. Includes
          implementations for PMU and I2C.
@@ -144,7 +154,7 @@ config SENSORS_AMS_I2C
 
 config SENSORS_ASB100
        tristate "Asus ASB100 Bach"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for the ASB100 Bach sensor
@@ -155,7 +165,7 @@ config SENSORS_ASB100
 
 config SENSORS_ATXP1
        tristate "Attansic ATXP1 VID controller"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for the Attansic ATXP1 VID
@@ -169,7 +179,7 @@ config SENSORS_ATXP1
 
 config SENSORS_DS1621
        tristate "Dallas Semiconductor DS1621 and DS1625"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1621 and DS1625 sensor chips.
@@ -179,7 +189,7 @@ config SENSORS_DS1621
 
 config SENSORS_F71805F
        tristate "Fintek F71805F/FG and F71872F/FG"
-       depends on HWMON && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for hardware monitoring
          features of the Fintek F71805F/FG and F71872F/FG Super-I/O
@@ -190,7 +200,7 @@ config SENSORS_F71805F
 
 config SENSORS_FSCHER
        tristate "FSC Hermes"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Hermes sensor chips.
@@ -200,7 +210,7 @@ config SENSORS_FSCHER
 
 config SENSORS_FSCPOS
        tristate "FSC Poseidon"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Poseidon sensor chips.
@@ -210,7 +220,7 @@ config SENSORS_FSCPOS
 
 config SENSORS_GL518SM
        tristate "Genesys Logic GL518SM"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for Genesys Logic GL518SM
          sensor chips.
@@ -220,7 +230,7 @@ config SENSORS_GL518SM
 
 config SENSORS_GL520SM
        tristate "Genesys Logic GL520SM"
-       depends on HWMON && I2C
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for Genesys Logic GL520SM
@@ -229,9 +239,17 @@ config SENSORS_GL520SM
          This driver can also be built as a module.  If so, the module
          will be called gl520sm.
 
+config SENSORS_CORETEMP
+       tristate "Intel Core (2) Duo/Solo temperature sensor"
+       depends on X86 && EXPERIMENTAL
+       help
+         If you say yes here you get support for the temperature
+         sensor inside your CPU. Supported all are all known variants
+         of Intel Core family.
+
 config SENSORS_IT87
        tristate "ITE IT87xx and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        select I2C_ISA
        select HWMON_VID
        help
@@ -243,7 +261,7 @@ config SENSORS_IT87
 
 config SENSORS_LM63
        tristate "National Semiconductor LM63"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for the National Semiconductor
          LM63 remote diode digital temperature sensor with integrated fan
@@ -255,7 +273,7 @@ config SENSORS_LM63
 
 config SENSORS_LM70
        tristate "National Semiconductor LM70"
-       depends on HWMON && SPI_MASTER && EXPERIMENTAL
+       depends on SPI_MASTER && EXPERIMENTAL
        help
          If you say yes here you get support for the National Semiconductor
          LM70 digital temperature sensor chip.
@@ -265,7 +283,7 @@ config SENSORS_LM70
 
 config SENSORS_LM75
        tristate "National Semiconductor LM75 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM75
          sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
@@ -280,7 +298,7 @@ config SENSORS_LM75
 
 config SENSORS_LM77
        tristate "National Semiconductor LM77"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM77
          sensor chips.
@@ -290,8 +308,7 @@ config SENSORS_LM77
 
 config SENSORS_LM78
        tristate "National Semiconductor LM78 and compatibles"
-       depends on HWMON && I2C
-       select I2C_ISA
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM78,
@@ -302,7 +319,7 @@ config SENSORS_LM78
 
 config SENSORS_LM80
        tristate "National Semiconductor LM80"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        help
          If you say yes here you get support for National Semiconductor
          LM80 sensor chips.
@@ -312,7 +329,7 @@ config SENSORS_LM80
 
 config SENSORS_LM83
        tristate "National Semiconductor LM83 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for National Semiconductor
          LM82 and LM83 sensor chips.
@@ -322,7 +339,7 @@ config SENSORS_LM83
 
 config SENSORS_LM85
        tristate "National Semiconductor LM85 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM85
@@ -333,7 +350,7 @@ config SENSORS_LM85
 
 config SENSORS_LM87
        tristate "National Semiconductor LM87"
-       depends on HWMON && I2C
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM87
@@ -344,7 +361,7 @@ config SENSORS_LM87
 
 config SENSORS_LM90
        tristate "National Semiconductor LM90 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM90,
          LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
@@ -358,7 +375,7 @@ config SENSORS_LM90
 
 config SENSORS_LM92
        tristate "National Semiconductor LM92 and compatibles"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM92
          and Maxim MAX6635 sensor chips.
@@ -368,16 +385,26 @@ config SENSORS_LM92
 
 config SENSORS_MAX1619
        tristate "Maxim MAX1619 sensor chip"
-       depends on HWMON && I2C
+       depends on I2C
        help
          If you say yes here you get support for MAX1619 sensor chip.
 
          This driver can also be built as a module.  If so, the module
          will be called max1619.
 
+config SENSORS_MAX6650
+       tristate "Maxim MAX6650 sensor chip"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the MAX6650 / MAX6651
+         sensor chips.
+
+         This driver can also be built as a module.  If so, the module
+         will be called max6650.
+
 config SENSORS_PC87360
        tristate "National Semiconductor PC87360 family"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select I2C_ISA
        select HWMON_VID
        help
@@ -392,7 +419,7 @@ config SENSORS_PC87360
 
 config SENSORS_PC87427
        tristate "National Semiconductor PC87427"
-       depends on HWMON && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get access to the hardware monitoring
          functions of the National Semiconductor PC87427 Super-I/O chip.
@@ -405,7 +432,7 @@ config SENSORS_PC87427
 
 config SENSORS_SIS5595
        tristate "Silicon Integrated Systems Corp. SiS5595"
-       depends on HWMON && I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI && EXPERIMENTAL
        select I2C_ISA
        help
          If you say yes here you get support for the integrated sensors in
@@ -416,28 +443,28 @@ config SENSORS_SIS5595
 
 config SENSORS_SMSC47M1
        tristate "SMSC LPC47M10x and compatibles"
-       depends on HWMON && I2C
-       select I2C_ISA
        help
          If you say yes here you get support for the integrated fan
          monitoring and control capabilities of the SMSC LPC47B27x,
          LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x,
-         LPC47M192 and LPC47M997 chips.
+         LPC47M192, LPC47M292 and LPC47M997 chips.
 
-         The temperature and voltage sensor features of the LPC47M192
-         and LPC47M997 are supported by another driver, select also
-         "SMSC LPC47M192 and compatibles" below for those.
+         The temperature and voltage sensor features of the LPC47M15x,
+         LPC47M192, LPC47M292 and LPC47M997 are supported by another
+         driver, select also "SMSC LPC47M192 and compatibles" below for
+         those.
 
          This driver can also be built as a module.  If so, the module
          will be called smsc47m1.
 
 config SENSORS_SMSC47M192
        tristate "SMSC LPC47M192 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for the temperature and
-         voltage sensors of the SMSC LPC47M192 and LPC47M997 chips.
+         voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292
+         and LPC47M997 chips.
 
          The fan monitoring and control capabilities of these chips
          are supported by another driver, select
@@ -449,8 +476,7 @@ config SENSORS_SMSC47M192
 
 config SENSORS_SMSC47B397
        tristate "SMSC LPC47B397-NC"
-       depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_ISA
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for the SMSC LPC47B397-NC
          sensor chip.
@@ -460,7 +486,7 @@ config SENSORS_SMSC47B397
 
 config SENSORS_VIA686A
        tristate "VIA686A"
-       depends on HWMON && I2C && PCI
+       depends on I2C && PCI
        select I2C_ISA
        help
          If you say yes here you get support for the integrated sensors in
@@ -471,7 +497,7 @@ config SENSORS_VIA686A
 
 config SENSORS_VT1211
        tristate "VIA VT1211"
-       depends on HWMON && EXPERIMENTAL
+       depends on EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here then you get support for hardware monitoring
@@ -482,7 +508,7 @@ config SENSORS_VT1211
 
 config SENSORS_VT8231
        tristate "VIA VT8231"
-       depends on HWMON && I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI && EXPERIMENTAL
        select HWMON_VID
        select I2C_ISA
        help
@@ -494,8 +520,7 @@ config SENSORS_VT8231
 
 config SENSORS_W83781D
        tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
-       depends on HWMON && I2C
-       select I2C_ISA
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W8378x series
@@ -507,7 +532,7 @@ config SENSORS_W83781D
 
 config SENSORS_W83791D
        tristate "Winbond W83791D"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W83791D chip.
@@ -517,7 +542,7 @@ config SENSORS_W83791D
 
 config SENSORS_W83792D
        tristate "Winbond W83792D"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        help
          If you say yes here you get support for the Winbond W83792D chip.
 
@@ -526,7 +551,7 @@ config SENSORS_W83792D
 
 config SENSORS_W83793
        tristate "Winbond W83793"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W83793
@@ -537,7 +562,7 @@ config SENSORS_W83793
 
 config SENSORS_W83L785TS
        tristate "Winbond W83L785TS-S"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        help
          If you say yes here you get support for the Winbond W83L785TS-S
          sensor chip, which is used on the Asus A7N8X, among other
@@ -548,8 +573,6 @@ config SENSORS_W83L785TS
 
 config SENSORS_W83627HF
        tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
-       depends on HWMON && I2C
-       select I2C_ISA
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W836X7 series
@@ -561,7 +584,7 @@ config SENSORS_W83627HF
 
 config SENSORS_W83627EHF
        tristate "Winbond W83627EHF"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL
        select I2C_ISA
        help
          If you say yes here you get preliminary support for the hardware
@@ -577,7 +600,7 @@ config SENSORS_W83627EHF
 
 config SENSORS_HDAPS
        tristate "IBM Hard Drive Active Protection System (hdaps)"
-       depends on HWMON && INPUT && X86
+       depends on INPUT && X86
        default n
        help
          This driver provides support for the IBM Hard Drive Active Protection
@@ -594,9 +617,32 @@ config SENSORS_HDAPS
          Say Y here if you have an applicable laptop and want to experience
          the awesome power of hdaps.
 
+config SENSORS_APPLESMC
+       tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
+       depends on HWMON && INPUT && X86
+       select NEW_LEDS
+       select LEDS_CLASS
+       default n
+       help
+         This driver provides support for the Apple System Management
+         Controller, which provides an accelerometer (Apple Sudden Motion
+         Sensor), light sensors, temperature sensors, keyboard backlight
+         control and fan control.
+
+         Only Intel-based Apple's computers are supported (MacBook Pro,
+         MacBook, MacMini).
+
+         Data from the different sensors, keyboard backlight control and fan
+         control are accessible via sysfs.
+
+         This driver also provides an absolute input class device, allowing
+         the laptop to act as a pinball machine-esque joystick.
+
+         Say Y here if you have an applicable laptop and want to experience
+         the awesome power of applesmc.
+
 config HWMON_DEBUG_CHIP
        bool "Hardware Monitoring Chip debugging messages"
-       depends on HWMON
        default n
        help
          Say Y here if you want the I2C chip drivers to produce a bunch of
@@ -604,4 +650,4 @@ config HWMON_DEBUG_CHIP
          a problem with I2C support and want to see more of what is going
          on.
 
-endmenu
+endif # HWMON
index 4165c27a2f255bdd1a0b33e62780e15bb2fa21e8..cfaf338919dd2a481613ad8a06f6e4d69e6f2672 100644 (file)
@@ -14,14 +14,17 @@ obj-$(CONFIG_SENSORS_W83781D)       += w83781d.o
 obj-$(CONFIG_SENSORS_W83791D)  += w83791d.o
 
 obj-$(CONFIG_SENSORS_ABITUGURU)        += abituguru.o
+obj-$(CONFIG_SENSORS_AD7418)   += ad7418.o
 obj-$(CONFIG_SENSORS_ADM1021)  += adm1021.o
 obj-$(CONFIG_SENSORS_ADM1025)  += adm1025.o
 obj-$(CONFIG_SENSORS_ADM1026)  += adm1026.o
 obj-$(CONFIG_SENSORS_ADM1029)  += adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)  += adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)  += adm9240.o
+obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
 obj-$(CONFIG_SENSORS_AMS)      += ams/
 obj-$(CONFIG_SENSORS_ATXP1)    += atxp1.o
+obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
 obj-$(CONFIG_SENSORS_DS1621)   += ds1621.o
 obj-$(CONFIG_SENSORS_F71805F)  += f71805f.o
 obj-$(CONFIG_SENSORS_FSCHER)   += fscher.o
@@ -43,6 +46,7 @@ obj-$(CONFIG_SENSORS_LM87)    += lm87.o
 obj-$(CONFIG_SENSORS_LM90)     += lm90.o
 obj-$(CONFIG_SENSORS_LM92)     += lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
+obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
 obj-$(CONFIG_SENSORS_SIS5595)  += sis5595.o
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
new file mode 100644 (file)
index 0000000..cc8b624
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * An hwmon driver for the Analog Devices AD7416/17/18
+ * Copyright (C) 2006-07 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * Based on lm75.c
+ * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License,
+ * as published by the Free Software Foundation - version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include "lm75.h"
+
+#define DRV_VERSION "0.3"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END };
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418);
+
+/* AD7418 registers */
+#define AD7418_REG_TEMP_IN     0x00
+#define AD7418_REG_CONF                0x01
+#define AD7418_REG_TEMP_HYST   0x02
+#define AD7418_REG_TEMP_OS     0x03
+#define AD7418_REG_ADC         0x04
+#define AD7418_REG_CONF2       0x05
+
+#define AD7418_REG_ADC_CH(x)   ((x) << 5)
+#define AD7418_CH_TEMP         AD7418_REG_ADC_CH(0)
+
+static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
+                                       AD7418_REG_TEMP_HYST,
+                                       AD7418_REG_TEMP_OS };
+
+struct ad7418_data {
+       struct i2c_client       client;
+       struct class_device     *class_dev;
+       struct attribute_group  attrs;
+       enum chips              type;
+       struct mutex            lock;
+       int                     adc_max;        /* number of ADC channels */
+       char                    valid;
+       unsigned long           last_updated;   /* In jiffies */
+       s16                     temp[3];        /* Register values */
+       u16                     in[4];
+};
+
+static int ad7418_attach_adapter(struct i2c_adapter *adapter);
+static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind);
+static int ad7418_detach_client(struct i2c_client *client);
+
+static struct i2c_driver ad7418_driver = {
+       .driver = {
+               .name   = "ad7418",
+       },
+       .attach_adapter = ad7418_attach_adapter,
+       .detach_client  = ad7418_detach_client,
+};
+
+/* All registers are word-sized, except for the configuration registers.
+ * AD7418 uses a high-byte first convention. Do NOT use those functions to
+ * access the configuration registers CONF and CONF2, as they are byte-sized.
+ */
+static inline int ad7418_read(struct i2c_client *client, u8 reg)
+{
+       return swab16(i2c_smbus_read_word_data(client, reg));
+}
+
+static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value)
+{
+       return i2c_smbus_write_word_data(client, reg, swab16(value));
+}
+
+static void ad7418_init_client(struct i2c_client *client)
+{
+       struct ad7418_data *data = i2c_get_clientdata(client);
+
+       int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+       if (reg < 0) {
+               dev_err(&client->dev, "cannot read configuration register\n");
+       } else {
+               dev_info(&client->dev, "configuring for mode 1\n");
+               i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
+
+               if (data->type == ad7417 || data->type == ad7418)
+                       i2c_smbus_write_byte_data(client,
+                                               AD7418_REG_CONF2, 0x00);
+       }
+}
+
+static struct ad7418_data *ad7418_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ad7418_data *data = i2c_get_clientdata(client);
+
+       mutex_lock(&data->lock);
+
+       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+               || !data->valid) {
+               u8 cfg;
+               int i, ch;
+
+               /* read config register and clear channel bits */
+               cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+               cfg &= 0x1F;
+
+               i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
+                                               cfg | AD7418_CH_TEMP);
+               udelay(30);
+
+               for (i = 0; i < 3; i++) {
+                       data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]);
+               }
+
+               for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
+                       i2c_smbus_write_byte_data(client,
+                                       AD7418_REG_CONF,
+                                       cfg | AD7418_REG_ADC_CH(ch));
+
+                       udelay(15);
+                       data->in[data->adc_max - 1 - i] =
+                               ad7418_read(client, AD7418_REG_ADC);
+               }
+
+               /* restore old configuration value */
+               ad7418_write(client, AD7418_REG_CONF, cfg);
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->lock);
+
+       return data;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct ad7418_data *data = ad7418_update_device(dev);
+       return sprintf(buf, "%d\n",
+               LM75_TEMP_FROM_REG(data->temp[attr->index]));
+}
+
+static ssize_t show_adc(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct ad7418_data *data = ad7418_update_device(dev);
+
+       return sprintf(buf, "%d\n",
+               ((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ad7418_data *data = i2c_get_clientdata(client);
+       int temp = simple_strtol(buf, NULL, 10);
+
+       mutex_lock(&data->lock);
+       data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
+       ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]);
+       mutex_unlock(&data->lock);
+       return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+                               show_temp, set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+                               show_temp, set_temp, 2);
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3);
+
+static int ad7418_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_probe(adapter, &addr_data, ad7418_detect);
+}
+
+static struct attribute *ad7416_attributes[] = {
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *ad7417_attributes[] = {
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *ad7418_attributes[] = {
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       NULL
+};
+
+static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct ad7418_data *data;
+       int err = 0;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+                                       I2C_FUNC_SMBUS_WORD_DATA))
+               goto exit;
+
+       if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       client = &data->client;
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &ad7418_driver;
+
+       i2c_set_clientdata(client, data);
+
+       mutex_init(&data->lock);
+
+       /* AD7418 has a curious behaviour on registers 6 and 7. They
+        * both always read 0xC071 and are not documented on the datasheet.
+        * We use them to detect the chip.
+        */
+       if (kind <= 0) {
+               int reg, reg6, reg7;
+
+               /* the AD7416 lies within this address range, but I have
+                * no means to check.
+                */
+               if (address >= 0x48 && address <= 0x4f) {
+                       /* XXX add tests for AD7416 here */
+                       /* data->type = ad7416; */
+               }
+               /* here we might have AD7417 or AD7418 */
+               else if (address >= 0x28 && address <= 0x2f) {
+                       reg6 = i2c_smbus_read_word_data(client, 0x06);
+                       reg7 = i2c_smbus_read_word_data(client, 0x07);
+
+                       if (address == 0x28 && reg6 == 0xC071 && reg7 == 0xC071)
+                               data->type = ad7418;
+
+                       /* XXX add tests for AD7417 here */
+
+
+                       /* both AD7417 and AD7418 have bits 0-5 of
+                        * the CONF2 register at 0
+                        */
+                       reg = i2c_smbus_read_byte_data(client,
+                                                       AD7418_REG_CONF2);
+                       if (reg & 0x3F)
+                               data->type = any_chip; /* detection failed */
+               }
+       } else {
+               dev_dbg(&adapter->dev, "detection forced\n");
+       }
+
+       if (kind > 0)
+               data->type = kind;
+       else if (kind < 0 && data->type == any_chip) {
+               err = -ENODEV;
+               goto exit_free;
+       }
+
+       switch (data->type) {
+       case any_chip:
+       case ad7416:
+               data->adc_max = 0;
+               data->attrs.attrs = ad7416_attributes;
+               strlcpy(client->name, "ad7416", I2C_NAME_SIZE);
+               break;
+
+       case ad7417:
+               data->adc_max = 4;
+               data->attrs.attrs = ad7417_attributes;
+               strlcpy(client->name, "ad7417", I2C_NAME_SIZE);
+               break;
+
+       case ad7418:
+               data->adc_max = 1;
+               data->attrs.attrs = ad7418_attributes;
+               strlcpy(client->name, "ad7418", I2C_NAME_SIZE);
+               break;
+       }
+
+       if ((err = i2c_attach_client(client)))
+               goto exit_free;
+
+       dev_info(&client->dev, "%s chip found\n", client->name);
+
+       /* Initialize the AD7418 chip */
+       ad7418_init_client(client);
+
+       /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
+               goto exit_detach;
+
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
+       }
+
+       return 0;
+
+exit_remove:
+       sysfs_remove_group(&client->dev.kobj, &data->attrs);
+exit_detach:
+       i2c_detach_client(client);
+exit_free:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int ad7418_detach_client(struct i2c_client *client)
+{
+       struct ad7418_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &data->attrs);
+       i2c_detach_client(client);
+       kfree(data);
+       return 0;
+}
+
+static int __init ad7418_init(void)
+{
+       return i2c_add_driver(&ad7418_driver);
+}
+
+static void __exit ad7418_exit(void)
+{
+       i2c_del_driver(&ad7418_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("AD7416/17/18 driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ad7418_init);
+module_exit(ad7418_exit);
index f5ebad5614126d966cfc7e637a6522fda5bf705d..6db9737397259f5af26c203682b1baa75454c617 100644 (file)
@@ -144,7 +144,7 @@ int ams_sensor_attach(void)
        const u32 *prop;
 
        /* Get orientation */
-       prop = get_property(ams_info.of_node, "orientation", NULL);
+       prop = of_get_property(ams_info.of_node, "orientation", NULL);
        if (!prop)
                return -ENODEV;
        ams_info.orient1 = *prop;
@@ -208,20 +208,17 @@ int __init ams_init(void)
 
 #ifdef CONFIG_SENSORS_AMS_I2C
        np = of_find_node_by_name(NULL, "accelerometer");
-       if (np && device_is_compatible(np, "AAPL,accelerometer_1"))
+       if (np && of_device_is_compatible(np, "AAPL,accelerometer_1"))
                /* Found I2C motion sensor */
                return ams_i2c_init(np);
 #endif
 
 #ifdef CONFIG_SENSORS_AMS_PMU
        np = of_find_node_by_name(NULL, "sms");
-       if (np && device_is_compatible(np, "sms"))
+       if (np && of_device_is_compatible(np, "sms"))
                /* Found PMU motion sensor */
                return ams_pmu_init(np);
 #endif
-
-       printk(KERN_ERR "ams: No motion sensor found.\n");
-
        return -ENODEV;
 }
 
index 485d333bcb3eadabd5b7ee8e5eb6b022cc5676f1..957760536a4cf46d7c387087e3fa6ee6134a78ef 100644 (file)
@@ -85,17 +85,17 @@ static int ams_i2c_write(u8 reg, u8 value)
 static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
 {
        s32 result;
-       int remaining = HZ / 20;
+       int count = 3;
 
        ams_i2c_write(AMS_COMMAND, cmd);
-       mdelay(5);
+       msleep(5);
 
-       while (remaining) {
+       while (count--) {
                result = ams_i2c_read(AMS_COMMAND);
                if (result == 0 || result & 0x80)
                        return 0;
 
-               remaining = schedule_timeout(remaining);
+               schedule_timeout_uninterruptible(HZ / 20);
        }
 
        return -1;
@@ -276,7 +276,7 @@ int __init ams_i2c_init(struct device_node *np)
        ams_info.bustype = BUS_I2C;
 
        /* look for bus either using "reg" or by path */
-       prop = get_property(ams_info.of_node, "reg", NULL);
+       prop = of_get_property(ams_info.of_node, "reg", NULL);
        if (!prop) {
                result = -ENODEV;
 
index 1b01c215bfe7471c672557dd41303bee1979d46c..9463e9768f6f55408ce35215a79274346e41a77d 100644 (file)
@@ -160,7 +160,7 @@ int __init ams_pmu_init(struct device_node *np)
        ams_info.bustype = BUS_HOST;
 
        /* Get PMU command, should be 0x4e, but we can never know */
-       prop = get_property(ams_info.of_node, "reg", NULL);
+       prop = of_get_property(ams_info.of_node, "reg", NULL);
        if (!prop) {
                result = -ENODEV;
                goto exit;
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
new file mode 100644 (file)
index 0000000..b51c104
--- /dev/null
@@ -0,0 +1,1340 @@
+/*
+ * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
+ * sensors, fan control, keyboard backlight control) used in Intel-based Apple
+ * computers.
+ *
+ * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
+ *
+ * Based on hdaps.c driver:
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * Fan control based on smcFanControl:
+ * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <linux/mutex.h>
+#include <linux/hwmon-sysfs.h>
+#include <asm/io.h>
+#include <linux/leds.h>
+#include <linux/hwmon.h>
+#include <linux/workqueue.h>
+
+/* data port used by Apple SMC */
+#define APPLESMC_DATA_PORT     0x300
+/* command/status port used by Apple SMC */
+#define APPLESMC_CMD_PORT      0x304
+
+#define APPLESMC_NR_PORTS      32 /* 0x300-0x31f */
+
+#define APPLESMC_MAX_DATA_LENGTH 32
+
+#define APPLESMC_STATUS_MASK   0x0f
+#define APPLESMC_READ_CMD      0x10
+#define APPLESMC_WRITE_CMD     0x11
+#define APPLESMC_GET_KEY_BY_INDEX_CMD  0x12
+#define APPLESMC_GET_KEY_TYPE_CMD      0x13
+
+#define KEY_COUNT_KEY          "#KEY" /* r-o ui32 */
+
+#define LIGHT_SENSOR_LEFT_KEY  "ALV0" /* r-o {alv (6 bytes) */
+#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+#define BACKLIGHT_KEY          "LKSB" /* w-o {lkb (2 bytes) */
+
+#define CLAMSHELL_KEY          "MSLD" /* r-o ui8 (unused) */
+
+#define MOTION_SENSOR_X_KEY    "MO_X" /* r-o sp78 (2 bytes) */
+#define MOTION_SENSOR_Y_KEY    "MO_Y" /* r-o sp78 (2 bytes) */
+#define MOTION_SENSOR_Z_KEY    "MO_Z" /* r-o sp78 (2 bytes) */
+#define MOTION_SENSOR_KEY      "MOCN" /* r/w ui16 */
+
+#define FANS_COUNT             "FNum" /* r-o ui8 */
+#define FANS_MANUAL            "FS! " /* r-w ui16 */
+#define FAN_ACTUAL_SPEED       "F0Ac" /* r-o fpe2 (2 bytes) */
+#define FAN_MIN_SPEED          "F0Mn" /* r-o fpe2 (2 bytes) */
+#define FAN_MAX_SPEED          "F0Mx" /* r-o fpe2 (2 bytes) */
+#define FAN_SAFE_SPEED         "F0Sf" /* r-o fpe2 (2 bytes) */
+#define FAN_TARGET_SPEED       "F0Tg" /* r-w fpe2 (2 bytes) */
+#define FAN_POSITION           "F0ID" /* r-o char[16] */
+
+/*
+ * Temperature sensors keys (sp78 - 2 bytes).
+ * First set for Macbook(Pro), second for Macmini.
+ */
+static const char* temperature_sensors_sets[][13] = {
+       { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
+         "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
+       { "TC0D", "TC0P", NULL }
+};
+
+/* List of keys used to read/write fan speeds */
+static const char* fan_speed_keys[] = {
+       FAN_ACTUAL_SPEED,
+       FAN_MIN_SPEED,
+       FAN_MAX_SPEED,
+       FAN_SAFE_SPEED,
+       FAN_TARGET_SPEED
+};
+
+#define INIT_TIMEOUT_MSECS     5000    /* wait up to 5s for device init ... */
+#define INIT_WAIT_MSECS                50      /* ... in 50ms increments */
+
+#define APPLESMC_POLL_PERIOD   (HZ/20) /* poll for input every 1/20s */
+#define APPLESMC_INPUT_FUZZ    4       /* input event threshold */
+#define APPLESMC_INPUT_FLAT    4
+
+#define SENSOR_X 0
+#define SENSOR_Y 1
+#define SENSOR_Z 2
+
+/* Structure to be passed to DMI_MATCH function */
+struct dmi_match_data {
+/* Indicates whether this computer has an accelerometer. */
+       int accelerometer;
+/* Indicates whether this computer has light sensors and keyboard backlight. */
+       int light;
+/* Indicates which temperature sensors set to use. */
+       int temperature_set;
+};
+
+static const int debug;
+static struct platform_device *pdev;
+static s16 rest_x;
+static s16 rest_y;
+static struct timer_list applesmc_timer;
+static struct input_dev *applesmc_idev;
+static struct class_device *hwmon_class_dev;
+
+/* Indicates whether this computer has an accelerometer. */
+static unsigned int applesmc_accelerometer;
+
+/* Indicates whether this computer has light sensors and keyboard backlight. */
+static unsigned int applesmc_light;
+
+/* Indicates which temperature sensors set to use. */
+static unsigned int applesmc_temperature_set;
+
+static struct mutex applesmc_lock;
+
+/*
+ * Last index written to key_at_index sysfs file, and value to use for all other
+ * key_at_index_* sysfs files.
+ */
+static unsigned int key_at_index;
+
+static struct workqueue_struct *applesmc_led_wq;
+
+/*
+ * __wait_status - Wait up to 2ms for the status port to get a certain value
+ * (masked with 0x0f), returning zero if the value is obtained.  Callers must
+ * hold applesmc_lock.
+ */
+static int __wait_status(u8 val)
+{
+       unsigned int i;
+
+       val = val & APPLESMC_STATUS_MASK;
+
+       for (i = 0; i < 200; i++) {
+               if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
+                       if (debug)
+                               printk(KERN_DEBUG
+                                               "Waited %d us for status %x\n",
+                                               i*10, val);
+                       return 0;
+               }
+               udelay(10);
+       }
+
+       printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
+                                               val, inb(APPLESMC_CMD_PORT));
+
+       return -EIO;
+}
+
+/*
+ * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
+ * Returns zero on success or a negative error on failure. Callers must
+ * hold applesmc_lock.
+ */
+static int applesmc_read_key(const char* key, u8* buffer, u8 len)
+{
+       int i;
+
+       if (len > APPLESMC_MAX_DATA_LENGTH) {
+               printk(KERN_ERR "applesmc_read_key: cannot read more than "
+                                       "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
+               return -EINVAL;
+       }
+
+       outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
+       if (__wait_status(0x0c))
+               return -EIO;
+
+       for (i = 0; i < 4; i++) {
+               outb(key[i], APPLESMC_DATA_PORT);
+               if (__wait_status(0x04))
+                       return -EIO;
+       }
+       if (debug)
+               printk(KERN_DEBUG "<%s", key);
+
+       outb(len, APPLESMC_DATA_PORT);
+       if (debug)
+               printk(KERN_DEBUG ">%x", len);
+
+       for (i = 0; i < len; i++) {
+               if (__wait_status(0x05))
+                       return -EIO;
+               buffer[i] = inb(APPLESMC_DATA_PORT);
+               if (debug)
+                       printk(KERN_DEBUG "<%x", buffer[i]);
+       }
+       if (debug)
+               printk(KERN_DEBUG "\n");
+
+       return 0;
+}
+
+/*
+ * applesmc_write_key - writes len bytes from buffer to a given key.
+ * Returns zero on success or a negative error on failure. Callers must
+ * hold applesmc_lock.
+ */
+static int applesmc_write_key(const char* key, u8* buffer, u8 len)
+{
+       int i;
+
+       if (len > APPLESMC_MAX_DATA_LENGTH) {
+               printk(KERN_ERR "applesmc_write_key: cannot write more than "
+                                       "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
+               return -EINVAL;
+       }
+
+       outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
+       if (__wait_status(0x0c))
+               return -EIO;
+
+       for (i = 0; i < 4; i++) {
+               outb(key[i], APPLESMC_DATA_PORT);
+               if (__wait_status(0x04))
+                       return -EIO;
+       }
+
+       outb(len, APPLESMC_DATA_PORT);
+
+       for (i = 0; i < len; i++) {
+               if (__wait_status(0x04))
+                       return -EIO;
+               outb(buffer[i], APPLESMC_DATA_PORT);
+       }
+
+       return 0;
+}
+
+/*
+ * applesmc_get_key_at_index - get key at index, and put the result in key
+ * (char[6]). Returns zero on success or a negative error on failure. Callers
+ * must hold applesmc_lock.
+ */
+static int applesmc_get_key_at_index(int index, char* key)
+{
+       int i;
+       u8 readkey[4];
+       readkey[0] = index >> 24;
+       readkey[1] = index >> 16;
+       readkey[2] = index >> 8;
+       readkey[3] = index;
+
+       outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
+       if (__wait_status(0x0c))
+               return -EIO;
+
+       for (i = 0; i < 4; i++) {
+               outb(readkey[i], APPLESMC_DATA_PORT);
+               if (__wait_status(0x04))
+                       return -EIO;
+       }
+
+       outb(4, APPLESMC_DATA_PORT);
+
+       for (i = 0; i < 4; i++) {
+               if (__wait_status(0x05))
+                       return -EIO;
+               key[i] = inb(APPLESMC_DATA_PORT);
+       }
+       key[4] = 0;
+
+       return 0;
+}
+
+/*
+ * applesmc_get_key_type - get key type, and put the result in type (char[6]).
+ * Returns zero on success or a negative error on failure. Callers must
+ * hold applesmc_lock.
+ */
+static int applesmc_get_key_type(char* key, char* type)
+{
+       int i;
+
+       outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT);
+       if (__wait_status(0x0c))
+               return -EIO;
+
+       for (i = 0; i < 4; i++) {
+               outb(key[i], APPLESMC_DATA_PORT);
+               if (__wait_status(0x04))
+                       return -EIO;
+       }
+
+       outb(5, APPLESMC_DATA_PORT);
+
+       for (i = 0; i < 6; i++) {
+               if (__wait_status(0x05))
+                       return -EIO;
+               type[i] = inb(APPLESMC_DATA_PORT);
+       }
+       type[5] = 0;
+
+       return 0;
+}
+
+/*
+ * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
+ * hold applesmc_lock.
+ */
+static int applesmc_read_motion_sensor(int index, s16* value)
+{
+       u8 buffer[2];
+       int ret;
+
+       switch (index) {
+       case SENSOR_X:
+               ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2);
+               break;
+       case SENSOR_Y:
+               ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
+               break;
+       case SENSOR_Z:
+               ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       *value = ((s16)buffer[0] << 8) | buffer[1];
+
+       return ret;
+}
+
+/*
+ * applesmc_device_init - initialize the accelerometer.  Returns zero on success
+ * and negative error code on failure.  Can sleep.
+ */
+static int applesmc_device_init(void)
+{
+       int total, ret = -ENXIO;
+       u8 buffer[2];
+
+       if (!applesmc_accelerometer)
+               return 0;
+
+       mutex_lock(&applesmc_lock);
+
+       for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+               if (debug)
+                       printk(KERN_DEBUG "applesmc try %d\n", total);
+               if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
+                               (buffer[0] != 0x00 || buffer[1] != 0x00)) {
+                       if (total == INIT_TIMEOUT_MSECS) {
+                               printk(KERN_DEBUG "applesmc: device has"
+                                               " already been initialized"
+                                               " (0x%02x, 0x%02x).\n",
+                                               buffer[0], buffer[1]);
+                       } else {
+                               printk(KERN_DEBUG "applesmc: device"
+                                               " successfully initialized"
+                                               " (0x%02x, 0x%02x).\n",
+                                               buffer[0], buffer[1]);
+                       }
+                       ret = 0;
+                       goto out;
+               }
+               buffer[0] = 0xe0;
+               buffer[1] = 0x00;
+               applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
+               msleep(INIT_WAIT_MSECS);
+       }
+
+       printk(KERN_WARNING "applesmc: failed to init the device\n");
+
+out:
+       mutex_unlock(&applesmc_lock);
+       return ret;
+}
+
+/*
+ * applesmc_get_fan_count - get the number of fans. Callers must NOT hold
+ * applesmc_lock.
+ */
+static int applesmc_get_fan_count(void)
+{
+       int ret;
+       u8 buffer[1];
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(FANS_COUNT, buffer, 1);
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return buffer[0];
+}
+
+/* Device model stuff */
+static int applesmc_probe(struct platform_device *dev)
+{
+       int ret;
+
+       ret = applesmc_device_init();
+       if (ret)
+               return ret;
+
+       printk(KERN_INFO "applesmc: device successfully initialized.\n");
+       return 0;
+}
+
+static int applesmc_resume(struct platform_device *dev)
+{
+       return applesmc_device_init();
+}
+
+static struct platform_driver applesmc_driver = {
+       .probe = applesmc_probe,
+       .resume = applesmc_resume,
+       .driver = {
+               .name = "applesmc",
+               .owner = THIS_MODULE,
+       },
+};
+
+/*
+ * applesmc_calibrate - Set our "resting" values.  Callers must
+ * hold applesmc_lock.
+ */
+static void applesmc_calibrate(void)
+{
+       applesmc_read_motion_sensor(SENSOR_X, &rest_x);
+       applesmc_read_motion_sensor(SENSOR_Y, &rest_y);
+       rest_x = -rest_x;
+}
+
+static int applesmc_idev_open(struct input_dev *dev)
+{
+       add_timer(&applesmc_timer);
+
+       return 0;
+}
+
+static void applesmc_idev_close(struct input_dev *dev)
+{
+       del_timer_sync(&applesmc_timer);
+}
+
+static void applesmc_idev_poll(unsigned long unused)
+{
+       s16 x, y;
+
+       /* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
+       if (!mutex_trylock(&applesmc_lock)) {
+               mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
+               return;
+       }
+
+       if (applesmc_read_motion_sensor(SENSOR_X, &x))
+               goto out;
+       if (applesmc_read_motion_sensor(SENSOR_Y, &y))
+               goto out;
+
+       x = -x;
+       input_report_abs(applesmc_idev, ABS_X, x - rest_x);
+       input_report_abs(applesmc_idev, ABS_Y, y - rest_y);
+       input_sync(applesmc_idev);
+
+out:
+       mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
+
+       mutex_unlock(&applesmc_lock);
+}
+
+/* Sysfs Files */
+
+static ssize_t applesmc_position_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret;
+       s16 x, y, z;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_motion_sensor(SENSOR_X, &x);
+       if (ret)
+               goto out;
+       ret = applesmc_read_motion_sensor(SENSOR_Y, &y);
+       if (ret)
+               goto out;
+       ret = applesmc_read_motion_sensor(SENSOR_Z, &z);
+       if (ret)
+               goto out;
+
+out:
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
+}
+
+static ssize_t applesmc_light_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       int ret;
+       u8 left = 0, right = 0;
+       u8 buffer[6];
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, 6);
+       left = buffer[2];
+       if (ret)
+               goto out;
+       ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6);
+       right = buffer[2];
+
+out:
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
+}
+
+/* Displays degree Celsius * 1000 */
+static ssize_t applesmc_show_temperature(struct device *dev,
+                       struct device_attribute *devattr, char *sysfsbuf)
+{
+       int ret;
+       u8 buffer[2];
+       unsigned int temp;
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       const char* key =
+               temperature_sensors_sets[applesmc_temperature_set][attr->index];
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(key, buffer, 2);
+       temp = buffer[0]*1000;
+       temp += (buffer[1] >> 6) * 250;
+
+       mutex_unlock(&applesmc_lock);
+
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
+}
+
+static ssize_t applesmc_show_fan_speed(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       int ret;
+       unsigned int speed = 0;
+       char newkey[5];
+       u8 buffer[2];
+       struct sensor_device_attribute_2 *sensor_attr =
+                                               to_sensor_dev_attr_2(attr);
+
+       newkey[0] = fan_speed_keys[sensor_attr->nr][0];
+       newkey[1] = '0' + sensor_attr->index;
+       newkey[2] = fan_speed_keys[sensor_attr->nr][2];
+       newkey[3] = fan_speed_keys[sensor_attr->nr][3];
+       newkey[4] = 0;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(newkey, buffer, 2);
+       speed = ((buffer[0] << 8 | buffer[1]) >> 2);
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
+}
+
+static ssize_t applesmc_store_fan_speed(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *sysfsbuf, size_t count)
+{
+       int ret;
+       u32 speed;
+       char newkey[5];
+       u8 buffer[2];
+       struct sensor_device_attribute_2 *sensor_attr =
+                                               to_sensor_dev_attr_2(attr);
+
+       speed = simple_strtoul(sysfsbuf, NULL, 10);
+
+       if (speed > 0x4000) /* Bigger than a 14-bit value */
+               return -EINVAL;
+
+       newkey[0] = fan_speed_keys[sensor_attr->nr][0];
+       newkey[1] = '0' + sensor_attr->index;
+       newkey[2] = fan_speed_keys[sensor_attr->nr][2];
+       newkey[3] = fan_speed_keys[sensor_attr->nr][3];
+       newkey[4] = 0;
+
+       mutex_lock(&applesmc_lock);
+
+       buffer[0] = (speed >> 6) & 0xff;
+       buffer[1] = (speed << 2) & 0xff;
+       ret = applesmc_write_key(newkey, buffer, 2);
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return count;
+}
+
+static ssize_t applesmc_show_fan_manual(struct device *dev,
+                       struct device_attribute *devattr, char *sysfsbuf)
+{
+       int ret;
+       u16 manual = 0;
+       u8 buffer[2];
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
+       manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01;
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
+}
+
+static ssize_t applesmc_store_fan_manual(struct device *dev,
+                                        struct device_attribute *devattr,
+                                        const char *sysfsbuf, size_t count)
+{
+       int ret;
+       u8 buffer[2];
+       u32 input;
+       u16 val;
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+       input = simple_strtoul(sysfsbuf, NULL, 10);
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
+       val = (buffer[0] << 8 | buffer[1]);
+       if (ret)
+               goto out;
+
+       if (input)
+               val = val | (0x01 << attr->index);
+       else
+               val = val & ~(0x01 << attr->index);
+
+       buffer[0] = (val >> 8) & 0xFF;
+       buffer[1] = val & 0xFF;
+
+       ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
+
+out:
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return count;
+}
+
+static ssize_t applesmc_show_fan_position(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       int ret;
+       char newkey[5];
+       u8 buffer[17];
+       struct sensor_device_attribute_2 *sensor_attr =
+                                               to_sensor_dev_attr_2(attr);
+
+       newkey[0] = FAN_POSITION[0];
+       newkey[1] = '0' + sensor_attr->index;
+       newkey[2] = FAN_POSITION[2];
+       newkey[3] = FAN_POSITION[3];
+       newkey[4] = 0;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(newkey, buffer, 16);
+       buffer[16] = 0;
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
+}
+
+static ssize_t applesmc_calibrate_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t applesmc_calibrate_store(struct device *dev,
+       struct device_attribute *attr, const char *sysfsbuf, size_t count)
+{
+       mutex_lock(&applesmc_lock);
+       applesmc_calibrate();
+       mutex_unlock(&applesmc_lock);
+
+       return count;
+}
+
+/* Store the next backlight value to be written by the work */
+static unsigned int backlight_value;
+
+static void applesmc_backlight_set(struct work_struct *work)
+{
+       u8 buffer[2];
+
+       mutex_lock(&applesmc_lock);
+       buffer[0] = backlight_value;
+       buffer[1] = 0x00;
+       applesmc_write_key(BACKLIGHT_KEY, buffer, 2);
+       mutex_unlock(&applesmc_lock);
+}
+static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
+
+static void applesmc_brightness_set(struct led_classdev *led_cdev,
+                                               enum led_brightness value)
+{
+       int ret;
+
+       backlight_value = value;
+       ret = queue_work(applesmc_led_wq, &backlight_work);
+
+       if (debug && (!ret))
+               printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
+}
+
+static ssize_t applesmc_key_count_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       int ret;
+       u8 buffer[4];
+       u32 count;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
+       count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
+                                               ((u32)buffer[2]<<8) + buffer[3];
+
+       mutex_unlock(&applesmc_lock);
+       if (ret)
+               return ret;
+       else
+               return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
+}
+
+static ssize_t applesmc_key_at_index_read_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       char key[5];
+       char info[6];
+       int ret;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_get_key_at_index(key_at_index, key);
+
+       if (ret || !key[0]) {
+               mutex_unlock(&applesmc_lock);
+
+               return -EINVAL;
+       }
+
+       ret = applesmc_get_key_type(key, info);
+
+       if (ret) {
+               mutex_unlock(&applesmc_lock);
+
+               return ret;
+       }
+
+       /*
+        * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
+        * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
+        */
+       ret = applesmc_read_key(key, sysfsbuf, info[0]);
+
+       mutex_unlock(&applesmc_lock);
+
+       if (!ret) {
+               return info[0];
+       }
+       else {
+               return ret;
+       }
+}
+
+static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       char key[5];
+       char info[6];
+       int ret;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_get_key_at_index(key_at_index, key);
+
+       if (ret || !key[0]) {
+               mutex_unlock(&applesmc_lock);
+
+               return -EINVAL;
+       }
+
+       ret = applesmc_get_key_type(key, info);
+
+       mutex_unlock(&applesmc_lock);
+
+       if (!ret)
+               return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]);
+       else
+               return ret;
+}
+
+static ssize_t applesmc_key_at_index_type_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       char key[5];
+       char info[6];
+       int ret;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_get_key_at_index(key_at_index, key);
+
+       if (ret || !key[0]) {
+               mutex_unlock(&applesmc_lock);
+
+               return -EINVAL;
+       }
+
+       ret = applesmc_get_key_type(key, info);
+
+       mutex_unlock(&applesmc_lock);
+
+       if (!ret)
+               return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1);
+       else
+               return ret;
+}
+
+static ssize_t applesmc_key_at_index_name_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       char key[5];
+       int ret;
+
+       mutex_lock(&applesmc_lock);
+
+       ret = applesmc_get_key_at_index(key_at_index, key);
+
+       mutex_unlock(&applesmc_lock);
+
+       if (!ret && key[0])
+               return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
+       else
+               return -EINVAL;
+}
+
+static ssize_t applesmc_key_at_index_show(struct device *dev,
+                               struct device_attribute *attr, char *sysfsbuf)
+{
+       return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
+}
+
+static ssize_t applesmc_key_at_index_store(struct device *dev,
+       struct device_attribute *attr, const char *sysfsbuf, size_t count)
+{
+       mutex_lock(&applesmc_lock);
+
+       key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
+
+       mutex_unlock(&applesmc_lock);
+
+       return count;
+}
+
+static struct led_classdev applesmc_backlight = {
+       .name                   = "smc:kbd_backlight",
+       .default_trigger        = "nand-disk",
+       .brightness_set         = applesmc_brightness_set,
+};
+
+static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
+static DEVICE_ATTR(calibrate, 0644,
+                       applesmc_calibrate_show, applesmc_calibrate_store);
+
+static struct attribute *accelerometer_attributes[] = {
+       &dev_attr_position.attr,
+       &dev_attr_calibrate.attr,
+       NULL
+};
+
+static const struct attribute_group accelerometer_attributes_group =
+       { .attrs = accelerometer_attributes };
+
+static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
+
+static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
+static DEVICE_ATTR(key_at_index, 0644,
+               applesmc_key_at_index_show, applesmc_key_at_index_store);
+static DEVICE_ATTR(key_at_index_name, 0444,
+                                       applesmc_key_at_index_name_show, NULL);
+static DEVICE_ATTR(key_at_index_type, 0444,
+                                       applesmc_key_at_index_type_show, NULL);
+static DEVICE_ATTR(key_at_index_data_length, 0444,
+                               applesmc_key_at_index_data_length_show, NULL);
+static DEVICE_ATTR(key_at_index_data, 0444,
+                               applesmc_key_at_index_read_show, NULL);
+
+static struct attribute *key_enumeration_attributes[] = {
+       &dev_attr_key_count.attr,
+       &dev_attr_key_at_index.attr,
+       &dev_attr_key_at_index_name.attr,
+       &dev_attr_key_at_index_type.attr,
+       &dev_attr_key_at_index_data_length.attr,
+       &dev_attr_key_at_index_data.attr,
+       NULL
+};
+
+static const struct attribute_group key_enumeration_group =
+       { .attrs = key_enumeration_attributes };
+
+/*
+ * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
+ *  - show actual speed
+ *  - show/store minimum speed
+ *  - show maximum speed
+ *  - show safe speed
+ *  - show/store target speed
+ *  - show/store manual mode
+ */
+#define sysfs_fan_speeds_offset(offset) \
+static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
+                       applesmc_show_fan_speed, NULL, 0, offset-1); \
+\
+static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
+       applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
+\
+static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
+                       applesmc_show_fan_speed, NULL, 2, offset-1); \
+\
+static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
+                       applesmc_show_fan_speed, NULL, 3, offset-1); \
+\
+static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
+       applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
+\
+static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
+       applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
+\
+static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
+       applesmc_show_fan_position, NULL, offset-1); \
+\
+static struct attribute *fan##offset##_attributes[] = { \
+       &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
+       &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
+       NULL \
+};
+
+/*
+ * Create the needed functions for each fan using the macro defined above
+ * (2 fans are supported)
+ */
+sysfs_fan_speeds_offset(1);
+sysfs_fan_speeds_offset(2);
+
+static const struct attribute_group fan_attribute_groups[] = {
+       { .attrs = fan1_attributes },
+       { .attrs = fan2_attributes }
+};
+
+/*
+ * Temperature sensors sysfs entries.
+ */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 10);
+static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 11);
+
+static struct attribute *temperature_attributes[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp5_input.dev_attr.attr,
+       &sensor_dev_attr_temp6_input.dev_attr.attr,
+       &sensor_dev_attr_temp7_input.dev_attr.attr,
+       &sensor_dev_attr_temp8_input.dev_attr.attr,
+       &sensor_dev_attr_temp9_input.dev_attr.attr,
+       &sensor_dev_attr_temp10_input.dev_attr.attr,
+       &sensor_dev_attr_temp11_input.dev_attr.attr,
+       &sensor_dev_attr_temp12_input.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group temperature_attributes_group =
+       { .attrs = temperature_attributes };
+
+/* Module stuff */
+
+/*
+ * applesmc_dmi_match - found a match.  return one, short-circuiting the hunt.
+ */
+static int applesmc_dmi_match(struct dmi_system_id *id)
+{
+       int i = 0;
+       struct dmi_match_data* dmi_data = id->driver_data;
+       printk(KERN_INFO "applesmc: %s detected:\n", id->ident);
+       applesmc_accelerometer = dmi_data->accelerometer;
+       printk(KERN_INFO "applesmc:  - Model %s accelerometer\n",
+                               applesmc_accelerometer ? "with" : "without");
+       applesmc_light = dmi_data->light;
+       printk(KERN_INFO "applesmc:  - Model %s light sensors and backlight\n",
+                                       applesmc_light ? "with" : "without");
+
+       applesmc_temperature_set =  dmi_data->temperature_set;
+       while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL)
+               i++;
+       printk(KERN_INFO "applesmc:  - Model with %d temperature sensors\n", i);
+       return 1;
+}
+
+/* Create accelerometer ressources */
+static int applesmc_create_accelerometer(void)
+{
+       int ret;
+
+       ret = sysfs_create_group(&pdev->dev.kobj,
+                                       &accelerometer_attributes_group);
+       if (ret)
+               goto out;
+
+       applesmc_idev = input_allocate_device();
+       if (!applesmc_idev) {
+               ret = -ENOMEM;
+               goto out_sysfs;
+       }
+
+       /* initial calibrate for the input device */
+       applesmc_calibrate();
+
+       /* initialize the input class */
+       applesmc_idev->name = "applesmc";
+       applesmc_idev->id.bustype = BUS_HOST;
+       applesmc_idev->cdev.dev = &pdev->dev;
+       applesmc_idev->evbit[0] = BIT(EV_ABS);
+       applesmc_idev->open = applesmc_idev_open;
+       applesmc_idev->close = applesmc_idev_close;
+       input_set_abs_params(applesmc_idev, ABS_X,
+                       -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
+       input_set_abs_params(applesmc_idev, ABS_Y,
+                       -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
+
+       ret = input_register_device(applesmc_idev);
+       if (ret)
+               goto out_idev;
+
+       /* start up our timer for the input device */
+       init_timer(&applesmc_timer);
+       applesmc_timer.function = applesmc_idev_poll;
+       applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD;
+
+       return 0;
+
+out_idev:
+       input_free_device(applesmc_idev);
+
+out_sysfs:
+       sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
+
+out:
+       printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
+       return ret;
+}
+
+/* Release all ressources used by the accelerometer */
+static void applesmc_release_accelerometer(void)
+{
+       del_timer_sync(&applesmc_timer);
+       input_unregister_device(applesmc_idev);
+       sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
+}
+
+static __initdata struct dmi_match_data applesmc_dmi_data[] = {
+/* MacBook Pro: accelerometer, backlight and temperature set 0 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 0 },
+/* MacBook: accelerometer and temperature set 0 */
+       { .accelerometer = 1, .light = 0, .temperature_set = 0 },
+/* MacBook: temperature set 1 */
+       { .accelerometer = 0, .light = 0, .temperature_set = 1 }
+};
+
+/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
+ * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
+static __initdata struct dmi_system_id applesmc_whitelist[] = {
+       { applesmc_dmi_match, "Apple MacBook Pro", {
+         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
+               (void*)&applesmc_dmi_data[0]},
+       { applesmc_dmi_match, "Apple MacBook", {
+         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
+               (void*)&applesmc_dmi_data[1]},
+       { applesmc_dmi_match, "Apple Macmini", {
+         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
+               (void*)&applesmc_dmi_data[2]},
+       { .ident = NULL }
+};
+
+static int __init applesmc_init(void)
+{
+       int ret;
+       int count;
+       int i;
+
+       mutex_init(&applesmc_lock);
+
+       if (!dmi_check_system(applesmc_whitelist)) {
+               printk(KERN_WARNING "applesmc: supported laptop not found!\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
+                                                               "applesmc")) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       ret = platform_driver_register(&applesmc_driver);
+       if (ret)
+               goto out_region;
+
+       pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
+                                              NULL, 0);
+       if (IS_ERR(pdev)) {
+               ret = PTR_ERR(pdev);
+               goto out_driver;
+       }
+
+       /* Create key enumeration sysfs files */
+       ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
+       if (ret)
+               goto out_device;
+
+       /* create fan files */
+       count = applesmc_get_fan_count();
+       if (count < 0) {
+               printk(KERN_ERR "applesmc: Cannot get the number of fans.\n");
+       } else {
+               printk(KERN_INFO "applesmc: %d fans found.\n", count);
+
+               switch (count) {
+               default:
+                       printk(KERN_WARNING "applesmc: More than 2 fans found,"
+                                       " but at most 2 fans are supported"
+                                               " by the driver.\n");
+               case 2:
+                       ret = sysfs_create_group(&pdev->dev.kobj,
+                                                &fan_attribute_groups[1]);
+                       if (ret)
+                               goto out_key_enumeration;
+               case 1:
+                       ret = sysfs_create_group(&pdev->dev.kobj,
+                                                &fan_attribute_groups[0]);
+                       if (ret)
+                               goto out_fan_1;
+               case 0:
+                       ;
+               }
+       }
+
+       for (i = 0;
+            temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
+            i++) {
+               if (temperature_attributes[i] == NULL) {
+                       printk(KERN_ERR "applesmc: More temperature sensors "
+                               "in temperature_sensors_sets (at least %i)"
+                               "than available sysfs files in "
+                               "temperature_attributes (%i), please report "
+                               "this bug.\n", i, i-1);
+                       goto out_temperature;
+               }
+               ret = sysfs_create_file(&pdev->dev.kobj,
+                                               temperature_attributes[i]);
+               if (ret)
+                       goto out_temperature;
+       }
+
+       if (applesmc_accelerometer) {
+               ret = applesmc_create_accelerometer();
+               if (ret)
+                       goto out_temperature;
+       }
+
+       if (applesmc_light) {
+               /* Add light sensor file */
+               ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr);
+               if (ret)
+                       goto out_accelerometer;
+
+               /* Create the workqueue */
+               applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
+               if (!applesmc_led_wq) {
+                       ret = -ENOMEM;
+                       goto out_light_sysfs;
+               }
+
+               /* register as a led device */
+               ret = led_classdev_register(&pdev->dev, &applesmc_backlight);
+               if (ret < 0)
+                       goto out_light_wq;
+       }
+
+       hwmon_class_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(hwmon_class_dev)) {
+               ret = PTR_ERR(hwmon_class_dev);
+               goto out_light_ledclass;
+       }
+
+       printk(KERN_INFO "applesmc: driver successfully loaded.\n");
+
+       return 0;
+
+out_light_ledclass:
+       if (applesmc_light)
+               led_classdev_unregister(&applesmc_backlight);
+out_light_wq:
+       if (applesmc_light)
+               destroy_workqueue(applesmc_led_wq);
+out_light_sysfs:
+       if (applesmc_light)
+               sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
+out_accelerometer:
+       if (applesmc_accelerometer)
+               applesmc_release_accelerometer();
+out_temperature:
+       sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
+       sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
+out_fan_1:
+       sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
+out_key_enumeration:
+       sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+out_device:
+       platform_device_unregister(pdev);
+out_driver:
+       platform_driver_unregister(&applesmc_driver);
+out_region:
+       release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+out:
+       printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
+       return ret;
+}
+
+static void __exit applesmc_exit(void)
+{
+       hwmon_device_unregister(hwmon_class_dev);
+       if (applesmc_light) {
+               led_classdev_unregister(&applesmc_backlight);
+               destroy_workqueue(applesmc_led_wq);
+               sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
+       }
+       if (applesmc_accelerometer)
+               applesmc_release_accelerometer();
+       sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
+       sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
+       sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
+       sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&applesmc_driver);
+       release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+
+       printk(KERN_INFO "applesmc: driver unloaded.\n");
+}
+
+module_init(applesmc_init);
+module_exit(applesmc_exit);
+
+MODULE_AUTHOR("Nicolas Boichat");
+MODULE_DESCRIPTION("Apple SMC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
new file mode 100644 (file)
index 0000000..75e3911
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * coretemp.c - Linux kernel module for hardware monitoring
+ *
+ * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * Inspired from many hwmon drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+#define DRVNAME        "coretemp"
+
+typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW;
+
+/*
+ * Functions declaration
+ */
+
+static struct coretemp_data *coretemp_update_device(struct device *dev);
+
+struct coretemp_data {
+       struct class_device *class_dev;
+       struct mutex update_lock;
+       const char *name;
+       u32 id;
+       char valid;             /* zero until following fields are valid */
+       unsigned long last_updated;     /* in jiffies */
+       int temp;
+       int tjmax;
+       u8 alarm;
+};
+
+static struct coretemp_data *coretemp_update_device(struct device *dev);
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       int ret;
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct coretemp_data *data = dev_get_drvdata(dev);
+
+       if (attr->index == SHOW_NAME)
+               ret = sprintf(buf, "%s\n", data->name);
+       else    /* show label */
+               ret = sprintf(buf, "Core %d\n", data->id);
+       return ret;
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       struct coretemp_data *data = coretemp_update_device(dev);
+       /* read the Out-of-spec log, never clear */
+       return sprintf(buf, "%d\n", data->alarm);
+}
+
+static ssize_t show_temp(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct coretemp_data *data = coretemp_update_device(dev);
+       int err;
+
+       if (attr->index == SHOW_TEMP)
+               err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
+       else
+               err = sprintf(buf, "%d\n", data->tjmax);
+
+       return err;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
+                         SHOW_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
+                         SHOW_TJMAX);
+static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+
+static struct attribute *coretemp_attributes[] = {
+       &sensor_dev_attr_name.dev_attr.attr,
+       &sensor_dev_attr_temp1_label.dev_attr.attr,
+       &dev_attr_temp1_crit_alarm.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group coretemp_group = {
+       .attrs = coretemp_attributes,
+};
+
+static struct coretemp_data *coretemp_update_device(struct device *dev)
+{
+       struct coretemp_data *data = dev_get_drvdata(dev);
+
+       mutex_lock(&data->update_lock);
+
+       if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
+               u32 eax, edx;
+
+               data->valid = 0;
+               rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
+               data->alarm = (eax >> 5) & 1;
+               /* update only if data has been valid */
+               if (eax & 0x80000000) {
+                       data->temp = data->tjmax - (((eax >> 16)
+                                                       & 0x7f) * 1000);
+                       data->valid = 1;
+               } else {
+                       dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
+               }
+               data->last_updated = jiffies;
+       }
+
+       mutex_unlock(&data->update_lock);
+       return data;
+}
+
+static int __devinit coretemp_probe(struct platform_device *pdev)
+{
+       struct coretemp_data *data;
+       struct cpuinfo_x86 *c = &(cpu_data)[pdev->id];
+       int err;
+       u32 eax, edx;
+
+       if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               dev_err(&pdev->dev, "Out of memory\n");
+               goto exit;
+       }
+
+       data->id = pdev->id;
+       data->name = "coretemp";
+       mutex_init(&data->update_lock);
+       /* Tjmax default is 100 degrees C */
+       data->tjmax = 100000;
+
+       /* test if we can access the THERM_STATUS MSR */
+       err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
+       if (err) {
+               dev_err(&pdev->dev,
+                       "Unable to access THERM_STATUS MSR, giving up\n");
+               goto exit_free;
+       }
+
+       /* Some processors have Tjmax 85 following magic should detect it
+          Intel won't disclose the information without signed NDA, but
+          individuals cannot sign it. Catch(ed) 22.
+       */
+
+       if (((c->x86_model == 0xf) && (c->x86_mask > 3)) ||
+               (c->x86_model == 0xe))  {
+               err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx);
+               if (err) {
+                       dev_warn(&pdev->dev,
+                                "Unable to access MSR 0xEE, Tjmax left at %d "
+                                "degrees C\n", data->tjmax/1000);
+               } else if (eax & 0x40000000) {
+                       data->tjmax = 85000;
+               }
+       }
+
+       platform_set_drvdata(pdev, data);
+
+       if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
+               goto exit_free;
+
+       data->class_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               dev_err(&pdev->dev, "Class registration failed (%d)\n",
+                       err);
+               goto exit_class;
+       }
+
+       return 0;
+
+exit_class:
+       sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
+exit_free:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int __devexit coretemp_remove(struct platform_device *pdev)
+{
+       struct coretemp_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+       return 0;
+}
+
+static struct platform_driver coretemp_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = DRVNAME,
+       },
+       .probe = coretemp_probe,
+       .remove = __devexit_p(coretemp_remove),
+};
+
+struct pdev_entry {
+       struct list_head list;
+       struct platform_device *pdev;
+       unsigned int cpu;
+};
+
+static LIST_HEAD(pdev_list);
+static DEFINE_MUTEX(pdev_list_mutex);
+
+static int __cpuinit coretemp_device_add(unsigned int cpu)
+{
+       int err;
+       struct platform_device *pdev;
+       struct pdev_entry *pdev_entry;
+
+       pdev = platform_device_alloc(DRVNAME, cpu);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
+       if (!pdev_entry) {
+               err = -ENOMEM;
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_free;
+       }
+
+       pdev_entry->pdev = pdev;
+       pdev_entry->cpu = cpu;
+       mutex_lock(&pdev_list_mutex);
+       list_add_tail(&pdev_entry->list, &pdev_list);
+       mutex_unlock(&pdev_list_mutex);
+
+       return 0;
+
+exit_device_free:
+       kfree(pdev_entry);
+exit_device_put:
+       platform_device_put(pdev);
+exit:
+       return err;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void coretemp_device_remove(unsigned int cpu)
+{
+       struct pdev_entry *p, *n;
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               if (p->cpu == cpu) {
+                       platform_device_unregister(p->pdev);
+                       list_del(&p->list);
+                       kfree(p);
+               }
+       }
+       mutex_unlock(&pdev_list_mutex);
+}
+
+static int coretemp_cpu_callback(struct notifier_block *nfb,
+                                unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long) hcpu;
+
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               coretemp_device_add(cpu);
+               break;
+       case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
+               coretemp_device_remove(cpu);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata coretemp_cpu_notifier = {
+       .notifier_call = coretemp_cpu_callback,
+};
+#endif                         /* !CONFIG_HOTPLUG_CPU */
+
+static int __init coretemp_init(void)
+{
+       int i, err = -ENODEV;
+       struct pdev_entry *p, *n;
+
+       printk(KERN_NOTICE DRVNAME ": This driver uses undocumented features "
+               "of Core CPU. Temperature might be wrong!\n");
+
+       /* quick check if we run Intel */
+       if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
+               goto exit;
+
+       err = platform_driver_register(&coretemp_driver);
+       if (err)
+               goto exit;
+
+       for_each_online_cpu(i) {
+               struct cpuinfo_x86 *c = &(cpu_data)[i];
+
+               /* check if family 6, models e, f */
+               if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
+                   !((c->x86_model == 0xe) || (c->x86_model == 0xf))) {
+
+                       /* supported CPU not found, but report the unknown
+                          family 6 CPU */
+                       if ((c->x86 == 0x6) && (c->x86_model > 0xf))
+                               printk(KERN_WARNING DRVNAME ": Unknown CPU "
+                                       "model %x\n", c->x86_model);
+                       continue;
+               }
+
+               err = coretemp_device_add(i);
+               if (err)
+                       goto exit_devices_unreg;
+       }
+       if (list_empty(&pdev_list)) {
+               err = -ENODEV;
+               goto exit_driver_unreg;
+       }
+
+#ifdef CONFIG_HOTPLUG_CPU
+       register_hotcpu_notifier(&coretemp_cpu_notifier);
+#endif
+       return 0;
+
+exit_devices_unreg:
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               platform_device_unregister(p->pdev);
+               list_del(&p->list);
+               kfree(p);
+       }
+       mutex_unlock(&pdev_list_mutex);
+exit_driver_unreg:
+       platform_driver_unregister(&coretemp_driver);
+exit:
+       return err;
+}
+
+static void __exit coretemp_exit(void)
+{
+       struct pdev_entry *p, *n;
+#ifdef CONFIG_HOTPLUG_CPU
+       unregister_hotcpu_notifier(&coretemp_cpu_notifier);
+#endif
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               platform_device_unregister(p->pdev);
+               list_del(&p->list);
+               kfree(p);
+       }
+       mutex_unlock(&pdev_list_mutex);
+       platform_driver_unregister(&coretemp_driver);
+}
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
+MODULE_DESCRIPTION("Intel Core temperature monitor");
+MODULE_LICENSE("GPL");
+
+module_init(coretemp_init)
+module_exit(coretemp_exit)
index 7c2973487122cd139b22081225cbcbefefa28bae..cdbe309b8fc41275a64ee5bd906504f2bb808220 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/ioport.h>
 #include <asm/io.h>
 
 static struct platform_device *pdev;
@@ -1140,6 +1141,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) {
+               err = -EBUSY;
+               dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
+                       (unsigned long)(res->start + ADDR_REG_OFFSET),
+                       (unsigned long)(res->start + ADDR_REG_OFFSET + 1));
+               goto exit_free;
+       }
        data->addr = res->start;
        data->name = names[sio_data->kind];
        mutex_init(&data->update_lock);
@@ -1165,7 +1173,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
 
        /* Register sysfs interface files */
        if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
-               goto exit_free;
+               goto exit_release_region;
        if (data->has_in & (1 << 4)) { /* in4 */
                if ((err = sysfs_create_group(&pdev->dev.kobj,
                                              &f71805f_group_optin[0])))
@@ -1219,6 +1227,8 @@ exit_remove_files:
        for (i = 0; i < 4; i++)
                sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
        sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
+exit_release_region:
+       release_region(res->start + ADDR_REG_OFFSET, 2);
 exit_free:
        platform_set_drvdata(pdev, NULL);
        kfree(data);
@@ -1229,6 +1239,7 @@ exit:
 static int __devexit f71805f_remove(struct platform_device *pdev)
 {
        struct f71805f_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
        int i;
 
        platform_set_drvdata(pdev, NULL);
@@ -1239,6 +1250,9 @@ static int __devexit f71805f_remove(struct platform_device *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
        kfree(data);
 
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start + ADDR_REG_OFFSET, 2);
+
        return 0;
 }
 
index bf759ea545ac593e319fe1d89f12e48b5caba0b9..f82fa2d23f9529febecc64209a129e60b1d9c269 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/kernel.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/dmi.h>
 #include <linux/jiffies.h>
+
 #include <asm/io.h>
 
 #define HDAPS_LOW_PORT         0x1600  /* first port used by hdaps */
@@ -71,10 +73,10 @@ static u8 km_activity;
 static int rest_x;
 static int rest_y;
 
-static DECLARE_MUTEX(hdaps_sem);
+static DEFINE_MUTEX(hdaps_mtx);
 
 /*
- * __get_latch - Get the value from a given port.  Callers must hold hdaps_sem.
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_mtx.
  */
 static inline u8 __get_latch(u16 port)
 {
@@ -83,7 +85,7 @@ static inline u8 __get_latch(u16 port)
 
 /*
  * __check_latch - Check a port latch for a given value.  Returns zero if the
- * port contains the given value.  Callers must hold hdaps_sem.
+ * port contains the given value.  Callers must hold hdaps_mtx.
  */
 static inline int __check_latch(u16 port, u8 val)
 {
@@ -94,7 +96,7 @@ static inline int __check_latch(u16 port, u8 val)
 
 /*
  * __wait_latch - Wait up to 100us for a port latch to get a certain value,
- * returning zero if the value is obtained.  Callers must hold hdaps_sem.
+ * returning zero if the value is obtained.  Callers must hold hdaps_mtx.
  */
 static int __wait_latch(u16 port, u8 val)
 {
@@ -111,7 +113,7 @@ static int __wait_latch(u16 port, u8 val)
 
 /*
  * __device_refresh - request a refresh from the accelerometer.  Does not wait
- * for refresh to complete.  Callers must hold hdaps_sem.
+ * for refresh to complete.  Callers must hold hdaps_mtx.
  */
 static void __device_refresh(void)
 {
@@ -125,7 +127,7 @@ static void __device_refresh(void)
 /*
  * __device_refresh_sync - request a synchronous refresh from the
  * accelerometer.  We wait for the refresh to complete.  Returns zero if
- * successful and nonzero on error.  Callers must hold hdaps_sem.
+ * successful and nonzero on error.  Callers must hold hdaps_mtx.
  */
 static int __device_refresh_sync(void)
 {
@@ -135,7 +137,7 @@ static int __device_refresh_sync(void)
 
 /*
  * __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh.  Callers must hold hdaps_sem.
+ * data, and then initiate an async refresh.  Callers must hold hdaps_mtx.
  */
 static inline void __device_complete(void)
 {
@@ -153,7 +155,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
 {
        int ret;
 
-       down(&hdaps_sem);
+       mutex_lock(&hdaps_mtx);
 
        /* do a sync refresh -- we need to be sure that we read fresh data */
        ret = __device_refresh_sync();
@@ -164,7 +166,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
        __device_complete();
 
 out:
-       up(&hdaps_sem);
+       mutex_unlock(&hdaps_mtx);
        return ret;
 }
 
@@ -199,9 +201,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
 {
        int ret;
 
-       down(&hdaps_sem);
+       mutex_lock(&hdaps_mtx);
        ret = __hdaps_read_pair(port1, port2, val1, val2);
-       up(&hdaps_sem);
+       mutex_unlock(&hdaps_mtx);
 
        return ret;
 }
@@ -214,7 +216,7 @@ static int hdaps_device_init(void)
 {
        int total, ret = -ENXIO;
 
-       down(&hdaps_sem);
+       mutex_lock(&hdaps_mtx);
 
        outb(0x13, 0x1610);
        outb(0x01, 0x161f);
@@ -280,7 +282,7 @@ static int hdaps_device_init(void)
        }
 
 out:
-       up(&hdaps_sem);
+       mutex_unlock(&hdaps_mtx);
        return ret;
 }
 
@@ -314,7 +316,7 @@ static struct platform_driver hdaps_driver = {
 };
 
 /*
- * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_sem.
+ * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_mtx.
  */
 static void hdaps_calibrate(void)
 {
@@ -326,7 +328,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
        int x, y;
 
        /* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
-       if (down_trylock(&hdaps_sem)) {
+       if (mutex_trylock(&hdaps_mtx)) {
                mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
                return;
        }
@@ -341,7 +343,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
        mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
 
 out:
-       up(&hdaps_sem);
+       mutex_unlock(&hdaps_mtx);
 }
 
 
@@ -421,9 +423,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t count)
 {
-       down(&hdaps_sem);
+       mutex_lock(&hdaps_mtx);
        hdaps_calibrate();
-       up(&hdaps_sem);
+       mutex_unlock(&hdaps_mtx);
 
        return count;
 }
index b80f6ed5acfc9897f6e370c1dc3083caaacb6134..5aab23b93e246ffa685dc2d1e561c7c13dafd870 100644 (file)
@@ -166,16 +166,16 @@ static struct vrm_model vrm_models[] = {
        {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14},          /* Intel Core (65 nm) */
        {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110},         /* Intel Conroe */
        {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82},          /* any P6 */
-       {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0},           /* Itanium */
        {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90},          /* P4 */
        {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},          /* P4 Willamette */
        {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},          /* P4 Northwood */
        {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},         /* Prescott and above assume VRD 10 */
-       {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0},          /* Itanium 2 */
        {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},        /* Eden ESP/Ezra */
        {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},        /* Ezra T */
        {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},        /* Nemiah */
-       {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},        /* C3-M */
+       {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},        /* C3-M, Eden-N */
+       {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},         /* No information */
+       {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},        /* C7, Esther */
        {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}          /* stop here */
 };
 
index 7c65b8bb6d721498c9ac1e0f2dc968bb1b2f4744..a40166ffad127665b756668e403754b71b6c5c99 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include "lm75.h"
@@ -39,10 +40,12 @@ I2C_CLIENT_INSMOD_1(lm75);
 /* Many LM75 constants specified below */
 
 /* The LM75 registers */
-#define LM75_REG_TEMP          0x00
 #define LM75_REG_CONF          0x01
-#define LM75_REG_TEMP_HYST     0x02
-#define LM75_REG_TEMP_OS       0x03
+static const u8 LM75_REG_TEMP[3] = {
+       0x00,           /* input */
+       0x03,           /* max */
+       0x02,           /* hyst */
+};
 
 /* Each client has this additional data */
 struct lm75_data {
@@ -51,9 +54,10 @@ struct lm75_data {
        struct mutex            update_lock;
        char                    valid;          /* !=0 if following fields are valid */
        unsigned long           last_updated;   /* In jiffies */
-       u16                     temp_input;     /* Register values */
-       u16                     temp_max;
-       u16                     temp_hyst;
+       u16                     temp[3];        /* Register values,
+                                                  0 = input
+                                                  1 = max
+                                                  2 = hyst */
 };
 
 static int lm75_attach_adapter(struct i2c_adapter *adapter);
@@ -75,35 +79,36 @@ static struct i2c_driver lm75_driver = {
        .detach_client  = lm75_detach_client,
 };
 
-#define show(value)    \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)              \
-{                                                                      \
-       struct lm75_data *data = lm75_update_device(dev);               \
-       return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value));   \
+static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+                        char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct lm75_data *data = lm75_update_device(dev);
+       return sprintf(buf, "%d\n",
+                      LM75_TEMP_FROM_REG(data->temp[attr->index]));
 }
-show(temp_max);
-show(temp_hyst);
-show(temp_input);
-
-#define set(value, reg)        \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)   \
-{                                                              \
-       struct i2c_client *client = to_i2c_client(dev);         \
-       struct lm75_data *data = i2c_get_clientdata(client);    \
-       int temp = simple_strtoul(buf, NULL, 10);               \
-                                                               \
-       mutex_lock(&data->update_lock);                         \
-       data->value = LM75_TEMP_TO_REG(temp);                   \
-       lm75_write_value(client, reg, data->value);             \
-       mutex_unlock(&data->update_lock);                                       \
-       return count;                                           \
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *da,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm75_data *data = i2c_get_clientdata(client);
+       int nr = attr->index;
+       unsigned long temp = simple_strtoul(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+       data->temp[nr] = LM75_TEMP_TO_REG(temp);
+       lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]);
+       mutex_unlock(&data->update_lock);
+       return count;
 }
-set(temp_max, LM75_REG_TEMP_OS);
-set(temp_hyst, LM75_REG_TEMP_HYST);
 
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
-static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+                       show_temp, set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+                       show_temp, set_temp, 2);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
 
 static int lm75_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -113,9 +118,9 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
 }
 
 static struct attribute *lm75_attributes[] = {
-       &dev_attr_temp1_input.attr,
-       &dev_attr_temp1_max.attr,
-       &dev_attr_temp1_max_hyst.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 
        NULL
 };
@@ -283,11 +288,12 @@ static struct lm75_data *lm75_update_device(struct device *dev)
 
        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
            || !data->valid) {
+               int i;
                dev_dbg(&client->dev, "Starting lm75 update\n");
 
-               data->temp_input = lm75_read_value(client, LM75_REG_TEMP);
-               data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS);
-               data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST);
+               for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+                       data->temp[i] = lm75_read_value(client,
+                                                       LM75_REG_TEMP[i]);
                data->last_updated = jiffies;
                data->valid = 1;
        }
index 886786c33916d8960757251d4bdf5fd662a5d6dd..9fb572f03ba5bf707cd8768a7c1f60928c444821 100644 (file)
@@ -2,6 +2,7 @@
     lm78.c - Part of lm_sensors, Linux kernel modules for hardware
              monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
+    Copyright (c) 2007        Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
 
+/* ISA device, if found */
+static struct platform_device *pdev;
+
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
                                        0x25, 0x26, 0x27, 0x28, 0x29,
@@ -121,12 +127,8 @@ static inline int TEMP_FROM_REG(s8 val)
    a bit - except if there could be more than one SMBus. Groan. No solution
    for this yet. */
 
-/* This module may seem overly long and complicated. In fact, it is not so
-   bad. Quite a lot of bookkeeping is done. A real driver can often cut
-   some corners. */
-
-/* For each registered chip, we need to keep some data in memory.
-   The structure is dynamically allocated. */
+/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
+   the driver field to differentiate between I2C and ISA chips. */
 struct lm78_data {
        struct i2c_client client;
        struct class_device *class_dev;
@@ -152,14 +154,16 @@ struct lm78_data {
 
 
 static int lm78_attach_adapter(struct i2c_adapter *adapter);
-static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
 static int lm78_detach_client(struct i2c_client *client);
 
-static int lm78_read_value(struct i2c_client *client, u8 reg);
-static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value);
+static int __devinit lm78_isa_probe(struct platform_device *pdev);
+static int __devexit lm78_isa_remove(struct platform_device *pdev);
+
+static int lm78_read_value(struct lm78_data *data, u8 reg);
+static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value);
 static struct lm78_data *lm78_update_device(struct device *dev);
-static void lm78_init_client(struct i2c_client *client);
+static void lm78_init_device(struct lm78_data *data);
 
 
 static struct i2c_driver lm78_driver = {
@@ -171,95 +175,78 @@ static struct i2c_driver lm78_driver = {
        .detach_client  = lm78_detach_client,
 };
 
-static struct i2c_driver lm78_isa_driver = {
+static struct platform_driver lm78_isa_driver = {
        .driver = {
                .owner  = THIS_MODULE,
-               .name   = "lm78-isa",
+               .name   = "lm78",
        },
-       .attach_adapter = lm78_isa_attach_adapter,
-       .detach_client  = lm78_detach_client,
+       .probe          = lm78_isa_probe,
+       .remove         = lm78_isa_remove,
 };
 
 
 /* 7 Voltages */
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+                      char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index]));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
+                          char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index]));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
+                          char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index]));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
+                         const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct lm78_data *data = dev_get_drvdata(dev);
        unsigned long val = simple_strtoul(buf, NULL, 10);
+       int nr = attr->index;
 
        mutex_lock(&data->update_lock);
        data->in_min[nr] = IN_TO_REG(val);
-       lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]);
+       lm78_write_value(data, LM78_REG_IN_MIN(nr), data->in_min[nr]);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-static ssize_t set_in_max(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
+                         const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct lm78_data *data = dev_get_drvdata(dev);
        unsigned long val = simple_strtoul(buf, NULL, 10);
+       int nr = attr->index;
 
        mutex_lock(&data->update_lock);
        data->in_max[nr] = IN_TO_REG(val);
-       lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]);
+       lm78_write_value(data, LM78_REG_IN_MAX(nr), data->in_max[nr]);
        mutex_unlock(&data->update_lock);
        return count;
 }
        
 #define show_in_offset(offset)                                 \
-static ssize_t                                                 \
-       show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)          \
-{                                                              \
-       return show_in(dev, buf, offset);                       \
-}                                                              \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO,                \
-               show_in##offset, NULL);                         \
-static ssize_t                                                 \
-       show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)   \
-{                                                              \
-       return show_in_min(dev, buf, offset);                   \
-}                                                              \
-static ssize_t                                                 \
-       show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)   \
-{                                                              \
-       return show_in_max(dev, buf, offset);                   \
-}                                                              \
-static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr,        \
-               const char *buf, size_t count)                  \
-{                                                              \
-       return set_in_min(dev, buf, count, offset);             \
-}                                                              \
-static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,        \
-               const char *buf, size_t count)                  \
-{                                                              \
-       return set_in_max(dev, buf, count, offset);             \
-}                                                              \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,                \
-               show_in##offset##_min, set_in##offset##_min);   \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,                \
-               show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,         \
+               show_in, NULL, offset);                         \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+               show_in_min, set_in_min, offset);               \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+               show_in_max, set_in_max, offset);
 
 show_in_offset(0);
 show_in_offset(1);
@@ -270,46 +257,49 @@ show_in_offset(5);
 show_in_offset(6);
 
 /* Temperature */
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+                        char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
 }
 
-static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *da,
+                             char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
 }
 
-static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
+                            const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct lm78_data *data = dev_get_drvdata(dev);
        long val = simple_strtol(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
        data->temp_over = TEMP_TO_REG(val);
-       lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over);
+       lm78_write_value(data, LM78_REG_TEMP_OVER, data->temp_over);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da,
+                             char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
 }
 
-static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
+                            const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct lm78_data *data = dev_get_drvdata(dev);
        long val = simple_strtol(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
        data->temp_hyst = TEMP_TO_REG(val);
-       lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst);
+       lm78_write_value(data, LM78_REG_TEMP_HYST, data->temp_hyst);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -321,49 +311,59 @@ static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
                show_temp_hyst, set_temp_hyst);
 
 /* 3 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *da,
+                       char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
+       int nr = attr->index;
        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
                DIV_FROM_REG(data->fan_div[nr])) );
 }
 
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
+                           char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
+       int nr = attr->index;
        return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
                DIV_FROM_REG(data->fan_div[nr])) );
 }
 
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
+                          const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct lm78_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
        data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-       lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
+       lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
+                           char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
 }
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
    least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-       size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
+                          const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct lm78_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        unsigned long val = simple_strtoul(buf, NULL, 10);
        unsigned long min;
        u8 reg;
@@ -378,13 +378,13 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
        case 4: data->fan_div[nr] = 2; break;
        case 8: data->fan_div[nr] = 3; break;
        default:
-               dev_err(&client->dev, "fan_div value %ld not "
+               dev_err(dev, "fan_div value %ld not "
                        "supported. Choose one of 1, 2, 4 or 8!\n", val);
                mutex_unlock(&data->update_lock);
                return -EINVAL;
        }
 
-       reg = lm78_read_value(client, LM78_REG_VID_FANDIV);
+       reg = lm78_read_value(data, LM78_REG_VID_FANDIV);
        switch (nr) {
        case 0:
                reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
@@ -393,63 +393,36 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
                reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
                break;
        }
-       lm78_write_value(client, LM78_REG_VID_FANDIV, reg);
+       lm78_write_value(data, LM78_REG_VID_FANDIV, reg);
 
        data->fan_min[nr] =
                FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-       lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
+       lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
        mutex_unlock(&data->update_lock);
 
        return count;
 }
 
-#define show_fan_offset(offset)                                                \
-static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)        \
-{                                                                      \
-       return show_fan(dev, buf, offset - 1);                          \
-}                                                                      \
-static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)  \
-{                                                                      \
-       return show_fan_min(dev, buf, offset - 1);                      \
-}                                                                      \
-static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)  \
-{                                                                      \
-       return show_fan_div(dev, buf, offset - 1);                      \
-}                                                                      \
-static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,              \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_fan_min(dev, buf, count, offset - 1);                \
-}                                                                      \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,               \
-               show_fan_##offset##_min, set_fan_##offset##_min);
-
-static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
-               size_t count)
-{
-       return set_fan_div(dev, buf, count, 0) ;
-}
-
-static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
-               size_t count)
-{
-       return set_fan_div(dev, buf, count, 1) ;
-}
+#define show_fan_offset(offset)                                \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,                \
+               show_fan, NULL, offset - 1);                    \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,        \
+               show_fan_min, set_fan_min, offset - 1);
 
 show_fan_offset(1);
 show_fan_offset(2);
 show_fan_offset(3);
 
 /* Fan 3 divisor is locked in H/W */
-static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
-               show_fan_1_div, set_fan_1_div);
-static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
-               show_fan_2_div, set_fan_2_div);
-static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+               show_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+               show_fan_div, set_fan_div, 1);
+static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2);
 
 /* VID */
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *da,
+                       char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
        return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82));
@@ -457,7 +430,8 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *da,
+                          char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
        return sprintf(buf, "%u\n", data->alarms);
@@ -475,45 +449,40 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm78_detect);
 }
 
-static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
-{
-       return lm78_detect(adapter, isa_address, -1);
-}
-
 static struct attribute *lm78_attributes[] = {
-       &dev_attr_in0_input.attr,
-       &dev_attr_in0_min.attr,
-       &dev_attr_in0_max.attr,
-       &dev_attr_in1_input.attr,
-       &dev_attr_in1_min.attr,
-       &dev_attr_in1_max.attr,
-       &dev_attr_in2_input.attr,
-       &dev_attr_in2_min.attr,
-       &dev_attr_in2_max.attr,
-       &dev_attr_in3_input.attr,
-       &dev_attr_in3_min.attr,
-       &dev_attr_in3_max.attr,
-       &dev_attr_in4_input.attr,
-       &dev_attr_in4_min.attr,
-       &dev_attr_in4_max.attr,
-       &dev_attr_in5_input.attr,
-       &dev_attr_in5_min.attr,
-       &dev_attr_in5_max.attr,
-       &dev_attr_in6_input.attr,
-       &dev_attr_in6_min.attr,
-       &dev_attr_in6_max.attr,
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_min.dev_attr.attr,
+       &sensor_dev_attr_in1_max.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in6_min.dev_attr.attr,
+       &sensor_dev_attr_in6_max.dev_attr.attr,
        &dev_attr_temp1_input.attr,
        &dev_attr_temp1_max.attr,
        &dev_attr_temp1_max_hyst.attr,
-       &dev_attr_fan1_input.attr,
-       &dev_attr_fan1_min.attr,
-       &dev_attr_fan1_div.attr,
-       &dev_attr_fan2_input.attr,
-       &dev_attr_fan2_min.attr,
-       &dev_attr_fan2_div.attr,
-       &dev_attr_fan3_input.attr,
-       &dev_attr_fan3_min.attr,
-       &dev_attr_fan3_div.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_min.dev_attr.attr,
+       &sensor_dev_attr_fan3_div.dev_attr.attr,
        &dev_attr_alarms.attr,
        &dev_attr_cpu0_vid.attr,
 
@@ -524,6 +493,17 @@ static const struct attribute_group lm78_group = {
        .attrs = lm78_attributes,
 };
 
+/* I2C devices get this name attribute automatically, but for ISA devices
+   we must create it by ourselves. */
+static ssize_t show_name(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
+{
+       struct lm78_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->client.name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 /* This function is called by i2c_probe */
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -531,54 +511,10 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        struct i2c_client *new_client;
        struct lm78_data *data;
        const char *client_name = "";
-       int is_isa = i2c_is_isa_adapter(adapter);
 
-       if (!is_isa &&
-           !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                err = -ENODEV;
-               goto ERROR0;
-       }
-
-       /* Reserve the ISA region */
-       if (is_isa)
-               if (!request_region(address, LM78_EXTENT,
-                                   lm78_isa_driver.driver.name)) {
-                       err = -EBUSY;
-                       goto ERROR0;
-               }
-
-       /* Probe whether there is anything available on this address. Already
-          done for SMBus clients */
-       if (kind < 0) {
-               if (is_isa) {
-
-#define REALLY_SLOW_IO
-                       /* We need the timeouts for at least some LM78-like
-                          chips. But only if we read 'undefined' registers. */
-                       i = inb_p(address + 1);
-                       if (inb_p(address + 2) != i) {
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-                       if (inb_p(address + 3) != i) {
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-                       if (inb_p(address + 7) != i) {
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-#undef REALLY_SLOW_IO
-
-                       /* Let's just hope nothing breaks here */
-                       i = inb_p(address + 5) & 0x7f;
-                       outb_p(~i & 0x7f, address + 5);
-                       if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
-                               outb_p(i, address + 5);
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-               }
+               goto ERROR1;
        }
 
        /* OK. For now, we presume we have a valid client. We now create the
@@ -591,22 +527,19 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        new_client = &data->client;
-       if (is_isa)
-               mutex_init(&data->lock);
        i2c_set_clientdata(new_client, data);
        new_client->addr = address;
        new_client->adapter = adapter;
-       new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
-       new_client->flags = 0;
+       new_client->driver = &lm78_driver;
 
        /* Now, we do the remaining detection. */
        if (kind < 0) {
-               if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80) {
+               if (lm78_read_value(data, LM78_REG_CONFIG) & 0x80) {
                        err = -ENODEV;
                        goto ERROR2;
                }
-               if (!is_isa && (lm78_read_value(
-                               new_client, LM78_REG_I2C_ADDR) != address)) {
+               if (lm78_read_value(data, LM78_REG_I2C_ADDR) !=
+                   address) {
                        err = -ENODEV;
                        goto ERROR2;
                }
@@ -614,7 +547,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Determine the chip type. */
        if (kind <= 0) {
-               i = lm78_read_value(new_client, LM78_REG_CHIPID);
+               i = lm78_read_value(data, LM78_REG_CHIPID);
                if (i == 0x00 || i == 0x20      /* LM78 */
                 || i == 0x40)                  /* LM78-J */
                        kind = lm78;
@@ -641,21 +574,12 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
        data->type = kind;
 
-       data->valid = 0;
-       mutex_init(&data->update_lock);
-
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(new_client)))
                goto ERROR2;
 
        /* Initialize the LM78 chip */
-       lm78_init_client(new_client);
-
-       /* A few vars need to be filled upon startup */
-       for (i = 0; i < 3; i++) {
-               data->fan_min[i] = lm78_read_value(new_client,
-                                       LM78_REG_FAN_MIN(i));
-       }
+       lm78_init_device(data);
 
        /* Register sysfs hooks */
        if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group)))
@@ -676,9 +600,6 @@ ERROR3:
 ERROR2:
        kfree(data);
 ERROR1:
-       if (is_isa)
-               release_region(address, LM78_EXTENT);
-ERROR0:
        return err;
 }
 
@@ -693,9 +614,77 @@ static int lm78_detach_client(struct i2c_client *client)
        if ((err = i2c_detach_client(client)))
                return err;
 
-       if(i2c_is_isa_client(client))
-               release_region(client->addr, LM78_EXTENT);
+       kfree(data);
+
+       return 0;
+}
+
+static int __devinit lm78_isa_probe(struct platform_device *pdev)
+{
+       int err;
+       struct lm78_data *data;
+       struct resource *res;
+       const char *name;
+
+       /* Reserve the ISA region */
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, LM78_EXTENT, "lm78")) {
+               err = -EBUSY;
+               goto exit;
+       }
+
+       if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit_release_region;
+       }
+       mutex_init(&data->lock);
+       data->client.addr = res->start;
+       i2c_set_clientdata(&data->client, data);
+       platform_set_drvdata(pdev, data);
+
+       if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
+               data->type = lm79;
+               name = "lm79";
+       } else {
+               data->type = lm78;
+               name = "lm78";
+       }
+       strlcpy(data->client.name, name, I2C_NAME_SIZE);
+
+       /* Initialize the LM78 chip */
+       lm78_init_device(data);
+
+       /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
+        || (err = device_create_file(&pdev->dev, &dev_attr_name)))
+               goto exit_remove_files;
+
+       data->class_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
+       }
+
+       return 0;
+
+ exit_remove_files:
+       sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       kfree(data);
+ exit_release_region:
+       release_region(res->start, LM78_EXTENT);
+ exit:
+       return err;
+}
+
+static int __devexit lm78_isa_remove(struct platform_device *pdev)
+{
+       struct lm78_data *data = platform_get_drvdata(pdev);
 
+       hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       release_region(data->client.addr, LM78_EXTENT);
        kfree(data);
 
        return 0;
@@ -706,11 +695,12 @@ static int lm78_detach_client(struct i2c_client *client)
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the LM78 access and should not be necessary.  */
-static int lm78_read_value(struct i2c_client *client, u8 reg)
+static int lm78_read_value(struct lm78_data *data, u8 reg)
 {
-       int res;
-       if (i2c_is_isa_client(client)) {
-               struct lm78_data *data = i2c_get_clientdata(client);
+       struct i2c_client *client = &data->client;
+
+       if (!client->driver) { /* ISA device */
+               int res;
                mutex_lock(&data->lock);
                outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
                res = inb_p(client->addr + LM78_DATA_REG_OFFSET);
@@ -727,10 +717,11 @@ static int lm78_read_value(struct i2c_client *client, u8 reg)
    would slow down the LM78 access and should not be necessary. 
    There are some ugly typecasts here, but the good new is - they should
    nowhere else be necessary! */
-static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
+static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
 {
-       if (i2c_is_isa_client(client)) {
-               struct lm78_data *data = i2c_get_clientdata(client);
+       struct i2c_client *client = &data->client;
+
+       if (!client->driver) { /* ISA device */
                mutex_lock(&data->lock);
                outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
                outb_p(value, client->addr + LM78_DATA_REG_OFFSET);
@@ -740,20 +731,29 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
                return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static void lm78_init_client(struct i2c_client *client)
+static void lm78_init_device(struct lm78_data *data)
 {
-       u8 config = lm78_read_value(client, LM78_REG_CONFIG);
+       u8 config;
+       int i;
 
        /* Start monitoring */
-       if (!(config & 0x01))
-               lm78_write_value(client, LM78_REG_CONFIG,
+       config = lm78_read_value(data, LM78_REG_CONFIG);
+       if ((config & 0x09) != 0x01)
+               lm78_write_value(data, LM78_REG_CONFIG,
                                 (config & 0xf7) | 0x01);
+
+       /* A few vars need to be filled upon startup */
+       for (i = 0; i < 3; i++) {
+               data->fan_min[i] = lm78_read_value(data,
+                                       LM78_REG_FAN_MIN(i));
+       }
+
+       mutex_init(&data->update_lock);
 }
 
 static struct lm78_data *lm78_update_device(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm78_data *data = i2c_get_clientdata(client);
+       struct lm78_data *data = dev_get_drvdata(dev);
        int i;
 
        mutex_lock(&data->update_lock);
@@ -761,39 +761,39 @@ static struct lm78_data *lm78_update_device(struct device *dev)
        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
            || !data->valid) {
 
-               dev_dbg(&client->dev, "Starting lm78 update\n");
+               dev_dbg(dev, "Starting lm78 update\n");
 
                for (i = 0; i <= 6; i++) {
                        data->in[i] =
-                           lm78_read_value(client, LM78_REG_IN(i));
+                           lm78_read_value(data, LM78_REG_IN(i));
                        data->in_min[i] =
-                           lm78_read_value(client, LM78_REG_IN_MIN(i));
+                           lm78_read_value(data, LM78_REG_IN_MIN(i));
                        data->in_max[i] =
-                           lm78_read_value(client, LM78_REG_IN_MAX(i));
+                           lm78_read_value(data, LM78_REG_IN_MAX(i));
                }
                for (i = 0; i < 3; i++) {
                        data->fan[i] =
-                           lm78_read_value(client, LM78_REG_FAN(i));
+                           lm78_read_value(data, LM78_REG_FAN(i));
                        data->fan_min[i] =
-                           lm78_read_value(client, LM78_REG_FAN_MIN(i));
+                           lm78_read_value(data, LM78_REG_FAN_MIN(i));
                }
-               data->temp = lm78_read_value(client, LM78_REG_TEMP);
+               data->temp = lm78_read_value(data, LM78_REG_TEMP);
                data->temp_over =
-                   lm78_read_value(client, LM78_REG_TEMP_OVER);
+                   lm78_read_value(data, LM78_REG_TEMP_OVER);
                data->temp_hyst =
-                   lm78_read_value(client, LM78_REG_TEMP_HYST);
-               i = lm78_read_value(client, LM78_REG_VID_FANDIV);
+                   lm78_read_value(data, LM78_REG_TEMP_HYST);
+               i = lm78_read_value(data, LM78_REG_VID_FANDIV);
                data->vid = i & 0x0f;
                if (data->type == lm79)
                        data->vid |=
-                           (lm78_read_value(client, LM78_REG_CHIPID) &
+                           (lm78_read_value(data, LM78_REG_CHIPID) &
                             0x01) << 4;
                else
                        data->vid |= 0x10;
                data->fan_div[0] = (i >> 4) & 0x03;
                data->fan_div[1] = i >> 6;
-               data->alarms = lm78_read_value(client, LM78_REG_ALARM1) +
-                   (lm78_read_value(client, LM78_REG_ALARM2) << 8);
+               data->alarms = lm78_read_value(data, LM78_REG_ALARM1) +
+                   (lm78_read_value(data, LM78_REG_ALARM2) << 8);
                data->last_updated = jiffies;
                data->valid = 1;
 
@@ -805,26 +805,154 @@ static struct lm78_data *lm78_update_device(struct device *dev)
        return data;
 }
 
+/* return 1 if a supported chip is found, 0 otherwise */
+static int __init lm78_isa_found(unsigned short address)
+{
+       int val, save, found = 0;
+
+       if (!request_region(address, LM78_EXTENT, "lm78"))
+               return 0;
+
+#define REALLY_SLOW_IO
+       /* We need the timeouts for at least some LM78-like
+          chips. But only if we read 'undefined' registers. */
+       val = inb_p(address + 1);
+       if (inb_p(address + 2) != val
+        || inb_p(address + 3) != val
+        || inb_p(address + 7) != val)
+               goto release;
+#undef REALLY_SLOW_IO
+
+       /* We should be able to change the 7 LSB of the address port. The
+          MSB (busy flag) should be clear initially, set after the write. */
+       save = inb_p(address + LM78_ADDR_REG_OFFSET);
+       if (save & 0x80)
+               goto release;
+       val = ~save & 0x7f;
+       outb_p(val, address + LM78_ADDR_REG_OFFSET);
+       if (inb_p(address + LM78_ADDR_REG_OFFSET) != (val | 0x80)) {
+               outb_p(save, address + LM78_ADDR_REG_OFFSET);
+               goto release;
+       }
+
+       /* We found a device, now see if it could be an LM78 */
+       outb_p(LM78_REG_CONFIG, address + LM78_ADDR_REG_OFFSET);
+       val = inb_p(address + LM78_DATA_REG_OFFSET);
+       if (val & 0x80)
+               goto release;
+       outb_p(LM78_REG_I2C_ADDR, address + LM78_ADDR_REG_OFFSET);
+       val = inb_p(address + LM78_DATA_REG_OFFSET);
+       if (val < 0x03 || val > 0x77)   /* Not a valid I2C address */
+               goto release;
+
+       /* The busy flag should be clear again */
+       if (inb_p(address + LM78_ADDR_REG_OFFSET) & 0x80)
+               goto release;
+
+       /* Explicitly prevent the misdetection of Winbond chips */
+       outb_p(0x4f, address + LM78_ADDR_REG_OFFSET);
+       val = inb_p(address + LM78_DATA_REG_OFFSET);
+       if (val == 0xa3 || val == 0x5c)
+               goto release;
+
+       /* Explicitly prevent the misdetection of ITE chips */
+       outb_p(0x58, address + LM78_ADDR_REG_OFFSET);
+       val = inb_p(address + LM78_DATA_REG_OFFSET);
+       if (val == 0x90)
+               goto release;
+
+       /* Determine the chip type */
+       outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET);
+       val = inb_p(address + LM78_DATA_REG_OFFSET);
+       if (val == 0x00                 /* LM78 */
+        || val == 0x40                 /* LM78-J */
+        || (val & 0xfe) == 0xc0)       /* LM79 */
+               found = 1;
+
+       if (found)
+               pr_info("lm78: Found an %s chip at %#x\n",
+                       val & 0x80 ? "LM79" : "LM78", (int)address);
+
+ release:
+       release_region(address, LM78_EXTENT);
+       return found;
+}
+
+static int __init lm78_isa_device_add(unsigned short address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + LM78_EXTENT,
+               .name   = "lm78",
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc("lm78", address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR "lm78: Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR "lm78: Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR "lm78: Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+ exit_device_put:
+       platform_device_put(pdev);
+ exit:
+       pdev = NULL;
+       return err;
+}
+
 static int __init sm_lm78_init(void)
 {
        int res;
 
        res = i2c_add_driver(&lm78_driver);
        if (res)
-               return res;
+               goto exit;
 
-       /* Don't exit if this one fails, we still want the I2C variants
-          to work! */
-       if (i2c_isa_add_driver(&lm78_isa_driver))
-               isa_address = 0;
+       if (lm78_isa_found(isa_address)) {
+               res = platform_driver_register(&lm78_isa_driver);
+               if (res)
+                       goto exit_unreg_i2c_driver;
+
+               /* Sets global pdev as a side effect */
+               res = lm78_isa_device_add(isa_address);
+               if (res)
+                       goto exit_unreg_isa_driver;
+       }
 
        return 0;
+
+ exit_unreg_isa_driver:
+       platform_driver_unregister(&lm78_isa_driver);
+ exit_unreg_i2c_driver:
+       i2c_del_driver(&lm78_driver);
+ exit:
+       return res;
 }
 
 static void __exit sm_lm78_exit(void)
 {
-       if (isa_address)
-               i2c_isa_del_driver(&lm78_isa_driver);
+       if (pdev) {
+               platform_device_unregister(pdev);
+               platform_driver_unregister(&lm78_isa_driver);
+       }
        i2c_del_driver(&lm78_driver);
 }
 
index 3ce825489e349c0c106646356397aa87eae69531..988ae1c4aada69ebb2f9315258ac1b4ee878f65b 100644 (file)
@@ -747,6 +747,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        if (!(data->channel & CHAN_NO_VID)) {
+               data->vrm = vid_which_vrm();
                if ((err = device_create_file(&new_client->dev,
                                        &dev_attr_cpu0_vid))
                 || (err = device_create_file(&new_client->dev,
@@ -779,7 +780,6 @@ static void lm87_init_client(struct i2c_client *client)
        u8 config;
 
        data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
-       data->vrm = vid_which_vrm();
 
        config = lm87_read_value(client, LM87_REG_CONFIG);
        if (!(config & 0x01)) {
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
new file mode 100644 (file)
index 0000000..8415664
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+ * max6650.c - Part of lm_sensors, Linux kernel modules for hardware
+ *             monitoring.
+ *
+ * (C) 2007 by Hans J. Koch <hjk@linutronix.de>
+ *
+ * based on code written by John Morris <john.morris@spirentcom.com>
+ * Copyright (c) 2003 Spirent Communications
+ * and Claus Gindhart <claus.gindhart@kontron.com>
+ *
+ * This module has only been tested with the MAX6650 chip. It should
+ * also work with the MAX6651. It does not distinguish max6650 and max6651
+ * chips.
+ *
+ * Tha datasheet was last seen at:
+ *
+ *        http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/*
+ * Addresses to scan. There are four disjoint possibilities, by pin config.
+ */
+
+static unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, I2C_CLIENT_END};
+
+/*
+ * Insmod parameters
+ */
+
+/* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */
+static int fan_voltage;
+/* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */
+static int prescaler;
+/* clock: The clock frequency of the chip the driver should assume */
+static int clock = 254000;
+
+module_param(fan_voltage, int, S_IRUGO);
+module_param(prescaler, int, S_IRUGO);
+module_param(clock, int, S_IRUGO);
+
+I2C_CLIENT_INSMOD_1(max6650);
+
+/*
+ * MAX 6650/6651 registers
+ */
+
+#define MAX6650_REG_SPEED      0x00
+#define MAX6650_REG_CONFIG     0x02
+#define MAX6650_REG_GPIO_DEF   0x04
+#define MAX6650_REG_DAC                0x06
+#define MAX6650_REG_ALARM_EN   0x08
+#define MAX6650_REG_ALARM      0x0A
+#define MAX6650_REG_TACH0      0x0C
+#define MAX6650_REG_TACH1      0x0E
+#define MAX6650_REG_TACH2      0x10
+#define MAX6650_REG_TACH3      0x12
+#define MAX6650_REG_GPIO_STAT  0x14
+#define MAX6650_REG_COUNT      0x16
+
+/*
+ * Config register bits
+ */
+
+#define MAX6650_CFG_V12                        0x08
+#define MAX6650_CFG_PRESCALER_MASK     0x07
+#define MAX6650_CFG_PRESCALER_2                0x01
+#define MAX6650_CFG_PRESCALER_4                0x02
+#define MAX6650_CFG_PRESCALER_8                0x03
+#define MAX6650_CFG_PRESCALER_16       0x04
+#define MAX6650_CFG_MODE_MASK          0x30
+#define MAX6650_CFG_MODE_ON            0x00
+#define MAX6650_CFG_MODE_OFF           0x10
+#define MAX6650_CFG_MODE_CLOSED_LOOP   0x20
+#define MAX6650_CFG_MODE_OPEN_LOOP     0x30
+#define MAX6650_COUNT_MASK             0x03
+
+/* Minimum and maximum values of the FAN-RPM */
+#define FAN_RPM_MIN 240
+#define FAN_RPM_MAX 30000
+
+#define DIV_FROM_REG(reg) (1 << (reg & 7))
+
+static int max6650_attach_adapter(struct i2c_adapter *adapter);
+static int max6650_detect(struct i2c_adapter *adapter, int address, int kind);
+static int max6650_init_client(struct i2c_client *client);
+static int max6650_detach_client(struct i2c_client *client);
+static struct max6650_data *max6650_update_device(struct device *dev);
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static struct i2c_driver max6650_driver = {
+       .driver = {
+               .name   = "max6650",
+       },
+       .attach_adapter = max6650_attach_adapter,
+       .detach_client  = max6650_detach_client,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+
+struct max6650_data
+{
+       struct i2c_client client;
+       struct class_device *class_dev;
+       struct mutex update_lock;
+       char valid; /* zero until following fields are valid */
+       unsigned long last_updated; /* in jiffies */
+
+       /* register values */
+       u8 speed;
+       u8 config;
+       u8 tach[4];
+       u8 count;
+       u8 dac;
+};
+
+static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
+                      char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct max6650_data *data = max6650_update_device(dev);
+       int rpm;
+
+       /*
+       * Calculation details:
+       *
+       * Each tachometer counts over an interval given by the "count"
+       * register (0.25, 0.5, 1 or 2 seconds). This module assumes
+       * that the fans produce two pulses per revolution (this seems
+       * to be the most common).
+       */
+
+       rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count));
+       return sprintf(buf, "%d\n", rpm);
+}
+
+/*
+ * Set the fan speed to the specified RPM (or read back the RPM setting).
+ * This works in closed loop mode only. Use pwm1 for open loop speed setting.
+ *
+ * The MAX6650/1 will automatically control fan speed when in closed loop
+ * mode.
+ *
+ * Assumptions:
+ *
+ * 1) The MAX6650/1 internal 254kHz clock frequency is set correctly. Use
+ *    the clock module parameter if you need to fine tune this.
+ *
+ * 2) The prescaler (low three bits of the config register) has already
+ *    been set to an appropriate value. Use the prescaler module parameter
+ *    if your BIOS doesn't initialize the chip properly.
+ *
+ * The relevant equations are given on pages 21 and 22 of the datasheet.
+ *
+ * From the datasheet, the relevant equation when in regulation is:
+ *
+ *    [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE
+ *
+ * where:
+ *
+ *    fCLK is the oscillator frequency (either the 254kHz internal
+ *         oscillator or the externally applied clock)
+ *
+ *    KTACH is the value in the speed register
+ *
+ *    FanSpeed is the speed of the fan in rps
+ *
+ *    KSCALE is the prescaler value (1, 2, 4, 8, or 16)
+ *
+ * When reading, we need to solve for FanSpeed. When writing, we need to
+ * solve for KTACH.
+ *
+ * Note: this tachometer is completely separate from the tachometers
+ * used to measure the fan speeds. Only one fan's speed (fan1) is
+ * controlled.
+ */
+
+static ssize_t get_target(struct device *dev, struct device_attribute *devattr,
+                        char *buf)
+{
+       struct max6650_data *data = max6650_update_device(dev);
+       int kscale, ktach, rpm;
+
+       /*
+       * Use the datasheet equation:
+       *
+       *    FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)]
+       *
+       * then multiply by 60 to give rpm.
+       */
+
+       kscale = DIV_FROM_REG(data->config);
+       ktach = data->speed;
+       rpm = 60 * kscale * clock / (256 * (ktach + 1));
+       return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
+                        const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int rpm = simple_strtoul(buf, NULL, 10);
+       int kscale, ktach;
+
+       rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
+
+       /*
+       * Divide the required speed by 60 to get from rpm to rps, then
+       * use the datasheet equation:
+       *
+       *     KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1
+       */
+
+       mutex_lock(&data->update_lock);
+
+       kscale = DIV_FROM_REG(data->config);
+       ktach = ((clock * kscale) / (256 * rpm / 60)) - 1;
+       if (ktach < 0)
+               ktach = 0;
+       if (ktach > 255)
+               ktach = 255;
+       data->speed = ktach;
+
+       i2c_smbus_write_byte_data(client, MAX6650_REG_SPEED, data->speed);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/*
+ * Get/set the fan speed in open loop mode using pwm1 sysfs file.
+ * Speed is given as a relative value from 0 to 255, where 255 is maximum
+ * speed. Note that this is done by writing directly to the chip's DAC,
+ * it won't change the closed loop speed set by fan1_target.
+ * Also note that due to rounding errors it is possible that you don't read
+ * back exactly the value you have set.
+ */
+
+static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr,
+                      char *buf)
+{
+       int pwm;
+       struct max6650_data *data = max6650_update_device(dev);
+
+       /* Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans.
+          Lower DAC values mean higher speeds. */
+       if (data->config & MAX6650_CFG_V12)
+               pwm = 255 - (255 * (int)data->dac)/180;
+       else
+               pwm = 255 - (255 * (int)data->dac)/76;
+
+       if (pwm < 0)
+               pwm = 0;
+
+       return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int pwm = simple_strtoul(buf, NULL, 10);
+
+       pwm = SENSORS_LIMIT(pwm, 0, 255);
+
+       mutex_lock(&data->update_lock);
+
+       if (data->config & MAX6650_CFG_V12)
+               data->dac = 180 - (180 * pwm)/255;
+       else
+               data->dac = 76 - (76 * pwm)/255;
+
+       i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/*
+ * Get/Set controller mode:
+ * Possible values:
+ * 0 = Fan always on
+ * 1 = Open loop, Voltage is set according to speed, not regulated.
+ * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer
+ */
+
+static ssize_t get_enable(struct device *dev, struct device_attribute *devattr,
+                         char *buf)
+{
+       struct max6650_data *data = max6650_update_device(dev);
+       int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4;
+       int sysfs_modes[4] = {0, 1, 2, 1};
+
+       return sprintf(buf, "%d\n", sysfs_modes[mode]);
+}
+
+static ssize_t set_enable(struct device *dev, struct device_attribute *devattr,
+                         const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int mode = simple_strtoul(buf, NULL, 10);
+       int max6650_modes[3] = {0, 3, 2};
+
+       if ((mode < 0)||(mode > 2)) {
+               dev_err(&client->dev,
+                       "illegal value for pwm1_enable (%d)\n", mode);
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->update_lock);
+
+       data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
+       data->config = (data->config & ~MAX6650_CFG_MODE_MASK)
+                      | (max6650_modes[mode] << 4);
+
+       i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, data->config);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/*
+ * Read/write functions for fan1_div sysfs file. The MAX6650 has no such
+ * divider. We handle this by converting between divider and counttime:
+ *
+ * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, or 3
+ *
+ * Lower values of k allow to connect a faster fan without the risk of
+ * counter overflow. The price is lower resolution. You can also set counttime
+ * using the module parameter. Note that the module parameter "prescaler" also
+ * influences the behaviour. Unfortunately, there's no sysfs attribute
+ * defined for that. See the data sheet for details.
+ */
+
+static ssize_t get_div(struct device *dev, struct device_attribute *devattr,
+                      char *buf)
+{
+       struct max6650_data *data = max6650_update_device(dev);
+
+       return sprintf(buf, "%d\n", DIV_FROM_REG(data->count));
+}
+
+static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
+                      const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int div = simple_strtoul(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+       switch (div) {
+       case 1:
+               data->count = 0;
+               break;
+       case 2:
+               data->count = 1;
+               break;
+       case 4:
+               data->count = 2;
+               break;
+       case 8:
+               data->count = 3;
+               break;
+       default:
+               dev_err(&client->dev,
+                       "illegal value for fan divider (%d)\n", div);
+               return -EINVAL;
+       }
+
+       i2c_smbus_write_byte_data(client, MAX6650_REG_COUNT, data->count);
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3);
+static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target);
+static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div);
+static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable);
+static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm);
+
+
+static struct attribute *max6650_attrs[] = {
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+       &dev_attr_fan1_target.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_pwm1_enable.attr,
+       &dev_attr_pwm1.attr,
+       NULL
+};
+
+static struct attribute_group max6650_attr_grp = {
+       .attrs = max6650_attrs,
+};
+
+/*
+ * Real code
+ */
+
+static int max6650_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON)) {
+               dev_dbg(&adapter->dev,
+                       "FATAL: max6650_attach_adapter class HWMON not set\n");
+               return 0;
+       }
+
+       return i2c_probe(adapter, &addr_data, max6650_detect);
+}
+
+/*
+ * The following function does more than just detection. If detection
+ * succeeds, it also registers the new chip.
+ */
+
+static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct max6650_data *data;
+       int err = -ENODEV;
+
+       dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind);
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support "
+                                       "byte read mode, skipping.\n");
+               return 0;
+       }
+
+       if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
+               dev_err(&adapter->dev, "max6650: out of memory.\n");
+               return -ENOMEM;
+       }
+
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &max6650_driver;
+
+       /*
+        * Now we do the remaining detection. A negative kind means that
+        * the driver was loaded with no force parameter (default), so we
+        * must both detect and identify the chip (actually there is only
+        * one possible kind of chip for now, max6650). A zero kind means that
+        * the driver was loaded with the force parameter, the detection
+        * step shall be skipped. A positive kind means that the driver
+        * was loaded with the force parameter and a given kind of chip is
+        * requested, so both the detection and the identification steps
+        * are skipped.
+        *
+        * Currently I can find no way to distinguish between a MAX6650 and
+        * a MAX6651. This driver has only been tried on the former.
+        */
+
+       if ((kind < 0) &&
+          (  (i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0)
+           ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0)
+           ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0)
+           ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0)
+           ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) {
+               dev_dbg(&adapter->dev,
+                       "max6650: detection failed at 0x%02x.\n", address);
+               goto err_free;
+       }
+
+       dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address);
+
+       strlcpy(client->name, "max6650", I2C_NAME_SIZE);
+       mutex_init(&data->update_lock);
+
+       if ((err = i2c_attach_client(client))) {
+               dev_err(&adapter->dev, "max6650: failed to attach client.\n");
+               goto err_free;
+       }
+
+       /*
+        * Initialize the max6650 chip
+        */
+       if (max6650_init_client(client))
+               goto err_detach;
+
+       err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp);
+       if (err)
+               goto err_detach;
+
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (!IS_ERR(data->class_dev))
+               return 0;
+
+       err = PTR_ERR(data->class_dev);
+       dev_err(&client->dev, "error registering hwmon device.\n");
+       sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
+err_detach:
+       i2c_detach_client(client);
+err_free:
+       kfree(data);
+       return err;
+}
+
+static int max6650_detach_client(struct i2c_client *client)
+{
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int err;
+
+       sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
+       hwmon_device_unregister(data->class_dev);
+       err = i2c_detach_client(client);
+       if (!err)
+               kfree(data);
+       return err;
+}
+
+static int max6650_init_client(struct i2c_client *client)
+{
+       struct max6650_data *data = i2c_get_clientdata(client);
+       int config;
+       int err = -EIO;
+
+       config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
+
+       if (config < 0) {
+               dev_err(&client->dev, "Error reading config, aborting.\n");
+               return err;
+       }
+
+       switch (fan_voltage) {
+               case 0:
+                       break;
+               case 5:
+                       config &= ~MAX6650_CFG_V12;
+                       break;
+               case 12:
+                       config |= MAX6650_CFG_V12;
+                       break;
+               default:
+                       dev_err(&client->dev,
+                               "illegal value for fan_voltage (%d)\n",
+                               fan_voltage);
+       }
+
+       dev_info(&client->dev, "Fan voltage is set to %dV.\n",
+                (config & MAX6650_CFG_V12) ? 12 : 5);
+
+       switch (prescaler) {
+               case 0:
+                       break;
+               case 1:
+                       config &= ~MAX6650_CFG_PRESCALER_MASK;
+                       break;
+               case 2:
+                       config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+                                | MAX6650_CFG_PRESCALER_2;
+                       break;
+               case  4:
+                       config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+                                | MAX6650_CFG_PRESCALER_4;
+                       break;
+               case  8:
+                       config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+                                | MAX6650_CFG_PRESCALER_8;
+                       break;
+               case 16:
+                       config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+                                | MAX6650_CFG_PRESCALER_16;
+                       break;
+               default:
+                       dev_err(&client->dev,
+                               "illegal value for prescaler (%d)\n",
+                               prescaler);
+       }
+
+       dev_info(&client->dev, "Prescaler is set to %d.\n",
+                1 << (config & MAX6650_CFG_PRESCALER_MASK));
+
+       /* If mode is set to "full off", we change it to "open loop" and
+        * set DAC to 255, which has the same effect. We do this because
+        * there's no "full off" mode defined in hwmon specifcations.
+        */
+
+       if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
+               dev_dbg(&client->dev, "Change mode to open loop, full off.\n");
+               config = (config & ~MAX6650_CFG_MODE_MASK)
+                        | MAX6650_CFG_MODE_OPEN_LOOP;
+               if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) {
+                       dev_err(&client->dev, "DAC write error, aborting.\n");
+                       return err;
+               }
+       }
+
+       if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) {
+               dev_err(&client->dev, "Config write error, aborting.\n");
+               return err;
+       }
+
+       data->config = config;
+       data->count = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT);
+
+       return 0;
+}
+
+static const u8 tach_reg[] = {
+       MAX6650_REG_TACH0,
+       MAX6650_REG_TACH1,
+       MAX6650_REG_TACH2,
+       MAX6650_REG_TACH3,
+};
+
+static struct max6650_data *max6650_update_device(struct device *dev)
+{
+       int i;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max6650_data *data = i2c_get_clientdata(client);
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+               data->speed = i2c_smbus_read_byte_data(client,
+                                                      MAX6650_REG_SPEED);
+               data->config = i2c_smbus_read_byte_data(client,
+                                                       MAX6650_REG_CONFIG);
+               for (i = 0; i < 4; i++) {
+                       data->tach[i] = i2c_smbus_read_byte_data(client,
+                                                                tach_reg[i]);
+               }
+               data->count = i2c_smbus_read_byte_data(client,
+                                                       MAX6650_REG_COUNT);
+               data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+       return data;
+}
+
+static int __init sensors_max6650_init(void)
+{
+       return i2c_add_driver(&max6650_driver);
+}
+
+static void __exit sensors_max6650_exit(void)
+{
+       i2c_del_driver(&max6650_driver);
+}
+
+MODULE_AUTHOR("Hans J. Koch");
+MODULE_DESCRIPTION("MAX6650 sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_max6650_init);
+module_exit(sensors_max6650_exit);
index affa21a5ccfd2372cc1abfcb52caa75ecbae62bb..29354fa26f81e3578b7db2dd6b4cc188f4fafff8 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/ioport.h>
 #include <asm/io.h>
 
 static struct platform_device *pdev;
@@ -429,6 +430,12 @@ static int __devinit pc87427_probe(struct platform_device *pdev)
        /* This will need to be revisited when we add support for
           temperature and voltage monitoring. */
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+               err = -EBUSY;
+               dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
+                       (unsigned long)res->start, (unsigned long)res->end);
+               goto exit_kfree;
+       }
        data->address[0] = res->start;
 
        mutex_init(&data->lock);
@@ -438,7 +445,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev)
 
        /* Register sysfs hooks */
        if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
-               goto exit_kfree;
+               goto exit_release_region;
        for (i = 0; i < 8; i++) {
                if (!(data->fan_enabled & (1 << i)))
                        continue;
@@ -462,6 +469,8 @@ exit_remove_files:
                        continue;
                sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
        }
+exit_release_region:
+       release_region(res->start, res->end - res->start + 1);
 exit_kfree:
        platform_set_drvdata(pdev, NULL);
        kfree(data);
@@ -472,6 +481,7 @@ exit:
 static int __devexit pc87427_remove(struct platform_device *pdev)
 {
        struct pc87427_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
        int i;
 
        platform_set_drvdata(pdev, NULL);
@@ -484,6 +494,9 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
        }
        kfree(data);
 
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, res->end - res->start + 1);
+
        return 0;
 }
 
index 72b0e2d8650ca1df9b5297190e28837ba5296858..943abbd95ab57eb50cb50f3bccbe6318eafb9256 100644 (file)
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
 
-/* Address is autodetected, there is no default value */
-static unsigned short address;
+static struct platform_device *pdev;
+
+#define DRVNAME "smsc47b397"
 
 /* Super-I/0 registers and commands */
 
@@ -91,7 +92,8 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
 #define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr))
 
 struct smsc47b397_data {
-       struct i2c_client client;
+       unsigned short addr;
+       const char *name;
        struct class_device *class_dev;
        struct mutex lock;
 
@@ -104,45 +106,43 @@ struct smsc47b397_data {
        u8 temp[4];
 };
 
-static int smsc47b397_read_value(struct i2c_client *client, u8 reg)
+static int smsc47b397_read_value(struct smsc47b397_data* data, u8 reg)
 {
-       struct smsc47b397_data *data = i2c_get_clientdata(client);
        int res;
 
        mutex_lock(&data->lock);
-       outb(reg, client->addr);
-       res = inb_p(client->addr + 1);
+       outb(reg, data->addr);
+       res = inb_p(data->addr + 1);
        mutex_unlock(&data->lock);
        return res;
 }
 
 static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47b397_data *data = i2c_get_clientdata(client);
+       struct smsc47b397_data *data = dev_get_drvdata(dev);
        int i;
 
        mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-               dev_dbg(&client->dev, "starting device update...\n");
+               dev_dbg(dev, "starting device update...\n");
 
                /* 4 temperature inputs, 4 fan inputs */
                for (i = 0; i < 4; i++) {
-                       data->temp[i] = smsc47b397_read_value(client,
+                       data->temp[i] = smsc47b397_read_value(data,
                                        SMSC47B397_REG_TEMP(i));
 
                        /* must read LSB first */
-                       data->fan[i]  = smsc47b397_read_value(client,
+                       data->fan[i]  = smsc47b397_read_value(data,
                                        SMSC47B397_REG_FAN_LSB(i));
-                       data->fan[i] |= smsc47b397_read_value(client,
+                       data->fan[i] |= smsc47b397_read_value(data,
                                        SMSC47B397_REG_FAN_MSB(i)) << 8;
                }
 
                data->last_updated = jiffies;
                data->valid = 1;
 
-               dev_dbg(&client->dev, "... device update complete\n");
+               dev_dbg(dev, "... device update complete\n");
        }
 
        mutex_unlock(&data->update_lock);
@@ -157,24 +157,18 @@ static int temp_from_reg(u8 reg)
        return (s8)reg * 1000;
 }
 
-/* 0 <= nr <= 3 */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47b397_data *data = smsc47b397_update_device(dev);
-       return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr]));
+       return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index]));
 }
 
-#define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_temp(dev, buf, num-1); \
-} \
-static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL)
-
-sysfs_temp(1);
-sysfs_temp(2);
-sysfs_temp(3);
-sysfs_temp(4);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
 
 /* FAN: 1 RPM/bit
    REG: count of 90kHz pulses / revolution */
@@ -183,35 +177,37 @@ static int fan_from_reg(u16 reg)
        return 90000 * 60 / reg;
 }
 
-/* 0 <= nr <= 3 */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute
+                       *devattr, char *buf)
 {
-        struct smsc47b397_data *data = smsc47b397_update_device(dev);
-        return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr]));
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct smsc47b397_data *data = smsc47b397_update_device(dev);
+       return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index]));
 }
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
 
-#define sysfs_fan(num) \
-static ssize_t show_fan##num(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_fan(dev, buf, num-1); \
-} \
-static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL)
-
-sysfs_fan(1);
-sysfs_fan(2);
-sysfs_fan(3);
-sysfs_fan(4);
+static ssize_t show_name(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
+{
+       struct smsc47b397_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static struct attribute *smsc47b397_attributes[] = {
-       &dev_attr_temp1_input.attr,
-       &dev_attr_temp2_input.attr,
-       &dev_attr_temp3_input.attr,
-       &dev_attr_temp4_input.attr,
-       &dev_attr_fan1_input.attr,
-       &dev_attr_fan2_input.attr,
-       &dev_attr_fan3_input.attr,
-       &dev_attr_fan4_input.attr,
-
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+
+       &dev_attr_name.attr,
        NULL
 };
 
@@ -219,44 +215,44 @@ static const struct attribute_group smsc47b397_group = {
        .attrs = smsc47b397_attributes,
 };
 
-static int smsc47b397_detach_client(struct i2c_client *client)
+static int __devexit smsc47b397_remove(struct platform_device *pdev)
 {
-       struct smsc47b397_data *data = i2c_get_clientdata(client);
-       int err;
+       struct smsc47b397_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
 
        hwmon_device_unregister(data->class_dev);
-       sysfs_remove_group(&client->dev.kobj, &smsc47b397_group);
-
-       if ((err = i2c_detach_client(client)))
-               return err;
-
-       release_region(client->addr, SMSC_EXTENT);
+       sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group);
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, SMSC_EXTENT);
        kfree(data);
 
        return 0;
 }
 
-static int smsc47b397_detect(struct i2c_adapter *adapter);
+static int smsc47b397_probe(struct platform_device *pdev);
 
-static struct i2c_driver smsc47b397_driver = {
+static struct platform_driver smsc47b397_driver = {
        .driver = {
                .owner  = THIS_MODULE,
-               .name   = "smsc47b397",
+               .name   = DRVNAME,
        },
-       .attach_adapter = smsc47b397_detect,
-       .detach_client  = smsc47b397_detach_client,
+       .probe          = smsc47b397_probe,
+       .remove         = __devexit_p(smsc47b397_remove),
 };
 
-static int smsc47b397_detect(struct i2c_adapter *adapter)
+static int __devinit smsc47b397_probe(struct platform_device *pdev)
 {
-       struct i2c_client *new_client;
+       struct device *dev = &pdev->dev;
        struct smsc47b397_data *data;
+       struct resource *res;
        int err = 0;
 
-       if (!request_region(address, SMSC_EXTENT,
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, SMSC_EXTENT,
                            smsc47b397_driver.driver.name)) {
-               dev_err(&adapter->dev, "Region 0x%x already in use!\n",
-                       address);
+               dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+                       (unsigned long)res->start,
+                       (unsigned long)res->start + SMSC_EXTENT - 1);
                return -EBUSY;
        }
 
@@ -265,25 +261,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
                goto error_release;
        }
 
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
+       data->addr = res->start;
+       data->name = "smsc47b397";
        mutex_init(&data->lock);
-       new_client->adapter = adapter;
-       new_client->driver = &smsc47b397_driver;
-       new_client->flags = 0;
-
-       strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE);
-
        mutex_init(&data->update_lock);
+       platform_set_drvdata(pdev, data);
 
-       if ((err = i2c_attach_client(new_client)))
+       if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group)))
                goto error_free;
 
-       if ((err = sysfs_create_group(&new_client->dev.kobj, &smsc47b397_group)))
-               goto error_detach;
-
-       data->class_dev = hwmon_device_register(&new_client->dev);
+       data->class_dev = hwmon_device_register(dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
                goto error_remove;
@@ -292,13 +279,50 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
        return 0;
 
 error_remove:
-       sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group);
-error_detach:
-       i2c_detach_client(new_client);
+       sysfs_remove_group(&dev->kobj, &smsc47b397_group);
 error_free:
        kfree(data);
 error_release:
-       release_region(address, SMSC_EXTENT);
+       release_region(res->start, SMSC_EXTENT);
+       return err;
+}
+
+static int __init smsc47b397_device_add(unsigned short address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + SMSC_EXTENT - 1,
+               .name   = DRVNAME,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc(DRVNAME, address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(pdev);
+exit:
        return err;
 }
 
@@ -320,7 +344,7 @@ static int __init smsc47b397_find(unsigned short *addr)
        *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
                 |  superio_inb(SUPERIO_REG_BASE_LSB);
 
-       printk(KERN_INFO "smsc47b397: found SMSC %s "
+       printk(KERN_INFO DRVNAME ": found SMSC %s "
                "(base address 0x%04x, revision %u)\n",
                id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
 
@@ -330,17 +354,33 @@ static int __init smsc47b397_find(unsigned short *addr)
 
 static int __init smsc47b397_init(void)
 {
+       unsigned short address;
        int ret;
 
        if ((ret = smsc47b397_find(&address)))
                return ret;
 
-       return i2c_isa_add_driver(&smsc47b397_driver);
+       ret = platform_driver_register(&smsc47b397_driver);
+       if (ret)
+               goto exit;
+
+       /* Sets global pdev as a side effect */
+       ret = smsc47b397_device_add(address);
+       if (ret)
+               goto exit_driver;
+
+       return 0;
+
+exit_driver:
+       platform_driver_unregister(&smsc47b397_driver);
+exit:
+       return ret;
 }
 
 static void __exit smsc47b397_exit(void)
 {
-       i2c_isa_del_driver(&smsc47b397_driver);
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&smsc47b397_driver);
 }
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
index beb881c4b2e8ce1f2c191f6ce2343655a0e57200..1e21c8cc948f5902571ead518aeb36d9b59a2ffa 100644 (file)
@@ -3,10 +3,11 @@
                  for hardware monitoring
 
     Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
-    LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
+    LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997
+    Super-I/O chips.
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
-    Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org>
     Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
                         and Jean Delvare
 
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <asm/io.h>
 
-/* Address is autodetected, there is no default value */
-static unsigned short address;
+static struct platform_device *pdev;
+
+#define DRVNAME "smsc47m1"
+enum chips { smsc47m1, smsc47m2 };
 
 /* Super-I/0 registers and commands */
 
@@ -87,10 +90,18 @@ superio_exit(void)
 #define SMSC47M1_REG_ALARM             0x04
 #define SMSC47M1_REG_TPIN(nr)          (0x34 - (nr))
 #define SMSC47M1_REG_PPIN(nr)          (0x36 - (nr))
-#define SMSC47M1_REG_PWM(nr)           (0x56 + (nr))
 #define SMSC47M1_REG_FANDIV            0x58
-#define SMSC47M1_REG_FAN(nr)           (0x59 + (nr))
-#define SMSC47M1_REG_FAN_PRELOAD(nr)   (0x5B + (nr))
+
+static const u8 SMSC47M1_REG_FAN[3]            = { 0x59, 0x5a, 0x6b };
+static const u8 SMSC47M1_REG_FAN_PRELOAD[3]    = { 0x5b, 0x5c, 0x6c };
+static const u8 SMSC47M1_REG_PWM[3]            = { 0x56, 0x57, 0x69 };
+
+#define SMSC47M2_REG_ALARM6            0x09
+#define SMSC47M2_REG_TPIN1             0x38
+#define SMSC47M2_REG_TPIN2             0x37
+#define SMSC47M2_REG_TPIN3             0x2d
+#define SMSC47M2_REG_PPIN3             0x2c
+#define SMSC47M2_REG_FANDIV3           0x6a
 
 #define MIN_FROM_REG(reg,div)          ((reg)>=192 ? 0 : \
                                         983040/((192-(reg))*(div)))
@@ -102,45 +113,57 @@ superio_exit(void)
 #define PWM_TO_REG(reg)                        (((reg) >> 1) & 0x7E)
 
 struct smsc47m1_data {
-       struct i2c_client client;
+       unsigned short addr;
+       const char *name;
+       enum chips type;
        struct class_device *class_dev;
-       struct mutex lock;
 
        struct mutex update_lock;
        unsigned long last_updated;     /* In jiffies */
 
-       u8 fan[2];              /* Register value */
-       u8 fan_preload[2];      /* Register value */
-       u8 fan_div[2];          /* Register encoding, shifted right */
+       u8 fan[3];              /* Register value */
+       u8 fan_preload[3];      /* Register value */
+       u8 fan_div[3];          /* Register encoding, shifted right */
        u8 alarms;              /* Register encoding */
-       u8 pwm[2];              /* Register value (bit 7 is enable) */
+       u8 pwm[3];              /* Register value (bit 0 is disable) */
 };
 
+struct smsc47m1_sio_data {
+       enum chips type;
+};
 
-static int smsc47m1_detect(struct i2c_adapter *adapter);
-static int smsc47m1_detach_client(struct i2c_client *client);
-
-static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
-static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
 
+static int smsc47m1_probe(struct platform_device *pdev);
+static int smsc47m1_remove(struct platform_device *pdev);
 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
                int init);
 
+static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg)
+{
+       return inb_p(data->addr + reg);
+}
 
-static struct i2c_driver smsc47m1_driver = {
+static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg,
+               u8 value)
+{
+       outb_p(value, data->addr + reg);
+}
+
+static struct platform_driver smsc47m1_driver = {
        .driver = {
                .owner  = THIS_MODULE,
-               .name   = "smsc47m1",
+               .name   = DRVNAME,
        },
-       .attach_adapter = smsc47m1_detect,
-       .detach_client  = smsc47m1_detach_client,
+       .probe          = smsc47m1_probe,
+       .remove         = __devexit_p(smsc47m1_remove),
 };
 
-/* nr is 0 or 1 in the callback functions below */
-
-static ssize_t get_fan(struct device *dev, char *buf, int nr)
+static ssize_t get_fan(struct device *dev, struct device_attribute
+                      *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       int nr = attr->index;
        /* This chip (stupidly) stops monitoring fan speed if PWM is
           enabled and duty cycle is 0%. This is fine if the monitoring
           and control concern the same fan, but troublesome if they are
@@ -152,43 +175,54 @@ static ssize_t get_fan(struct device *dev, char *buf, int nr)
        return sprintf(buf, "%d\n", rpm);
 }
 
-static ssize_t get_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t get_fan_min(struct device *dev, struct device_attribute
+                          *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       int nr = attr->index;
        int rpm = MIN_FROM_REG(data->fan_preload[nr],
                               DIV_FROM_REG(data->fan_div[nr]));
        return sprintf(buf, "%d\n", rpm);
 }
 
-static ssize_t get_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t get_fan_div(struct device *dev, struct device_attribute
+                          *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
-       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
 }
 
-static ssize_t get_pwm(struct device *dev, char *buf, int nr)
+static ssize_t get_pwm(struct device *dev, struct device_attribute
+                      *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
-       return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
+       return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index]));
 }
 
-static ssize_t get_pwm_en(struct device *dev, char *buf, int nr)
+static ssize_t get_pwm_en(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
-       return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
+       return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index]));
 }
 
-static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t get_alarms(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
 {
        struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
        return sprintf(buf, "%d\n", data->alarms);
 }
 
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+                          *devattr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        long rpmdiv, val = simple_strtol(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
@@ -200,7 +234,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
        }
 
        data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
-       smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+       smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
                             data->fan_preload[nr]);
        mutex_unlock(&data->update_lock);
 
@@ -211,12 +245,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
    determined in part by the fan clock divider.  This follows the principle
    of least surprise; the user doesn't expect the fan minimum to change just
    because the divider changed. */
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute
+                          *devattr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
-
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        long new_div = simple_strtol(buf, NULL, 10), tmp;
        u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
 
@@ -234,27 +268,38 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
                return -EINVAL;
        }
 
-       tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F;
-       tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6);
-       smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp);
+       switch (nr) {
+       case 0:
+       case 1:
+               tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV)
+                     & ~(0x03 << (4 + 2 * nr));
+               tmp |= data->fan_div[nr] << (4 + 2 * nr);
+               smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp);
+               break;
+       case 2:
+               tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF;
+               tmp |= data->fan_div[2] << 4;
+               smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp);
+               break;
+       }
 
        /* Preserve fan min */
        tmp = 192 - (old_div * (192 - data->fan_preload[nr])
                     + new_div / 2) / new_div;
        data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
-       smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+       smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
                             data->fan_preload[nr]);
        mutex_unlock(&data->update_lock);
 
        return count;
 }
 
-static ssize_t set_pwm(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_pwm(struct device *dev, struct device_attribute
+                      *devattr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
-
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        long val = simple_strtol(buf, NULL, 10);
 
        if (val < 0 || val > 255)
@@ -263,19 +308,19 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
        mutex_lock(&data->update_lock);
        data->pwm[nr] &= 0x81; /* Preserve additional bits */
        data->pwm[nr] |= PWM_TO_REG(val);
-       smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+       smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
                             data->pwm[nr]);
        mutex_unlock(&data->update_lock);
 
        return count;
 }
 
-static ssize_t set_pwm_en(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_pwm_en(struct device *dev, struct device_attribute
+                         *devattr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
-
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        long val = simple_strtol(buf, NULL, 10);
        
        if (val != 0 && val != 1)
@@ -284,7 +329,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
        mutex_lock(&data->update_lock);
        data->pwm[nr] &= 0xFE; /* preserve the other bits */
        data->pwm[nr] |= !val;
-       smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+       smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
                             data->pwm[nr]);
        mutex_unlock(&data->update_lock);
 
@@ -292,79 +337,55 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
 }
 
 #define fan_present(offset)                                            \
-static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf)          \
-{                                                                      \
-       return get_fan(dev, buf, offset - 1);                           \
-}                                                                      \
-static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)    \
-{                                                                      \
-       return get_fan_min(dev, buf, offset - 1);                       \
-}                                                                      \
-static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr,               \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_fan_min(dev, buf, count, offset - 1);                \
-}                                                                      \
-static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)    \
-{                                                                      \
-       return get_fan_div(dev, buf, offset - 1);                       \
-}                                                                      \
-static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr,               \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_fan_div(dev, buf, count, offset - 1);                \
-}                                                                      \
-static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf)          \
-{                                                                      \
-       return get_pwm(dev, buf, offset - 1);                           \
-}                                                                      \
-static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr,                     \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_pwm(dev, buf, count, offset - 1);                    \
-}                                                                      \
-static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf)     \
-{                                                                      \
-       return get_pwm_en(dev, buf, offset - 1);                        \
-}                                                                      \
-static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr,                \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_pwm_en(dev, buf, count, offset - 1);                 \
-}                                                                      \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset,      \
-               NULL);                                                  \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,               \
-               get_fan##offset##_min, set_fan##offset##_min);          \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,               \
-               get_fan##offset##_div, set_fan##offset##_div);          \
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,                     \
-               get_pwm##offset, set_pwm##offset);                      \
-static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,            \
-               get_pwm##offset##_en, set_pwm##offset##_en);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan,       \
+               NULL, offset - 1);                                      \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,                \
+               get_fan_min, set_fan_min, offset - 1);                  \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,                \
+               get_fan_div, set_fan_div, offset - 1);                  \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,              \
+               get_pwm, set_pwm, offset - 1);                          \
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,     \
+               get_pwm_en, set_pwm_en, offset - 1)
 
 fan_present(1);
 fan_present(2);
+fan_present(3);
 
 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
 
+static ssize_t show_name(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
+{
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 /* Almost all sysfs files may or may not be created depending on the chip
    setup so we create them individually. It is still convenient to define a
    group to remove them all at once. */
 static struct attribute *smsc47m1_attributes[] = {
-       &dev_attr_fan1_input.attr,
-       &dev_attr_fan1_min.attr,
-       &dev_attr_fan1_div.attr,
-       &dev_attr_fan2_input.attr,
-       &dev_attr_fan2_min.attr,
-       &dev_attr_fan2_div.attr,
-
-       &dev_attr_pwm1.attr,
-       &dev_attr_pwm1_enable.attr,
-       &dev_attr_pwm2.attr,
-       &dev_attr_pwm2_enable.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_min.dev_attr.attr,
+       &sensor_dev_attr_fan3_div.dev_attr.attr,
+
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm3.dev_attr.attr,
+       &sensor_dev_attr_pwm3_enable.dev_attr.attr,
 
        &dev_attr_alarms.attr,
+       &dev_attr_name.attr,
        NULL
 };
 
@@ -372,7 +393,8 @@ static const struct attribute_group smsc47m1_group = {
        .attrs = smsc47m1_attributes,
 };
 
-static int __init smsc47m1_find(unsigned short *addr)
+static int __init smsc47m1_find(unsigned short *addr,
+                               struct smsc47m1_sio_data *sio_data)
 {
        u8 val;
 
@@ -386,18 +408,32 @@ static int __init smsc47m1_find(unsigned short *addr)
         * can do much more besides (device id 0x60).
         * The LPC47M997 is undocumented, but seems to be compatible with
         * the LPC47M192, and has the same device id.
+        * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
+        * supports a 3rd fan, and the pin configuration registers are
+        * unfortunately different.
         */
-       if (val == 0x51)
-               printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
-       else if (val == 0x59)
-               printk(KERN_INFO "smsc47m1: Found SMSC "
-                      "LPC47M10x/LPC47M112/LPC47M13x\n");
-       else if (val == 0x5F)
-               printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
-       else if (val == 0x60)
-               printk(KERN_INFO "smsc47m1: Found SMSC "
-                      "LPC47M15x/LPC47M192/LPC47M997\n");
-       else {
+       switch (val) {
+       case 0x51:
+               pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
+               sio_data->type = smsc47m1;
+               break;
+       case 0x59:
+               pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
+               sio_data->type = smsc47m1;
+               break;
+       case 0x5F:
+               pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
+               sio_data->type = smsc47m1;
+               break;
+       case 0x60:
+               pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
+               sio_data->type = smsc47m1;
+               break;
+       case 0x6B:
+               pr_info(DRVNAME ": Found SMSC LPC47M292\n");
+               sio_data->type = smsc47m2;
+               break;
+       default:
                superio_exit();
                return -ENODEV;
        }
@@ -407,7 +443,7 @@ static int __init smsc47m1_find(unsigned short *addr)
              |  superio_inb(SUPERIO_REG_BASE + 1);
        val = superio_inb(SUPERIO_REG_ACT);
        if (*addr == 0 || (val & 0x01) == 0) {
-               printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
+               pr_info(DRVNAME ": Device is disabled, will not use\n");
                superio_exit();
                return -ENODEV;
        }
@@ -416,15 +452,25 @@ static int __init smsc47m1_find(unsigned short *addr)
        return 0;
 }
 
-static int smsc47m1_detect(struct i2c_adapter *adapter)
+static int __devinit smsc47m1_probe(struct platform_device *pdev)
 {
-       struct i2c_client *new_client;
+       struct device *dev = &pdev->dev;
+       struct smsc47m1_sio_data *sio_data = dev->platform_data;
        struct smsc47m1_data *data;
+       struct resource *res;
        int err = 0;
-       int fan1, fan2, pwm1, pwm2;
-
-       if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) {
-               dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
+       int fan1, fan2, fan3, pwm1, pwm2, pwm3;
+
+       static const char *names[] = {
+               "smsc47m1",
+               "smsc47m2",
+       };
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) {
+               dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+                       (unsigned long)res->start,
+                       (unsigned long)res->end);
                return -EBUSY;
        }
 
@@ -433,93 +479,114 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
                goto error_release;
        }
 
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
-       mutex_init(&data->lock);
-       new_client->adapter = adapter;
-       new_client->driver = &smsc47m1_driver;
-       new_client->flags = 0;
-
-       strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
+       data->addr = res->start;
+       data->type = sio_data->type;
+       data->name = names[sio_data->type];
        mutex_init(&data->update_lock);
+       platform_set_drvdata(pdev, data);
 
        /* If no function is properly configured, there's no point in
           actually registering the chip. */
-       fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
-              == 0x05;
-       fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
-              == 0x05;
-       pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
+       pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05)
               == 0x04;
-       pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
+       pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05)
               == 0x04;
-       if (!(fan1 || fan2 || pwm1 || pwm2)) {
-               dev_warn(&adapter->dev, "Device at 0x%x is not configured, "
-                        "will not use\n", new_client->addr);
+       if (data->type == smsc47m2) {
+               fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1)
+                       & 0x0d) == 0x09;
+               fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2)
+                       & 0x0d) == 0x09;
+               fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3)
+                       & 0x0d) == 0x0d;
+               pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3)
+                       & 0x0d) == 0x08;
+       } else {
+               fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0))
+                       & 0x05) == 0x05;
+               fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1))
+                       & 0x05) == 0x05;
+               fan3 = 0;
+               pwm3 = 0;
+       }
+       if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) {
+               dev_warn(dev, "Device not configured, will not use\n");
                err = -ENODEV;
                goto error_free;
        }
 
-       if ((err = i2c_attach_client(new_client)))
-               goto error_free;
-
        /* Some values (fan min, clock dividers, pwm registers) may be
           needed before any update is triggered, so we better read them
           at least once here. We don't usually do it that way, but in
           this particular case, manually reading 5 registers out of 8
           doesn't make much sense and we're better using the existing
           function. */
-       smsc47m1_update_device(&new_client->dev, 1);
+       smsc47m1_update_device(dev, 1);
 
        /* Register sysfs hooks */
        if (fan1) {
-               if ((err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan1_input))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan1_min))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan1_div)))
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_fan1_input.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan1_min.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan1_div.dev_attr)))
                        goto error_remove_files;
        } else
-               dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
-                       "skipping\n");
+               dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n");
 
        if (fan2) {
-               if ((err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan2_input))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan2_min))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_fan2_div)))
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_fan2_input.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan2_min.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan2_div.dev_attr)))
                        goto error_remove_files;
        } else
-               dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
-                       "skipping\n");
+               dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n");
+
+       if (fan3) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_fan3_input.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan3_min.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan3_div.dev_attr)))
+                       goto error_remove_files;
+       } else
+               dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n");
 
        if (pwm1) {
-               if ((err = device_create_file(&new_client->dev,
-                                             &dev_attr_pwm1))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_pwm1_enable)))
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_pwm1.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_pwm1_enable.dev_attr)))
                        goto error_remove_files;
        } else
-               dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
-                       "skipping\n");
+               dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n");
+
        if (pwm2) {
-               if ((err = device_create_file(&new_client->dev,
-                                             &dev_attr_pwm2))
-                || (err = device_create_file(&new_client->dev,
-                                             &dev_attr_pwm2_enable)))
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_pwm2.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_pwm2_enable.dev_attr)))
+                       goto error_remove_files;
+       } else
+               dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n");
+
+       if (pwm3) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_pwm3.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_pwm3_enable.dev_attr)))
                        goto error_remove_files;
        } else
-               dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
-                       "skipping\n");
+               dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
 
-       if ((err = device_create_file(&new_client->dev, &dev_attr_alarms)))
+       if ((err = device_create_file(dev, &dev_attr_alarms)))
                goto error_remove_files;
 
-       data->class_dev = hwmon_device_register(&new_client->dev);
+       data->class_dev = hwmon_device_register(dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
                goto error_remove_files;
@@ -528,78 +595,71 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
        return 0;
 
 error_remove_files:
-       sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group);
-       i2c_detach_client(new_client);
+       sysfs_remove_group(&dev->kobj, &smsc47m1_group);
 error_free:
        kfree(data);
 error_release:
-       release_region(address, SMSC_EXTENT);
+       release_region(res->start, SMSC_EXTENT);
        return err;
 }
 
-static int smsc47m1_detach_client(struct i2c_client *client)
+static int __devexit smsc47m1_remove(struct platform_device *pdev)
 {
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
-       int err;
+       struct smsc47m1_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
 
+       platform_set_drvdata(pdev, NULL);
        hwmon_device_unregister(data->class_dev);
-       sysfs_remove_group(&client->dev.kobj, &smsc47m1_group);
-
-       if ((err = i2c_detach_client(client)))
-               return err;
+       sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
 
-       release_region(client->addr, SMSC_EXTENT);
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, SMSC_EXTENT);
        kfree(data);
 
        return 0;
 }
 
-static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
-{
-       int res;
-
-       mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
-       res = inb_p(client->addr + reg);
-       mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
-       return res;
-}
-
-static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
-{
-       mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
-       outb_p(value, client->addr + reg);
-       mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
-}
-
 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
                int init)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct smsc47m1_data *data = i2c_get_clientdata(client);
+       struct smsc47m1_data *data = dev_get_drvdata(dev);
 
        mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
-               int i;
-
-               for (i = 0; i < 2; i++) {
-                       data->fan[i] = smsc47m1_read_value(client,
-                                      SMSC47M1_REG_FAN(i));
-                       data->fan_preload[i] = smsc47m1_read_value(client,
-                                              SMSC47M1_REG_FAN_PRELOAD(i));
-                       data->pwm[i] = smsc47m1_read_value(client,
-                                      SMSC47M1_REG_PWM(i));
+               int i, fan_nr;
+               fan_nr = data->type == smsc47m2 ? 3 : 2;
+
+               for (i = 0; i < fan_nr; i++) {
+                       data->fan[i] = smsc47m1_read_value(data,
+                                      SMSC47M1_REG_FAN[i]);
+                       data->fan_preload[i] = smsc47m1_read_value(data,
+                                              SMSC47M1_REG_FAN_PRELOAD[i]);
+                       data->pwm[i] = smsc47m1_read_value(data,
+                                      SMSC47M1_REG_PWM[i]);
                }
 
-               i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
+               i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
                data->fan_div[0] = (i >> 4) & 0x03;
                data->fan_div[1] = i >> 6;
 
-               data->alarms = smsc47m1_read_value(client,
+               data->alarms = smsc47m1_read_value(data,
                               SMSC47M1_REG_ALARM) >> 6;
                /* Clear alarms if needed */
                if (data->alarms)
-                       smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
+                       smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
+
+               if (fan_nr >= 3) {
+                       data->fan_div[2] = (smsc47m1_read_value(data,
+                                           SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
+                       data->alarms |= (smsc47m1_read_value(data,
+                                        SMSC47M2_REG_ALARM6) & 0x40) >> 4;
+                       /* Clear alarm if needed */
+                       if (data->alarms & 0x04)
+                               smsc47m1_write_value(data,
+                                                    SMSC47M2_REG_ALARM6,
+                                                    0x40);
+               }
 
                data->last_updated = jiffies;
        }
@@ -608,18 +668,86 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
        return data;
 }
 
+static int __init smsc47m1_device_add(unsigned short address,
+                                     const struct smsc47m1_sio_data *sio_data)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + SMSC_EXTENT - 1,
+               .name   = DRVNAME,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc(DRVNAME, address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       pdev->dev.platform_data = kmalloc(sizeof(struct smsc47m1_sio_data),
+                                         GFP_KERNEL);
+       if (!pdev->dev.platform_data) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+               goto exit_device_put;
+       }
+       memcpy(pdev->dev.platform_data, sio_data,
+              sizeof(struct smsc47m1_sio_data));
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(pdev);
+exit:
+       return err;
+}
+
 static int __init sm_smsc47m1_init(void)
 {
-       if (smsc47m1_find(&address)) {
+       int err;
+       unsigned short address;
+       struct smsc47m1_sio_data sio_data;
+
+       if (smsc47m1_find(&address, &sio_data))
                return -ENODEV;
-       }
 
-       return i2c_isa_add_driver(&smsc47m1_driver);
+       err = platform_driver_register(&smsc47m1_driver);
+       if (err)
+               goto exit;
+
+       /* Sets global pdev as a side effect */
+       err = smsc47m1_device_add(address, &sio_data);
+       if (err)
+               goto exit_driver;
+
+       return 0;
+
+exit_driver:
+       platform_driver_unregister(&smsc47m1_driver);
+exit:
+       return err;
 }
 
 static void __exit sm_smsc47m1_exit(void)
 {
-       i2c_isa_del_driver(&smsc47m1_driver);
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&smsc47m1_driver);
 }
 
 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
index a6833f4373950c8f46295cdb3b579945c7feb668..a012f396f354d146a65a9128855e63f1aa6d0751 100644 (file)
@@ -1,6 +1,6 @@
 /*
     smsc47m192.c - Support for hardware monitoring block of
-                   SMSC LPC47M192 and LPC47M997 Super I/O chips
+                   SMSC LPC47M192 and compatible Super I/O chips
 
     Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
 
@@ -518,7 +518,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
                 && (i2c_smbus_read_byte_data(client,
                                SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
                        dev_info(&adapter->dev,
-                                "found SMSC47M192 or SMSC47M997, "
+                                "found SMSC47M192 or compatible, "
                                 "version 2, stepping A%d\n", version & 0x0f);
                } else {
                        dev_dbg(&adapter->dev,
index 89c23d6add7be174190cbc90f2cf2f1b25d2be10..9f3e332c5b7fe129f6ec9a62baa3201168ecf0c3 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/ioport.h>
 #include <asm/io.h>
 
 static int uch_config = -1;
@@ -1130,6 +1131,12 @@ static int __devinit vt1211_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+               err = -EBUSY;
+               dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
+                       (unsigned long)res->start, (unsigned long)res->end);
+               goto EXIT_KFREE;
+       }
        data->addr = res->start;
        data->name = DRVNAME;
        mutex_init(&data->update_lock);
@@ -1197,6 +1204,8 @@ EXIT_DEV_REMOVE:
        dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
 EXIT_DEV_REMOVE_SILENT:
        vt1211_remove_sysfs(pdev);
+       release_region(res->start, res->end - res->start + 1);
+EXIT_KFREE:
        platform_set_drvdata(pdev, NULL);
        kfree(data);
 EXIT:
@@ -1206,12 +1215,16 @@ EXIT:
 static int __devexit vt1211_remove(struct platform_device *pdev)
 {
        struct vt1211_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
 
        hwmon_device_unregister(data->class_dev);
        vt1211_remove_sysfs(pdev);
        platform_set_drvdata(pdev, NULL);
        kfree(data);
 
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, res->end - res->start + 1);
+
        return 0;
 }
 
index d7e240635b3b7b3d370d81db423e48e90b3249a8..a5b774b07cbde457618d6885fd96d675193f8c11 100644 (file)
@@ -5,6 +5,7 @@
     Philip Edelbrock <phil@netroedge.com>,
     and Mark Studebaker <mdsxyz123@yahoo.com>
     Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
+    Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/ioport.h>
 #include <asm/io.h>
 #include "lm75.h"
 
+static struct platform_device *pdev;
+
+#define DRVNAME "w83627hf"
+enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
+
 static u16 force_addr;
 module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
@@ -60,12 +66,6 @@ module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
                 "Initialize the i2c address of the sensors");
 
-/* The actual ISA address is read from Super-I/O configuration space */
-static unsigned short address;
-
-/* Insmod parameters */
-enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
-
 static int reset;
 module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
@@ -156,9 +156,9 @@ superio_exit(void)
 #define WINB_REGION_OFFSET     5
 #define WINB_REGION_SIZE       2
 
-/* Where are the sensors address/data registers relative to the base address */
-#define W83781D_ADDR_REG_OFFSET 5
-#define W83781D_DATA_REG_OFFSET 6
+/* Where are the sensors address/data registers relative to the region offset */
+#define W83781D_ADDR_REG_OFFSET 0
+#define W83781D_DATA_REG_OFFSET 1
 
 /* The W83781D registers */
 /* The W83782D registers for nr=7,8 are in bank 5 */
@@ -289,7 +289,8 @@ static inline u8 DIV_TO_REG(long val)
 /* For each registered chip, we need to keep some data in memory.
    The structure is dynamically allocated. */
 struct w83627hf_data {
-       struct i2c_client client;
+       unsigned short addr;
+       const char *name;
        struct class_device *class_dev;
        struct mutex lock;
        enum chips type;
@@ -298,9 +299,6 @@ struct w83627hf_data {
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
 
-       struct i2c_client *lm75;        /* for secondary I2C addresses */
-       /* pointer to array of 2 subclients */
-
        u8 in[9];               /* Register value */
        u8 in_max[9];           /* Register value */
        u8 in_min[9];           /* Register value */
@@ -327,22 +325,26 @@ struct w83627hf_data {
        u8 vrm_ovt;             /* Register value, 627THF/637HF/687THF only */
 };
 
+struct w83627hf_sio_data {
+       enum chips type;
+};
+
 
-static int w83627hf_detect(struct i2c_adapter *adapter);
-static int w83627hf_detach_client(struct i2c_client *client);
+static int w83627hf_probe(struct platform_device *pdev);
+static int w83627hf_remove(struct platform_device *pdev);
 
-static int w83627hf_read_value(struct i2c_client *client, u16 reg);
-static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value);
+static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
+static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
 static struct w83627hf_data *w83627hf_update_device(struct device *dev);
-static void w83627hf_init_client(struct i2c_client *client);
+static void w83627hf_init_device(struct platform_device *pdev);
 
-static struct i2c_driver w83627hf_driver = {
+static struct platform_driver w83627hf_driver = {
        .driver = {
                .owner  = THIS_MODULE,
-               .name   = "w83627hf",
+               .name   = DRVNAME,
        },
-       .attach_adapter = w83627hf_detect,
-       .detach_client  = w83627hf_detach_client,
+       .probe          = w83627hf_probe,
+       .remove         = __devexit_p(w83627hf_remove),
 };
 
 /* following are the sysfs callback functions */
@@ -360,15 +362,14 @@ show_in_reg(in_max)
 static ssize_t \
 store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
 { \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct w83627hf_data *data = i2c_get_clientdata(client); \
+       struct w83627hf_data *data = dev_get_drvdata(dev); \
        u32 val; \
         \
        val = simple_strtoul(buf, NULL, 10); \
         \
        mutex_lock(&data->update_lock); \
        data->in_##reg[nr] = IN_TO_REG(val); \
-       w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \
+       w83627hf_write_value(data, W83781D_REG_IN_##REG(nr), \
                            data->in_##reg[nr]); \
         \
        mutex_unlock(&data->update_lock); \
@@ -452,8 +453,7 @@ static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *at
 static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
        const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -472,7 +472,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
                /* use VRM8 (standard) calculation */
                data->in_min[0] = IN_TO_REG(val);
 
-       w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]);
+       w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -480,8 +480,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
 static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
        const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -500,7 +499,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
                /* use VRM8 (standard) calculation */
                data->in_max[0] = IN_TO_REG(val);
 
-       w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]);
+       w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -525,8 +524,7 @@ show_fan_reg(fan_min);
 static ssize_t
 store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -534,7 +532,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
        mutex_lock(&data->update_lock);
        data->fan_min[nr - 1] =
            FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
-       w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr),
+       w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr),
                            data->fan_min[nr - 1]);
 
        mutex_unlock(&data->update_lock);
@@ -587,8 +585,7 @@ show_temp_reg(temp_max_hyst);
 static ssize_t \
 store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
 { \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct w83627hf_data *data = i2c_get_clientdata(client); \
+       struct w83627hf_data *data = dev_get_drvdata(dev); \
        u32 val; \
         \
        val = simple_strtoul(buf, NULL, 10); \
@@ -597,11 +594,11 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
         \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
                data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
-               w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+               w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \
                                data->temp_##reg##_add[nr-2]); \
        } else {        /* TEMP1 */ \
                data->temp_##reg = TEMP_TO_REG(val); \
-               w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+               w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \
                        data->temp_##reg); \
        } \
         \
@@ -659,8 +656,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 static ssize_t
 store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -695,8 +691,7 @@ static ssize_t
 store_beep_reg(struct device *dev, const char *buf, size_t count,
               int update_mask)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val, val2;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -705,18 +700,18 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
 
        if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
                data->beep_mask = BEEP_MASK_TO_REG(val);
-               w83627hf_write_value(client, W83781D_REG_BEEP_INTS1,
+               w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
                                    data->beep_mask & 0xff);
-               w83627hf_write_value(client, W83781D_REG_BEEP_INTS3,
+               w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
                                    ((data->beep_mask) >> 16) & 0xff);
                val2 = (data->beep_mask >> 8) & 0x7f;
        } else {                /* We are storing beep_enable */
                val2 =
-                   w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
+                   w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
                data->beep_enable = BEEP_ENABLE_TO_REG(val);
        }
 
-       w83627hf_write_value(client, W83781D_REG_BEEP_INTS2,
+       w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
                            val2 | data->beep_enable << 7);
 
        mutex_unlock(&data->update_lock);
@@ -754,8 +749,7 @@ show_fan_div_reg(struct device *dev, char *buf, int nr)
 static ssize_t
 store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        unsigned long min;
        u8 reg;
        unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -768,19 +762,19 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        data->fan_div[nr] = DIV_TO_REG(val);
 
-       reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
+       reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
               & (nr==0 ? 0xcf : 0x3f))
            | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
-       w83627hf_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
+       w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
 
-       reg = (w83627hf_read_value(client, W83781D_REG_VBAT)
+       reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
               & ~(1 << (5 + nr)))
            | ((data->fan_div[nr] & 0x04) << (3 + nr));
-       w83627hf_write_value(client, W83781D_REG_VBAT, reg);
+       w83627hf_write_value(data, W83781D_REG_VBAT, reg);
 
        /* Restore fan_min */
        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-       w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+       w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 
        mutex_unlock(&data->update_lock);
        return count;
@@ -814,8 +808,7 @@ show_pwm_reg(struct device *dev, char *buf, int nr)
 static ssize_t
 store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -825,14 +818,14 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
        if (data->type == w83627thf) {
                /* bits 0-3 are reserved  in 627THF */
                data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0;
-               w83627hf_write_value(client,
+               w83627hf_write_value(data,
                                     W836X7HF_REG_PWM(data->type, nr),
                                     data->pwm[nr - 1] |
-                                    (w83627hf_read_value(client,
+                                    (w83627hf_read_value(data,
                                     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
        } else {
                data->pwm[nr - 1] = PWM_TO_REG(val);
-               w83627hf_write_value(client,
+               w83627hf_write_value(data,
                                     W836X7HF_REG_PWM(data->type, nr),
                                     data->pwm[nr - 1]);
        }
@@ -868,8 +861,7 @@ show_sensor_reg(struct device *dev, char *buf, int nr)
 static ssize_t
 store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        u32 val, tmp;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -878,31 +870,31 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        switch (val) {
        case 1:         /* PII/Celeron diode */
-               tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
-               w83627hf_write_value(client, W83781D_REG_SCFG1,
+               tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
+               w83627hf_write_value(data, W83781D_REG_SCFG1,
                                    tmp | BIT_SCFG1[nr - 1]);
-               tmp = w83627hf_read_value(client, W83781D_REG_SCFG2);
-               w83627hf_write_value(client, W83781D_REG_SCFG2,
+               tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
+               w83627hf_write_value(data, W83781D_REG_SCFG2,
                                    tmp | BIT_SCFG2[nr - 1]);
                data->sens[nr - 1] = val;
                break;
        case 2:         /* 3904 */
-               tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
-               w83627hf_write_value(client, W83781D_REG_SCFG1,
+               tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
+               w83627hf_write_value(data, W83781D_REG_SCFG1,
                                    tmp | BIT_SCFG1[nr - 1]);
-               tmp = w83627hf_read_value(client, W83781D_REG_SCFG2);
-               w83627hf_write_value(client, W83781D_REG_SCFG2,
+               tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
+               w83627hf_write_value(data, W83781D_REG_SCFG2,
                                    tmp & ~BIT_SCFG2[nr - 1]);
                data->sens[nr - 1] = val;
                break;
        case W83781D_DEFAULT_BETA:      /* thermistor */
-               tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
-               w83627hf_write_value(client, W83781D_REG_SCFG1,
+               tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
+               w83627hf_write_value(data, W83781D_REG_SCFG1,
                                    tmp & ~BIT_SCFG1[nr - 1]);
                data->sens[nr - 1] = val;
                break;
        default:
-               dev_err(&client->dev,
+               dev_err(dev,
                       "Invalid sensor type %ld; must be 1, 2, or %d\n",
                       (long) val, W83781D_DEFAULT_BETA);
                break;
@@ -929,35 +921,85 @@ sysfs_sensor(1);
 sysfs_sensor(2);
 sysfs_sensor(3);
 
-static int __init w83627hf_find(int sioaddr, unsigned short *addr)
+static ssize_t show_name(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
+{
+       struct w83627hf_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static int __init w83627hf_find(int sioaddr, unsigned short *addr,
+                               struct w83627hf_sio_data *sio_data)
 {
+       int err = -ENODEV;
        u16 val;
 
+       static const __initdata char *names[] = {
+               "W83627HF",
+               "W83627THF",
+               "W83697HF",
+               "W83637HF",
+               "W83687THF",
+       };
+
        REG = sioaddr;
        VAL = sioaddr + 1;
 
        superio_enter();
        val= superio_inb(DEVID);
-       if(val != W627_DEVID &&
-          val != W627THF_DEVID &&
-          val != W697_DEVID &&
-          val != W637_DEVID &&
-          val != W687THF_DEVID) {
-               superio_exit();
-               return -ENODEV;
+       switch (val) {
+       case W627_DEVID:
+               sio_data->type = w83627hf;
+               break;
+       case W627THF_DEVID:
+               sio_data->type = w83627thf;
+               break;
+       case W697_DEVID:
+               sio_data->type = w83697hf;
+               break;
+       case W637_DEVID:
+               sio_data->type = w83637hf;
+               break;
+       case W687THF_DEVID:
+               sio_data->type = w83687thf;
+               break;
+       default:
+               pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", val);
+               goto exit;
        }
 
        superio_select(W83627HF_LD_HWM);
+       force_addr &= WINB_ALIGNMENT;
+       if (force_addr) {
+               printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
+                      force_addr);
+               superio_outb(WINB_BASE_REG, force_addr >> 8);
+               superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
+       }
        val = (superio_inb(WINB_BASE_REG) << 8) |
               superio_inb(WINB_BASE_REG + 1);
        *addr = val & WINB_ALIGNMENT;
-       if (*addr == 0 && force_addr == 0) {
-               superio_exit();
-               return -ENODEV;
+       if (*addr == 0) {
+               printk(KERN_WARNING DRVNAME ": Base address not set, "
+                      "skipping\n");
+               goto exit;
        }
 
+       val = superio_inb(WINB_ACT_REG);
+       if (!(val & 0x01)) {
+               printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
+               superio_outb(WINB_ACT_REG, val | 0x01);
+       }
+
+       err = 0;
+       pr_info(DRVNAME ": Found %s chip at %#x\n",
+               names[sio_data->type], *addr);
+
+ exit:
        superio_exit();
-       return 0;
+       return err;
 }
 
 static struct attribute *w83627hf_attributes[] = {
@@ -1003,6 +1045,7 @@ static struct attribute *w83627hf_attributes[] = {
        &dev_attr_pwm1.attr,
        &dev_attr_pwm2.attr,
 
+       &dev_attr_name.attr,
        NULL
 };
 
@@ -1039,161 +1082,92 @@ static const struct attribute_group w83627hf_group_opt = {
        .attrs = w83627hf_attributes_opt,
 };
 
-static int w83627hf_detect(struct i2c_adapter *adapter)
+static int __devinit w83627hf_probe(struct platform_device *pdev)
 {
-       int val, kind;
-       struct i2c_client *new_client;
+       struct device *dev = &pdev->dev;
+       struct w83627hf_sio_data *sio_data = dev->platform_data;
        struct w83627hf_data *data;
-       int err = 0;
-       const char *client_name = "";
-
-       if(force_addr)
-               address = force_addr & WINB_ALIGNMENT;
+       struct resource *res;
+       int err;
 
-       if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
-                           w83627hf_driver.driver.name)) {
+       static const char *names[] = {
+               "w83627hf",
+               "w83627thf",
+               "w83697hf",
+               "w83637hf",
+               "w83687thf",
+       };
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
+               dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
+                       (unsigned long)res->start,
+                       (unsigned long)(res->start + WINB_REGION_SIZE - 1));
                err = -EBUSY;
                goto ERROR0;
        }
 
-       if(force_addr) {
-               printk("w83627hf.o: forcing ISA address 0x%04X\n", address);
-               superio_enter();
-               superio_select(W83627HF_LD_HWM);
-               superio_outb(WINB_BASE_REG, address >> 8);
-               superio_outb(WINB_BASE_REG+1, address & 0xff);
-               superio_exit();
-       }
-
-       superio_enter();
-       val= superio_inb(DEVID);
-       if(val == W627_DEVID)
-               kind = w83627hf;
-       else if(val == W697_DEVID)
-               kind = w83697hf;
-       else if(val == W627THF_DEVID)
-               kind = w83627thf;
-       else if(val == W637_DEVID)
-               kind = w83637hf;
-       else if (val == W687THF_DEVID)
-               kind = w83687thf;
-       else {
-               dev_info(&adapter->dev,
-                        "Unsupported chip (dev_id=0x%02X).\n", val);
-               goto ERROR1;
-       }
-
-       superio_select(W83627HF_LD_HWM);
-       if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0)
-               superio_outb(WINB_ACT_REG, 1);
-       superio_exit();
-
-       /* OK. For now, we presume we have a valid client. We now create the
-          client structure, even though we cannot fill it completely yet.
-          But it allows us to access w83627hf_{read,write}_value. */
-
        if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
                err = -ENOMEM;
                goto ERROR1;
        }
-
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
+       data->addr = res->start;
+       data->type = sio_data->type;
+       data->name = names[sio_data->type];
        mutex_init(&data->lock);
-       new_client->adapter = adapter;
-       new_client->driver = &w83627hf_driver;
-       new_client->flags = 0;
-
-
-       if (kind == w83627hf) {
-               client_name = "w83627hf";
-       } else if (kind == w83627thf) {
-               client_name = "w83627thf";
-       } else if (kind == w83697hf) {
-               client_name = "w83697hf";
-       } else if (kind == w83637hf) {
-               client_name = "w83637hf";
-       } else if (kind == w83687thf) {
-               client_name = "w83687thf";
-       }
-
-       /* Fill in the remaining client fields and put into the global list */
-       strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
-       data->type = kind;
-       data->valid = 0;
        mutex_init(&data->update_lock);
-
-       /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(new_client)))
-               goto ERROR2;
-
-       data->lm75 = NULL;
+       platform_set_drvdata(pdev, data);
 
        /* Initialize the chip */
-       w83627hf_init_client(new_client);
+       w83627hf_init_device(pdev);
 
        /* A few vars need to be filled upon startup */
-       data->fan_min[0] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(1));
-       data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2));
-       data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
+       data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
+       data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
+       data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
 
        /* Register common device attributes */
-       if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group)))
+       if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
                goto ERROR3;
 
        /* Register chip-specific device attributes */
-       if (kind == w83627hf || kind == w83697hf)
-               if ((err = device_create_file(&new_client->dev,
-                                       &dev_attr_in5_input))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in5_min))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in5_max))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in6_input))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in6_min))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in6_max)))
+       if (data->type == w83627hf || data->type == w83697hf)
+               if ((err = device_create_file(dev, &dev_attr_in5_input))
+                || (err = device_create_file(dev, &dev_attr_in5_min))
+                || (err = device_create_file(dev, &dev_attr_in5_max))
+                || (err = device_create_file(dev, &dev_attr_in6_input))
+                || (err = device_create_file(dev, &dev_attr_in6_min))
+                || (err = device_create_file(dev, &dev_attr_in6_max)))
                        goto ERROR4;
 
-       if (kind != w83697hf)
-               if ((err = device_create_file(&new_client->dev,
-                                       &dev_attr_in1_input))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in1_min))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_in1_max))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_fan3_input))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_fan3_min))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_fan3_div))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_temp3_input))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_temp3_max))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_temp3_max_hyst))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_temp3_type)))
+       if (data->type != w83697hf)
+               if ((err = device_create_file(dev, &dev_attr_in1_input))
+                || (err = device_create_file(dev, &dev_attr_in1_min))
+                || (err = device_create_file(dev, &dev_attr_in1_max))
+                || (err = device_create_file(dev, &dev_attr_fan3_input))
+                || (err = device_create_file(dev, &dev_attr_fan3_min))
+                || (err = device_create_file(dev, &dev_attr_fan3_div))
+                || (err = device_create_file(dev, &dev_attr_temp3_input))
+                || (err = device_create_file(dev, &dev_attr_temp3_max))
+                || (err = device_create_file(dev, &dev_attr_temp3_max_hyst))
+                || (err = device_create_file(dev, &dev_attr_temp3_type)))
                        goto ERROR4;
 
-       if (kind != w83697hf && data->vid != 0xff)
-               if ((err = device_create_file(&new_client->dev,
-                                       &dev_attr_cpu0_vid))
-                || (err = device_create_file(&new_client->dev,
-                                       &dev_attr_vrm)))
+       if (data->type != w83697hf && data->vid != 0xff) {
+               /* Convert VID to voltage based on VRM */
+               data->vrm = vid_which_vrm();
+
+               if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
+                || (err = device_create_file(dev, &dev_attr_vrm)))
                        goto ERROR4;
+       }
 
-       if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
-               if ((err = device_create_file(&new_client->dev,
-                                       &dev_attr_pwm3)))
+       if (data->type == w83627thf || data->type == w83637hf
+        || data->type == w83687thf)
+               if ((err = device_create_file(dev, &dev_attr_pwm3)))
                        goto ERROR4;
 
-       data->class_dev = hwmon_device_register(&new_client->dev);
+       data->class_dev = hwmon_device_register(dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
                goto ERROR4;
@@ -1202,47 +1176,37 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
        return 0;
 
       ERROR4:
-       sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group);
-       sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt);
+       sysfs_remove_group(&dev->kobj, &w83627hf_group);
+       sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
       ERROR3:
-       i2c_detach_client(new_client);
-      ERROR2:
        kfree(data);
       ERROR1:
-       release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
+       release_region(res->start, WINB_REGION_SIZE);
       ERROR0:
        return err;
 }
 
-static int w83627hf_detach_client(struct i2c_client *client)
+static int __devexit w83627hf_remove(struct platform_device *pdev)
 {
-       struct w83627hf_data *data = i2c_get_clientdata(client);
-       int err;
+       struct w83627hf_data *data = platform_get_drvdata(pdev);
+       struct resource *res;
 
+       platform_set_drvdata(pdev, NULL);
        hwmon_device_unregister(data->class_dev);
 
-       sysfs_remove_group(&client->dev.kobj, &w83627hf_group);
-       sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt);
-
-       if ((err = i2c_detach_client(client)))
-               return err;
-
-       release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
+       sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
+       sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
        kfree(data);
 
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, WINB_REGION_SIZE);
+
        return 0;
 }
 
 
-/*
-   ISA access must always be locked explicitly!
-   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the W83781D access and should not be necessary.
-   There are some ugly typecasts here, but the good news is - they should
-   nowhere else be necessary! */
-static int w83627hf_read_value(struct i2c_client *client, u16 reg)
+static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
 {
-       struct w83627hf_data *data = i2c_get_clientdata(client);
        int res, word_sized;
 
        mutex_lock(&data->lock);
@@ -1253,29 +1217,29 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
                   || ((reg & 0x00ff) == 0x55));
        if (reg & 0xff00) {
                outb_p(W83781D_REG_BANK,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
                outb_p(reg >> 8,
-                      client->addr + W83781D_DATA_REG_OFFSET);
+                      data->addr + W83781D_DATA_REG_OFFSET);
        }
-       outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
-       res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
+       outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
+       res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
        if (word_sized) {
                outb_p((reg & 0xff) + 1,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
                res =
-                   (res << 8) + inb_p(client->addr +
+                   (res << 8) + inb_p(data->addr +
                                       W83781D_DATA_REG_OFFSET);
        }
        if (reg & 0xff00) {
                outb_p(W83781D_REG_BANK,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
-               outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
+               outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
        }
        mutex_unlock(&data->lock);
        return res;
 }
 
-static int w83627thf_read_gpio5(struct i2c_client *client)
+static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
 {
        int res = 0xff, sel;
 
@@ -1284,7 +1248,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
 
        /* Make sure these GPIO pins are enabled */
        if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
-               dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n");
+               dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
                goto exit;
        }
 
@@ -1292,12 +1256,12 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
           There must be at least five (VRM 9), and possibly 6 (VRM 10) */
        sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
        if ((sel & 0x1f) != 0x1f) {
-               dev_dbg(&client->dev, "GPIO5 not configured for VID "
+               dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
                        "function\n");
                goto exit;
        }
 
-       dev_info(&client->dev, "Reading VID from GPIO5\n");
+       dev_info(&pdev->dev, "Reading VID from GPIO5\n");
        res = superio_inb(W83627THF_GPIO5_DR) & sel;
 
 exit:
@@ -1305,7 +1269,7 @@ exit:
        return res;
 }
 
-static int w83687thf_read_vid(struct i2c_client *client)
+static int __devinit w83687thf_read_vid(struct platform_device *pdev)
 {
        int res = 0xff;
 
@@ -1314,13 +1278,13 @@ static int w83687thf_read_vid(struct i2c_client *client)
 
        /* Make sure these GPIO pins are enabled */
        if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
-               dev_dbg(&client->dev, "VID disabled, no VID function\n");
+               dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
                goto exit;
        }
 
        /* Make sure the pins are configured for input */
        if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
-               dev_dbg(&client->dev, "VID configured as output, "
+               dev_dbg(&pdev->dev, "VID configured as output, "
                        "no VID function\n");
                goto exit;
        }
@@ -1332,9 +1296,8 @@ exit:
        return res;
 }
 
-static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
+static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
 {
-       struct w83627hf_data *data = i2c_get_clientdata(client);
        int word_sized;
 
        mutex_lock(&data->lock);
@@ -1344,33 +1307,33 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
                   || ((reg & 0x00ff) == 0x55));
        if (reg & 0xff00) {
                outb_p(W83781D_REG_BANK,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
                outb_p(reg >> 8,
-                      client->addr + W83781D_DATA_REG_OFFSET);
+                      data->addr + W83781D_DATA_REG_OFFSET);
        }
-       outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
+       outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
        if (word_sized) {
                outb_p(value >> 8,
-                      client->addr + W83781D_DATA_REG_OFFSET);
+                      data->addr + W83781D_DATA_REG_OFFSET);
                outb_p((reg & 0xff) + 1,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
        }
        outb_p(value & 0xff,
-              client->addr + W83781D_DATA_REG_OFFSET);
+              data->addr + W83781D_DATA_REG_OFFSET);
        if (reg & 0xff00) {
                outb_p(W83781D_REG_BANK,
-                      client->addr + W83781D_ADDR_REG_OFFSET);
-               outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+                      data->addr + W83781D_ADDR_REG_OFFSET);
+               outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
        }
        mutex_unlock(&data->lock);
        return 0;
 }
 
-static void w83627hf_init_client(struct i2c_client *client)
+static void __devinit w83627hf_init_device(struct platform_device *pdev)
 {
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = platform_get_drvdata(pdev);
        int i;
-       int type = data->type;
+       enum chips type = data->type;
        u8 tmp;
 
        if (reset) {
@@ -1379,57 +1342,53 @@ static void w83627hf_init_client(struct i2c_client *client)
                   speed...) so it is now optional. It might even go away if
                   nobody reports it as being useful, as I see very little
                   reason why this would be needed at all. */
-               dev_info(&client->dev, "If reset=1 solved a problem you were "
+               dev_info(&pdev->dev, "If reset=1 solved a problem you were "
                         "having, please report!\n");
 
                /* save this register */
-               i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
+               i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG);
                /* Reset all except Watchdog values and last conversion values
                   This sets fan-divs to 2, among others */
-               w83627hf_write_value(client, W83781D_REG_CONFIG, 0x80);
+               w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80);
                /* Restore the register and disable power-on abnormal beep.
                   This saves FAN 1/2/3 input/output values set by BIOS. */
-               w83627hf_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
+               w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
                /* Disable master beep-enable (reset turns it on).
                   Individual beeps should be reset to off but for some reason
                   disabling this bit helps some people not get beeped */
-               w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, 0);
+               w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0);
        }
 
        /* Minimize conflicts with other winbond i2c-only clients...  */
        /* disable i2c subclients... how to disable main i2c client?? */
        /* force i2c address to relatively uncommon address */
-       w83627hf_write_value(client, W83781D_REG_I2C_SUBADDR, 0x89);
-       w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c);
+       w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
+       w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
 
        /* Read VID only once */
-       if (w83627hf == data->type || w83637hf == data->type) {
-               int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
-               int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
+       if (type == w83627hf || type == w83637hf) {
+               int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
+               int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
                data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
-       } else if (w83627thf == data->type) {
-               data->vid = w83627thf_read_gpio5(client);
-       } else if (w83687thf == data->type) {
-               data->vid = w83687thf_read_vid(client);
+       } else if (type == w83627thf) {
+               data->vid = w83627thf_read_gpio5(pdev);
+       } else if (type == w83687thf) {
+               data->vid = w83687thf_read_vid(pdev);
        }
 
        /* Read VRM & OVT Config only once */
-       if (w83627thf == data->type || w83637hf == data->type
-        || w83687thf == data->type) {
+       if (type == w83627thf || type == w83637hf || type == w83687thf) {
                data->vrm_ovt = 
-                       w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
+                       w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
        }
 
-       /* Convert VID to voltage based on VRM */
-       data->vrm = vid_which_vrm();
-
-       tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
+       tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
        for (i = 1; i <= 3; i++) {
                if (!(tmp & BIT_SCFG1[i - 1])) {
                        data->sens[i - 1] = W83781D_DEFAULT_BETA;
                } else {
                        if (w83627hf_read_value
-                           (client,
+                           (data,
                             W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
                                data->sens[i - 1] = 1;
                        else
@@ -1441,38 +1400,37 @@ static void w83627hf_init_client(struct i2c_client *client)
 
        if(init) {
                /* Enable temp2 */
-               tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
+               tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
                if (tmp & 0x01) {
-                       dev_warn(&client->dev, "Enabling temp2, readings "
+                       dev_warn(&pdev->dev, "Enabling temp2, readings "
                                 "might not make sense\n");
-                       w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG,
+                       w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
                                tmp & 0xfe);
                }
 
                /* Enable temp3 */
                if (type != w83697hf) {
-                       tmp = w83627hf_read_value(client,
+                       tmp = w83627hf_read_value(data,
                                W83781D_REG_TEMP3_CONFIG);
                        if (tmp & 0x01) {
-                               dev_warn(&client->dev, "Enabling temp3, "
+                               dev_warn(&pdev->dev, "Enabling temp3, "
                                         "readings might not make sense\n");
-                               w83627hf_write_value(client,
+                               w83627hf_write_value(data,
                                        W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
                        }
                }
        }
 
        /* Start monitoring */
-       w83627hf_write_value(client, W83781D_REG_CONFIG,
-                           (w83627hf_read_value(client,
+       w83627hf_write_value(data, W83781D_REG_CONFIG,
+                           (w83627hf_read_value(data,
                                                W83781D_REG_CONFIG) & 0xf7)
                            | 0x01);
 }
 
 static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83627hf_data *data = i2c_get_clientdata(client);
+       struct w83627hf_data *data = dev_get_drvdata(dev);
        int i;
 
        mutex_lock(&data->update_lock);
@@ -1486,23 +1444,23 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
                            && (i == 5 || i == 6)))
                                continue;
                        data->in[i] =
-                           w83627hf_read_value(client, W83781D_REG_IN(i));
+                           w83627hf_read_value(data, W83781D_REG_IN(i));
                        data->in_min[i] =
-                           w83627hf_read_value(client,
+                           w83627hf_read_value(data,
                                               W83781D_REG_IN_MIN(i));
                        data->in_max[i] =
-                           w83627hf_read_value(client,
+                           w83627hf_read_value(data,
                                               W83781D_REG_IN_MAX(i));
                }
                for (i = 1; i <= 3; i++) {
                        data->fan[i - 1] =
-                           w83627hf_read_value(client, W83781D_REG_FAN(i));
+                           w83627hf_read_value(data, W83781D_REG_FAN(i));
                        data->fan_min[i - 1] =
-                           w83627hf_read_value(client,
+                           w83627hf_read_value(data,
                                               W83781D_REG_FAN_MIN(i));
                }
                for (i = 1; i <= 3; i++) {
-                       u8 tmp = w83627hf_read_value(client,
+                       u8 tmp = w83627hf_read_value(data,
                                W836X7HF_REG_PWM(data->type, i));
                        /* bits 0-3 are reserved  in 627THF */
                        if (data->type == w83627thf)
@@ -1513,47 +1471,47 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
                                break;
                }
 
-               data->temp = w83627hf_read_value(client, W83781D_REG_TEMP(1));
+               data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
                data->temp_max =
-                   w83627hf_read_value(client, W83781D_REG_TEMP_OVER(1));
+                   w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
                data->temp_max_hyst =
-                   w83627hf_read_value(client, W83781D_REG_TEMP_HYST(1));
+                   w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
                data->temp_add[0] =
-                   w83627hf_read_value(client, W83781D_REG_TEMP(2));
+                   w83627hf_read_value(data, W83781D_REG_TEMP(2));
                data->temp_max_add[0] =
-                   w83627hf_read_value(client, W83781D_REG_TEMP_OVER(2));
+                   w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
                data->temp_max_hyst_add[0] =
-                   w83627hf_read_value(client, W83781D_REG_TEMP_HYST(2));
+                   w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
                if (data->type != w83697hf) {
                        data->temp_add[1] =
-                         w83627hf_read_value(client, W83781D_REG_TEMP(3));
+                         w83627hf_read_value(data, W83781D_REG_TEMP(3));
                        data->temp_max_add[1] =
-                         w83627hf_read_value(client, W83781D_REG_TEMP_OVER(3));
+                         w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
                        data->temp_max_hyst_add[1] =
-                         w83627hf_read_value(client, W83781D_REG_TEMP_HYST(3));
+                         w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
                }
 
-               i = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
+               i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
                data->fan_div[0] = (i >> 4) & 0x03;
                data->fan_div[1] = (i >> 6) & 0x03;
                if (data->type != w83697hf) {
-                       data->fan_div[2] = (w83627hf_read_value(client,
+                       data->fan_div[2] = (w83627hf_read_value(data,
                                               W83781D_REG_PIN) >> 6) & 0x03;
                }
-               i = w83627hf_read_value(client, W83781D_REG_VBAT);
+               i = w83627hf_read_value(data, W83781D_REG_VBAT);
                data->fan_div[0] |= (i >> 3) & 0x04;
                data->fan_div[1] |= (i >> 4) & 0x04;
                if (data->type != w83697hf)
                        data->fan_div[2] |= (i >> 5) & 0x04;
                data->alarms =
-                   w83627hf_read_value(client, W83781D_REG_ALARM1) |
-                   (w83627hf_read_value(client, W83781D_REG_ALARM2) << 8) |
-                   (w83627hf_read_value(client, W83781D_REG_ALARM3) << 16);
-               i = w83627hf_read_value(client, W83781D_REG_BEEP_INTS2);
+                   w83627hf_read_value(data, W83781D_REG_ALARM1) |
+                   (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
+                   (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
+               i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
                data->beep_enable = i >> 7;
                data->beep_mask = ((i & 0x7f) << 8) |
-                   w83627hf_read_value(client, W83781D_REG_BEEP_INTS1) |
-                   w83627hf_read_value(client, W83781D_REG_BEEP_INTS3) << 16;
+                   w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
+                   w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
                data->last_updated = jiffies;
                data->valid = 1;
        }
@@ -1563,19 +1521,87 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
        return data;
 }
 
+static int __init w83627hf_device_add(unsigned short address,
+                                     const struct w83627hf_sio_data *sio_data)
+{
+       struct resource res = {
+               .start  = address + WINB_REGION_OFFSET,
+               .end    = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
+               .name   = DRVNAME,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc(DRVNAME, address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data),
+                                         GFP_KERNEL);
+       if (!pdev->dev.platform_data) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+               goto exit_device_put;
+       }
+       memcpy(pdev->dev.platform_data, sio_data,
+              sizeof(struct w83627hf_sio_data));
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(pdev);
+exit:
+       return err;
+}
+
 static int __init sensors_w83627hf_init(void)
 {
-       if (w83627hf_find(0x2e, &address)
-        && w83627hf_find(0x4e, &address)) {
+       int err;
+       unsigned short address;
+       struct w83627hf_sio_data sio_data;
+
+       if (w83627hf_find(0x2e, &address, &sio_data)
+        && w83627hf_find(0x4e, &address, &sio_data))
                return -ENODEV;
-       }
 
-       return i2c_isa_add_driver(&w83627hf_driver);
+       err = platform_driver_register(&w83627hf_driver);
+       if (err)
+               goto exit;
+
+       /* Sets global pdev as a side effect */
+       err = w83627hf_device_add(address, &sio_data);
+       if (err)
+               goto exit_driver;
+
+       return 0;
+
+exit_driver:
+       platform_driver_unregister(&w83627hf_driver);
+exit:
+       return err;
 }
 
 static void __exit sensors_w83627hf_exit(void)
 {
-       i2c_isa_del_driver(&w83627hf_driver);
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&w83627hf_driver);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
index a47da3ec5472e61eaab91f5c837df97f708502e0..f85b48fea1c4700d566edd5413ed265ec4e382b9 100644 (file)
@@ -2,8 +2,9 @@
     w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
                 monitoring
     Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>,
-    Philip Edelbrock <phil@netroedge.com>,
-    and Mark Studebaker <mdsxyz123@yahoo.com>
+                               Philip Edelbrock <phil@netroedge.com>,
+                               and Mark Studebaker <mdsxyz123@yahoo.com>
+    Copyright (c) 2007         Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
 #include "lm75.h"
 
+/* ISA device, if found */
+static struct platform_device *pdev;
+
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
                                        0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
@@ -75,8 +81,8 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 #define W83781D_ADDR_REG_OFFSET                5
 #define W83781D_DATA_REG_OFFSET                6
 
-/* The W83781D registers */
-/* The W83782D registers for nr=7,8 are in bank 5 */
+/* The device registers */
+/* in nr from 0 to 8 */
 #define W83781D_REG_IN_MAX(nr)         ((nr < 7) ? (0x2b + (nr) * 2) : \
                                                    (0x554 + (((nr) - 7) * 2)))
 #define W83781D_REG_IN_MIN(nr)         ((nr < 7) ? (0x2c + (nr) * 2) : \
@@ -84,12 +90,14 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 #define W83781D_REG_IN(nr)             ((nr < 7) ? (0x20 + (nr)) : \
                                                    (0x550 + (nr) - 7))
 
-#define W83781D_REG_FAN_MIN(nr)                (0x3a + (nr))
-#define W83781D_REG_FAN(nr)            (0x27 + (nr))
+/* fan nr from 0 to 2 */
+#define W83781D_REG_FAN_MIN(nr)                (0x3b + (nr))
+#define W83781D_REG_FAN(nr)            (0x28 + (nr))
 
 #define W83781D_REG_BANK               0x4E
 #define W83781D_REG_TEMP2_CONFIG       0x152
 #define W83781D_REG_TEMP3_CONFIG       0x252
+/* temp nr from 1 to 3 */
 #define W83781D_REG_TEMP(nr)           ((nr == 3) ? (0x0250) : \
                                        ((nr == 2) ? (0x0150) : \
                                                     (0x27)))
@@ -127,19 +135,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 #define W83781D_REG_VBAT               0x5D
 
 /* PWM 782D (1-4) and 783S (1-2) only */
-#define W83781D_REG_PWM1               0x5B    /* 782d and 783s/627hf datasheets disagree */
-                                               /* on which is which; */
-#define W83781D_REG_PWM2               0x5A    /* We follow the 782d convention here, */
-                                               /* However 782d is probably wrong. */
-#define W83781D_REG_PWM3               0x5E
-#define W83781D_REG_PWM4               0x5F
+static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F };
 #define W83781D_REG_PWMCLK12           0x5C
 #define W83781D_REG_PWMCLK34           0x45C
-static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
-       W83781D_REG_PWM3, W83781D_REG_PWM4
-};
-
-#define W83781D_REG_PWM(nr)            (regpwm[(nr) - 1])
 
 #define W83781D_REG_I2C_ADDR           0x48
 #define W83781D_REG_I2C_SUBADDR                0x4A
@@ -159,12 +157,9 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
 #define W83781D_REG_RT_IDX             0x50
 #define W83781D_REG_RT_VAL             0x51
 
-/* Conversions. Rounding and limit checking is only done on the TO_REG
-   variants. Note that you should be a bit careful with which arguments
-   these macros are called: arguments may be evaluated more than once.
-   Fixing this is just not worth it. */
-#define IN_TO_REG(val)                 (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
-#define IN_FROM_REG(val)               (((val) * 16) / 10)
+/* Conversions */
+#define IN_TO_REG(val)                 SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
+#define IN_FROM_REG(val)               ((val) * 16)
 
 static inline u8
 FAN_TO_REG(long rpm, int div)
@@ -175,24 +170,24 @@ FAN_TO_REG(long rpm, int div)
        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
-#define FAN_FROM_REG(val,div)          ((val) == 0   ? -1 : \
-                                       ((val) == 255 ? 0 : \
-                                                       1350000 / ((val) * (div))))
+static inline long
+FAN_FROM_REG(u8 val, int div)
+{
+       if (val == 0)
+               return -1;
+       if (val == 255)
+               return 0;
+       return 1350000 / (val * div);
+}
 
-#define TEMP_TO_REG(val)               (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
-                                               : (val)) / 1000, 0, 0xff))
-#define TEMP_FROM_REG(val)             (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+#define TEMP_TO_REG(val)               SENSORS_LIMIT((val) / 1000, -127, 128)
+#define TEMP_FROM_REG(val)             ((val) * 1000)
 
-#define PWM_FROM_REG(val)              (val)
-#define PWM_TO_REG(val)                        (SENSORS_LIMIT((val),0,255))
 #define BEEP_MASK_FROM_REG(val,type)   ((type) == as99127f ? \
                                         (val) ^ 0x7fff : (val))
 #define BEEP_MASK_TO_REG(val,type)     ((type) == as99127f ? \
                                         (~(val)) & 0x7fff : (val) & 0xffffff)
 
-#define BEEP_ENABLE_TO_REG(val)                ((val) ? 1 : 0)
-#define BEEP_ENABLE_FROM_REG(val)      ((val) ? 1 : 0)
-
 #define DIV_FROM_REG(val)              (1 << (val))
 
 static inline u8
@@ -207,7 +202,7 @@ DIV_TO_REG(long val, enum chips type)
                        break;
                val >>= 1;
        }
-       return ((u8) i);
+       return i;
 }
 
 /* There are some complications in a module like this. First off, W83781D chips
@@ -221,8 +216,8 @@ DIV_TO_REG(long val, enum chips type)
    a bit - except if there could be more than one SMBus. Groan. No solution
    for this yet. */
 
-/* For each registered chip, we need to keep some data in memory.
-   The structure is dynamically allocated. */
+/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
+   the driver field to differentiate between I2C and ISA chips. */
 struct w83781d_data {
        struct i2c_client client;
        struct class_device *class_dev;
@@ -241,9 +236,9 @@ struct w83781d_data {
        u8 in_min[9];           /* Register value - 8 & 9 for 782D only */
        u8 fan[3];              /* Register value */
        u8 fan_min[3];          /* Register value */
-       u8 temp;
-       u8 temp_max;            /* Register value */
-       u8 temp_max_hyst;       /* Register value */
+       s8 temp;                /* Register value */
+       s8 temp_max;            /* Register value */
+       s8 temp_max_hyst;       /* Register value */
        u16 temp_add[2];        /* Register value */
        u16 temp_max_add[2];    /* Register value */
        u16 temp_max_hyst_add[2];       /* Register value */
@@ -253,7 +248,7 @@ struct w83781d_data {
        u32 beep_mask;          /* Register encoding, combined */
        u8 beep_enable;         /* Boolean */
        u8 pwm[4];              /* Register value */
-       u8 pwmenable[4];        /* Boolean */
+       u8 pwm2_enable;         /* Boolean */
        u16 sens[3];            /* 782D/783S only.
                                   1 = pentium diode; 2 = 3904 diode;
                                   3000-5000 = thermistor beta.
@@ -263,14 +258,16 @@ struct w83781d_data {
 };
 
 static int w83781d_attach_adapter(struct i2c_adapter *adapter);
-static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
 static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
 static int w83781d_detach_client(struct i2c_client *client);
 
-static int w83781d_read_value(struct i2c_client *client, u16 reg);
-static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value);
+static int __devinit w83781d_isa_probe(struct platform_device *pdev);
+static int __devexit w83781d_isa_remove(struct platform_device *pdev);
+
+static int w83781d_read_value(struct w83781d_data *data, u16 reg);
+static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
 static struct w83781d_data *w83781d_update_device(struct device *dev);
-static void w83781d_init_client(struct i2c_client *client);
+static void w83781d_init_device(struct device *dev);
 
 static struct i2c_driver w83781d_driver = {
        .driver = {
@@ -281,39 +278,44 @@ static struct i2c_driver w83781d_driver = {
        .detach_client = w83781d_detach_client,
 };
 
-static struct i2c_driver w83781d_isa_driver = {
+static struct platform_driver w83781d_isa_driver = {
        .driver = {
                .owner = THIS_MODULE,
-               .name = "w83781d-isa",
+               .name = "w83781d",
        },
-       .attach_adapter = w83781d_isa_attach_adapter,
-       .detach_client = w83781d_detach_client,
+       .probe = w83781d_isa_probe,
+       .remove = w83781d_isa_remove,
 };
 
 
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
-static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+               char *buf) \
 { \
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
        struct w83781d_data *data = w83781d_update_device(dev); \
-       return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \
+       return sprintf(buf, "%ld\n", \
+                      (long)IN_FROM_REG(data->reg[attr->index])); \
 }
 show_in_reg(in);
 show_in_reg(in_min);
 show_in_reg(in_max);
 
 #define store_in_reg(REG, reg) \
-static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+static ssize_t store_in_##reg (struct device *dev, struct device_attribute \
+               *da, const char *buf, size_t count) \
 { \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct w83781d_data *data = i2c_get_clientdata(client); \
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
+       struct w83781d_data *data = dev_get_drvdata(dev); \
+       int nr = attr->index; \
        u32 val; \
         \
-       val = simple_strtoul(buf, NULL, 10) / 10; \
+       val = simple_strtoul(buf, NULL, 10); \
         \
        mutex_lock(&data->update_lock); \
        data->in_##reg[nr] = IN_TO_REG(val); \
-       w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
+       w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
         \
        mutex_unlock(&data->update_lock); \
        return count; \
@@ -321,29 +323,13 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count
 store_in_reg(MIN, min);
 store_in_reg(MAX, max);
 
-#define sysfs_in_offset(offset) \
-static ssize_t \
-show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-        return show_in(dev, buf, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
-
-#define sysfs_in_reg_offset(reg, offset) \
-static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_in_##reg (dev, buf, offset); \
-} \
-static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-       return store_in_##reg (dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset);
-
 #define sysfs_in_offsets(offset) \
-sysfs_in_offset(offset); \
-sysfs_in_reg_offset(min, offset); \
-sysfs_in_reg_offset(max, offset);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+               show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+               show_in_min, store_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+               show_in_max, store_in_max, offset)
 
 sysfs_in_offsets(0);
 sysfs_in_offsets(1);
@@ -356,63 +342,56 @@ sysfs_in_offsets(7);
 sysfs_in_offsets(8);
 
 #define show_fan_reg(reg) \
-static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+               char *buf) \
 { \
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
        struct w83781d_data *data = w83781d_update_device(dev); \
        return sprintf(buf,"%ld\n", \
-               FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
+               FAN_FROM_REG(data->reg[attr->index], \
+                       DIV_FROM_REG(data->fan_div[attr->index]))); \
 }
 show_fan_reg(fan);
 show_fan_reg(fan_min);
 
 static ssize_t
-store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+store_fan_min(struct device *dev, struct device_attribute *da,
+               const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
-       data->fan_min[nr - 1] =
-           FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
-       w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
-                           data->fan_min[nr - 1]);
+       data->fan_min[nr] =
+           FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+       w83781d_write_value(data, W83781D_REG_FAN_MIN(nr),
+                           data->fan_min[nr]);
 
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-#define sysfs_fan_offset(offset) \
-static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_fan(dev, buf, offset); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
-
-#define sysfs_fan_min_offset(offset) \
-static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_fan_min(dev, buf, offset); \
-} \
-static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-       return store_fan_min(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset);
-
-sysfs_fan_offset(1);
-sysfs_fan_min_offset(1);
-sysfs_fan_offset(2);
-sysfs_fan_min_offset(2);
-sysfs_fan_offset(3);
-sysfs_fan_min_offset(3);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
+               show_fan_min, store_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
+               show_fan_min, store_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
+               show_fan_min, store_fan_min, 2);
 
 #define show_temp_reg(reg) \
-static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+               char *buf) \
 { \
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
        struct w83781d_data *data = w83781d_update_device(dev); \
+       int nr = attr->index; \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
                return sprintf(buf,"%d\n", \
                        LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
@@ -425,10 +404,12 @@ show_temp_reg(temp_max);
 show_temp_reg(temp_max_hyst);
 
 #define store_temp_reg(REG, reg) \
-static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+static ssize_t store_temp_##reg (struct device *dev, \
+               struct device_attribute *da, const char *buf, size_t count) \
 { \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct w83781d_data *data = i2c_get_clientdata(client); \
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
+       struct w83781d_data *data = dev_get_drvdata(dev); \
+       int nr = attr->index; \
        s32 val; \
         \
        val = simple_strtol(buf, NULL, 10); \
@@ -437,11 +418,11 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
         \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
                data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
-               w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+               w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
                                data->temp_##reg##_add[nr-2]); \
        } else {        /* TEMP1 */ \
                data->temp_##reg = TEMP_TO_REG(val); \
-               w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+               w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
                        data->temp_##reg); \
        } \
         \
@@ -451,29 +432,13 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
 store_temp_reg(OVER, max);
 store_temp_reg(HYST, max_hyst);
 
-#define sysfs_temp_offset(offset) \
-static ssize_t \
-show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_temp(dev, buf, offset); \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
-
-#define sysfs_temp_reg_offset(reg, offset) \
-static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_temp_##reg (dev, buf, offset); \
-} \
-static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-       return store_temp_##reg (dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset);
-
 #define sysfs_temp_offsets(offset) \
-sysfs_temp_offset(offset); \
-sysfs_temp_reg_offset(max, offset); \
-sysfs_temp_reg_offset(max_hyst, offset);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+               show_temp, NULL, offset); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+               show_temp_max, store_temp_max, offset); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
+               show_temp_max_hyst, store_temp_max_hyst, offset);
 
 sysfs_temp_offsets(1);
 sysfs_temp_offsets(2);
@@ -498,8 +463,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 static ssize_t
 store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct w83781d_data *data = dev_get_drvdata(dev);
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -528,68 +492,67 @@ static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr
 static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n",
-                      (long)BEEP_ENABLE_FROM_REG(data->beep_enable));
+       return sprintf(buf, "%ld\n", (long)data->beep_enable);
 }
 
-#define BEEP_ENABLE                    0       /* Store beep_enable */
-#define BEEP_MASK                      1       /* Store beep_mask */
-
 static ssize_t
-store_beep_reg(struct device *dev, const char *buf, size_t count,
-              int update_mask)
+store_beep_mask(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
-       u32 val, val2;
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
+       data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
+       w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
+                           data->beep_mask & 0xff);
+       w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
+                           ((data->beep_mask >> 8) & 0x7f)
+                           | data->beep_enable << 7);
+       if (data->type != w83781d && data->type != as99127f) {
+               w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
+                                   ((data->beep_mask) >> 16) & 0xff);
+       }
+       mutex_unlock(&data->update_lock);
 
-       if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
-               data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
-               w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
-                                   data->beep_mask & 0xff);
-
-               if ((data->type != w83781d) && (data->type != as99127f)) {
-                       w83781d_write_value(client, W83781D_REG_BEEP_INTS3,
-                                           ((data->beep_mask) >> 16) & 0xff);
-               }
+       return count;
+}
 
-               val2 = (data->beep_mask >> 8) & 0x7f;
-       } else {                /* We are storing beep_enable */
-               val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
-               data->beep_enable = BEEP_ENABLE_TO_REG(val);
-       }
+static ssize_t
+store_beep_enable(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       u32 val;
 
-       w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
-                           val2 | data->beep_enable << 7);
+       val = simple_strtoul(buf, NULL, 10);
+       if (val != 0 && val != 1)
+               return -EINVAL;
 
+       mutex_lock(&data->update_lock);
+       data->beep_enable = val;
+       val = w83781d_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
+       val |= data->beep_enable << 7;
+       w83781d_write_value(data, W83781D_REG_BEEP_INTS2, val);
        mutex_unlock(&data->update_lock);
+
        return count;
 }
 
-#define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_beep_##reg(dev, attr, buf); \
-} \
-static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-       return store_beep_reg(dev, buf, count, BEEP_##REG); \
-} \
-static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg);
-
-sysfs_beep(ENABLE, enable);
-sysfs_beep(MASK, mask);
+static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+               show_beep_mask, store_beep_mask);
+static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+               show_beep_enable, store_beep_enable);
 
 static ssize_t
-show_fan_div_reg(struct device *dev, char *buf, int nr)
+show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct w83781d_data *data = w83781d_update_device(dev);
        return sprintf(buf, "%ld\n",
-                      (long) DIV_FROM_REG(data->fan_div[nr - 1]));
+                      (long) DIV_FROM_REG(data->fan_div[attr->index]));
 }
 
 /* Note: we save and restore the fan minimum here, because its value is
@@ -597,11 +560,13 @@ show_fan_div_reg(struct device *dev, char *buf, int nr)
    least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
-store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
+store_fan_div(struct device *dev, struct device_attribute *da,
+               const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct w83781d_data *data = dev_get_drvdata(dev);
        unsigned long min;
+       int nr = attr->index;
        u8 reg;
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
@@ -613,77 +578,72 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        data->fan_div[nr] = DIV_TO_REG(val, data->type);
 
-       reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
+       reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
               & (nr==0 ? 0xcf : 0x3f))
            | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
-       w83781d_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
+       w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
 
        /* w83781d and as99127f don't have extended divisor bits */
        if (data->type != w83781d && data->type != as99127f) {
-               reg = (w83781d_read_value(client, W83781D_REG_VBAT)
+               reg = (w83781d_read_value(data, W83781D_REG_VBAT)
                       & ~(1 << (5 + nr)))
                    | ((data->fan_div[nr] & 0x04) << (3 + nr));
-               w83781d_write_value(client, W83781D_REG_VBAT, reg);
+               w83781d_write_value(data, W83781D_REG_VBAT, reg);
        }
 
        /* Restore fan_min */
        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-       w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+       w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]);
 
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-#define sysfs_fan_div(offset) \
-static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_fan_div_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-       return store_fan_div_reg(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset);
-
-sysfs_fan_div(1);
-sysfs_fan_div(2);
-sysfs_fan_div(3);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+               show_fan_div, store_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+               show_fan_div, store_fan_div, 1);
+static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR,
+               show_fan_div, store_fan_div, 2);
 
 static ssize_t
-show_pwm_reg(struct device *dev, char *buf, int nr)
+show_pwm(struct device *dev, struct device_attribute *da, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
+       return sprintf(buf, "%d\n", (int)data->pwm[attr->index]);
 }
 
 static ssize_t
-show_pwmenable_reg(struct device *dev, char *buf, int nr)
+show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf)
 {
        struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]);
+       return sprintf(buf, "%d\n", (int)data->pwm2_enable);
 }
 
 static ssize_t
-store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
+store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
+               size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
-       data->pwm[nr - 1] = PWM_TO_REG(val);
-       w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
+       data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
+       w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
 static ssize_t
-store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
+store_pwm2_enable(struct device *dev, struct device_attribute *da,
+               const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct w83781d_data *data = dev_get_drvdata(dev);
        u32 val, reg;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -693,15 +653,15 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
        switch (val) {
        case 0:
        case 1:
-               reg = w83781d_read_value(client, W83781D_REG_PWMCLK12);
-               w83781d_write_value(client, W83781D_REG_PWMCLK12,
+               reg = w83781d_read_value(data, W83781D_REG_PWMCLK12);
+               w83781d_write_value(data, W83781D_REG_PWMCLK12,
                                    (reg & 0xf7) | (val << 3));
 
-               reg = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
-               w83781d_write_value(client, W83781D_REG_BEEP_CONFIG,
+               reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
+               w83781d_write_value(data, W83781D_REG_BEEP_CONFIG,
                                    (reg & 0xef) | (!val << 4));
 
-               data->pwmenable[nr - 1] = val;
+               data->pwm2_enable = val;
                break;
 
        default:
@@ -713,50 +673,29 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
        return count;
 }
 
-#define sysfs_pwm(offset) \
-static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_pwm_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \
-               const char *buf, size_t count) \
-{ \
-       return store_pwm_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
-               show_regs_pwm_##offset, store_regs_pwm_##offset);
-
-#define sysfs_pwmenable(offset) \
-static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       return show_pwmenable_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \
-               const char *buf, size_t count) \
-{ \
-       return store_pwmenable_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
-               show_regs_pwmenable_##offset, store_regs_pwmenable_##offset);
-
-sysfs_pwm(1);
-sysfs_pwm(2);
-sysfs_pwmenable(2);            /* only PWM2 can be enabled/disabled */
-sysfs_pwm(3);
-sysfs_pwm(4);
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3);
+/* only PWM2 can be enabled/disabled */
+static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+               show_pwm2_enable, store_pwm2_enable);
 
 static ssize_t
-show_sensor_reg(struct device *dev, char *buf, int nr)
+show_sensor(struct device *dev, struct device_attribute *da, char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
+       return sprintf(buf, "%d\n", (int)data->sens[attr->index]);
 }
 
 static ssize_t
-store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
+store_sensor(struct device *dev, struct device_attribute *da,
+               const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       int nr = attr->index;
        u32 val, tmp;
 
        val = simple_strtoul(buf, NULL, 10);
@@ -765,28 +704,28 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        switch (val) {
        case 1:         /* PII/Celeron diode */
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
-               w83781d_write_value(client, W83781D_REG_SCFG1,
-                                   tmp | BIT_SCFG1[nr - 1]);
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
-               w83781d_write_value(client, W83781D_REG_SCFG2,
-                                   tmp | BIT_SCFG2[nr - 1]);
-               data->sens[nr - 1] = val;
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
+               w83781d_write_value(data, W83781D_REG_SCFG1,
+                                   tmp | BIT_SCFG1[nr]);
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
+               w83781d_write_value(data, W83781D_REG_SCFG2,
+                                   tmp | BIT_SCFG2[nr]);
+               data->sens[nr] = val;
                break;
        case 2:         /* 3904 */
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
-               w83781d_write_value(client, W83781D_REG_SCFG1,
-                                   tmp | BIT_SCFG1[nr - 1]);
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
-               w83781d_write_value(client, W83781D_REG_SCFG2,
-                                   tmp & ~BIT_SCFG2[nr - 1]);
-               data->sens[nr - 1] = val;
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
+               w83781d_write_value(data, W83781D_REG_SCFG1,
+                                   tmp | BIT_SCFG1[nr]);
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
+               w83781d_write_value(data, W83781D_REG_SCFG2,
+                                   tmp & ~BIT_SCFG2[nr]);
+               data->sens[nr] = val;
                break;
        case W83781D_DEFAULT_BETA:      /* thermistor */
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
-               w83781d_write_value(client, W83781D_REG_SCFG1,
-                                   tmp & ~BIT_SCFG1[nr - 1]);
-               data->sens[nr - 1] = val;
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
+               w83781d_write_value(data, W83781D_REG_SCFG1,
+                                   tmp & ~BIT_SCFG1[nr]);
+               data->sens[nr] = val;
                break;
        default:
                dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n",
@@ -798,20 +737,22 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
        return count;
 }
 
-#define sysfs_sensor(offset) \
-static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-    return show_sensor_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-    return store_sensor_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset);
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
+       show_sensor, store_sensor, 0);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
+       show_sensor, store_sensor, 0);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
+       show_sensor, store_sensor, 0);
 
-sysfs_sensor(1);
-sysfs_sensor(2);
-sysfs_sensor(3);
+/* I2C devices get this name attribute automatically, but for ISA devices
+   we must create it by ourselves. */
+static ssize_t
+show_name(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%s\n", data->client.name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 /* This function is called when:
      * w83781d_driver is inserted (when this module is loaded), for each
@@ -825,12 +766,6 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, w83781d_detect);
 }
 
-static int
-w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
-{
-       return w83781d_detect(adapter, isa_address, -1);
-}
-
 /* Assumes that adapter is of I2C, not ISA variety.
  * OTHERWISE DON'T CALL THIS
  */
@@ -862,12 +797,12 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
                                goto ERROR_SC_1;
                        }
                }
-               w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR,
+               w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
                                (force_subclients[2] & 0x07) |
                                ((force_subclients[3] & 0x07) << 4));
                data->lm75[0]->addr = force_subclients[2];
        } else {
-               val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR);
+               val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
                data->lm75[0]->addr = 0x48 + (val1 & 0x07);
        }
 
@@ -937,20 +872,20 @@ ERROR_SC_0:
        return err;
 }
 
-#define IN_UNIT_ATTRS(X)                       \
-       &dev_attr_in##X##_input.attr,           \
-       &dev_attr_in##X##_min.attr,             \
-       &dev_attr_in##X##_max.attr
+#define IN_UNIT_ATTRS(X)                                       \
+       &sensor_dev_attr_in##X##_input.dev_attr.attr,           \
+       &sensor_dev_attr_in##X##_min.dev_attr.attr,             \
+       &sensor_dev_attr_in##X##_max.dev_attr.attr
 
-#define FAN_UNIT_ATTRS(X)                      \
-       &dev_attr_fan##X##_input.attr,          \
-       &dev_attr_fan##X##_min.attr,            \
-       &dev_attr_fan##X##_div.attr
+#define FAN_UNIT_ATTRS(X)                                      \
+       &sensor_dev_attr_fan##X##_input.dev_attr.attr,          \
+       &sensor_dev_attr_fan##X##_min.dev_attr.attr,            \
+       &sensor_dev_attr_fan##X##_div.dev_attr.attr
 
-#define TEMP_UNIT_ATTRS(X)                     \
-       &dev_attr_temp##X##_input.attr,         \
-       &dev_attr_temp##X##_max.attr,           \
-       &dev_attr_temp##X##_max_hyst.attr
+#define TEMP_UNIT_ATTRS(X)                                     \
+       &sensor_dev_attr_temp##X##_input.dev_attr.attr,         \
+       &sensor_dev_attr_temp##X##_max.dev_attr.attr,           \
+       &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr
 
 static struct attribute* w83781d_attributes[] = {
        IN_UNIT_ATTRS(0),
@@ -980,91 +915,115 @@ static struct attribute *w83781d_attributes_opt[] = {
        IN_UNIT_ATTRS(7),
        IN_UNIT_ATTRS(8),
        TEMP_UNIT_ATTRS(3),
-       &dev_attr_pwm1.attr,
-       &dev_attr_pwm2.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm3.dev_attr.attr,
+       &sensor_dev_attr_pwm4.dev_attr.attr,
        &dev_attr_pwm2_enable.attr,
-       &dev_attr_pwm3.attr,
-       &dev_attr_pwm4.attr,
-       &dev_attr_temp1_type.attr,
-       &dev_attr_temp2_type.attr,
-       &dev_attr_temp3_type.attr,
+       &sensor_dev_attr_temp1_type.dev_attr.attr,
+       &sensor_dev_attr_temp2_type.dev_attr.attr,
+       &sensor_dev_attr_temp3_type.dev_attr.attr,
        NULL
 };
 static const struct attribute_group w83781d_group_opt = {
        .attrs = w83781d_attributes_opt,
 };
 
+/* No clean up is done on error, it's up to the caller */
 static int
-w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
+w83781d_create_files(struct device *dev, int kind, int is_isa)
 {
-       int i = 0, val1 = 0, val2;
-       struct i2c_client *client;
-       struct device *dev;
-       struct w83781d_data *data;
        int err;
-       const char *client_name = "";
-       int is_isa = i2c_is_isa_adapter(adapter);
-       enum vendor { winbond, asus } vendid;
 
-       if (!is_isa
-           && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-               err = -EINVAL;
-               goto ERROR0;
+       if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
+               return err;
+
+       if (kind != w83783s) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_in1_input.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in1_min.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in1_max.dev_attr)))
+                       return err;
+       }
+       if (kind != as99127f && kind != w83781d && kind != w83783s) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_in7_input.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in7_min.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in7_max.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in8_input.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in8_min.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_in8_max.dev_attr)))
+                       return err;
+       }
+       if (kind != w83783s) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_temp3_input.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_temp3_max.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_temp3_max_hyst.dev_attr)))
+                       return err;
        }
 
-       /* Prevent users from forcing a kind for a bus it isn't supposed
-          to possibly be on */
-       if (is_isa && (kind == as99127f || kind == w83783s)) {
-               dev_err(&adapter->dev,
-                       "Cannot force I2C-only chip for ISA address 0x%02x.\n",
-                       address);
-               err = -EINVAL;
-               goto ERROR0;
+       if (kind != w83781d && kind != as99127f) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_pwm1.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_pwm2.dev_attr))
+                   || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
+                       return err;
        }
-       
-       if (is_isa)
-               if (!request_region(address, W83781D_EXTENT,
-                                   w83781d_isa_driver.driver.name)) {
-                       dev_dbg(&adapter->dev, "Request of region "
-                               "0x%x-0x%x for w83781d failed\n", address,
-                               address + W83781D_EXTENT - 1);
-                       err = -EBUSY;
-                       goto ERROR0;
+       if (kind == w83782d && !is_isa) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_pwm3.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_pwm4.dev_attr)))
+                       return err;
+       }
+
+       if (kind != as99127f && kind != w83781d) {
+               if ((err = device_create_file(dev,
+                               &sensor_dev_attr_temp1_type.dev_attr))
+                   || (err = device_create_file(dev,
+                               &sensor_dev_attr_temp2_type.dev_attr)))
+                       return err;
+               if (kind != w83783s) {
+                       if ((err = device_create_file(dev,
+                                       &sensor_dev_attr_temp3_type.dev_attr)))
+                               return err;
                }
+       }
 
-       /* Probe whether there is anything available on this address. Already
-          done for SMBus clients */
-       if (kind < 0) {
-               if (is_isa) {
+       if (is_isa) {
+               err = device_create_file(&pdev->dev, &dev_attr_name);
+               if (err)
+                       return err;
+       }
 
-#define REALLY_SLOW_IO
-                       /* We need the timeouts for at least some LM78-like
-                          chips. But only if we read 'undefined' registers. */
-                       i = inb_p(address + 1);
-                       if (inb_p(address + 2) != i
-                        || inb_p(address + 3) != i
-                        || inb_p(address + 7) != i) {
-                               dev_dbg(&adapter->dev, "Detection of w83781d "
-                                       "chip failed at step 1\n");
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-#undef REALLY_SLOW_IO
+       return 0;
+}
 
-                       /* Let's just hope nothing breaks here */
-                       i = inb_p(address + 5) & 0x7f;
-                       outb_p(~i & 0x7f, address + 5);
-                       val2 = inb_p(address + 5) & 0x7f;
-                       if (val2 != (~i & 0x7f)) {
-                               outb_p(i, address + 5);
-                               dev_dbg(&adapter->dev, "Detection of w83781d "
-                                       "chip failed at step 2 (0x%x != "
-                                       "0x%x at 0x%x)\n", val2, ~i & 0x7f,
-                                       address + 5);
-                               err = -ENODEV;
-                               goto ERROR1;
-                       }
-               }
+static int
+w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       int val1 = 0, val2;
+       struct i2c_client *client;
+       struct device *dev;
+       struct w83781d_data *data;
+       int err;
+       const char *client_name = "";
+       enum vendor { winbond, asus } vendid;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               err = -EINVAL;
+               goto ERROR1;
        }
 
        /* OK. For now, we presume we have a valid client. We now create the
@@ -1081,8 +1040,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        client->addr = address;
        mutex_init(&data->lock);
        client->adapter = adapter;
-       client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
-       client->flags = 0;
+       client->driver = &w83781d_driver;
        dev = &client->dev;
 
        /* Now, we do the remaining detection. */
@@ -1092,14 +1050,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
           force_*=... parameter, and the Winbond will be reset to the right
           bank. */
        if (kind < 0) {
-               if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
+               if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
                        dev_dbg(&adapter->dev, "Detection of w83781d chip "
                                "failed at step 3\n");
                        err = -ENODEV;
                        goto ERROR2;
                }
-               val1 = w83781d_read_value(client, W83781D_REG_BANK);
-               val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
+               val1 = w83781d_read_value(data, W83781D_REG_BANK);
+               val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
                /* Check for Winbond or Asus ID if in bank 0 */
                if ((!(val1 & 0x07)) &&
                    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
@@ -1111,10 +1069,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                }
                /* If Winbond SMBus, check address at 0x48.
                   Asus doesn't support, except for as99127f rev.2 */
-               if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
-                                 ((val1 & 0x80) && (val2 == 0x5c)))) {
+               if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
+                   ((val1 & 0x80) && (val2 == 0x5c))) {
                        if (w83781d_read_value
-                           (client, W83781D_REG_I2C_ADDR) != address) {
+                           (data, W83781D_REG_I2C_ADDR) != address) {
                                dev_dbg(&adapter->dev, "Detection of w83781d "
                                        "chip failed at step 5\n");
                                err = -ENODEV;
@@ -1125,14 +1083,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* We have either had a force parameter, or we have already detected the
           Winbond. Put it now into bank 0 and Vendor ID High Byte */
-       w83781d_write_value(client, W83781D_REG_BANK,
-                           (w83781d_read_value(client, W83781D_REG_BANK)
+       w83781d_write_value(data, W83781D_REG_BANK,
+                           (w83781d_read_value(data, W83781D_REG_BANK)
                             & 0x78) | 0x80);
 
        /* Determine the chip type. */
        if (kind <= 0) {
                /* get vendor ID */
-               val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
+               val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
                if (val2 == 0x5c)
                        vendid = winbond;
                else if (val2 == 0x12)
@@ -1144,17 +1102,16 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                        goto ERROR2;
                }
 
-               val1 = w83781d_read_value(client, W83781D_REG_WCHIPID);
+               val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
                if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
                        kind = w83781d;
                else if (val1 == 0x30 && vendid == winbond)
                        kind = w83782d;
-               else if (val1 == 0x40 && vendid == winbond && !is_isa
-                               && address == 0x2d)
+               else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
                        kind = w83783s;
                else if (val1 == 0x21 && vendid == winbond)
                        kind = w83627hf;
-               else if (val1 == 0x31 && !is_isa && address >= 0x28)
+               else if (val1 == 0x31 && address >= 0x28)
                        kind = as99127f;
                else {
                        if (kind == 0)
@@ -1182,86 +1139,23 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        strlcpy(client->name, client_name, I2C_NAME_SIZE);
        data->type = kind;
 
-       data->valid = 0;
-       mutex_init(&data->update_lock);
-
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(client)))
                goto ERROR2;
 
        /* attach secondary i2c lm75-like clients */
-       if (!is_isa) {
-               if ((err = w83781d_detect_subclients(adapter, address,
-                               kind, client)))
-                       goto ERROR3;
-       } else {
-               data->lm75[0] = NULL;
-               data->lm75[1] = NULL;
-       }
+       if ((err = w83781d_detect_subclients(adapter, address,
+                       kind, client)))
+               goto ERROR3;
 
        /* Initialize the chip */
-       w83781d_init_client(client);
-
-       /* A few vars need to be filled upon startup */
-       for (i = 1; i <= 3; i++) {
-               data->fan_min[i - 1] = w83781d_read_value(client,
-                                       W83781D_REG_FAN_MIN(i));
-       }
-       if (kind != w83781d && kind != as99127f)
-               for (i = 0; i < 4; i++)
-                       data->pwmenable[i] = 1;
+       w83781d_init_device(dev);
 
        /* Register sysfs hooks */
-       if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
+       err = w83781d_create_files(dev, kind, 0);
+       if (err)
                goto ERROR4;
 
-       if (kind != w83783s) {
-               if ((err = device_create_file(dev, &dev_attr_in1_input))
-                   || (err = device_create_file(dev, &dev_attr_in1_min))
-                   || (err = device_create_file(dev, &dev_attr_in1_max)))
-                       goto ERROR4;
-       }
-       if (kind != as99127f && kind != w83781d && kind != w83783s) {
-               if ((err = device_create_file(dev, &dev_attr_in7_input))
-                   || (err = device_create_file(dev, &dev_attr_in7_min))
-                   || (err = device_create_file(dev, &dev_attr_in7_max))
-                   || (err = device_create_file(dev, &dev_attr_in8_input))
-                   || (err = device_create_file(dev, &dev_attr_in8_min))
-                   || (err = device_create_file(dev, &dev_attr_in8_max)))
-                       goto ERROR4;
-       }
-       if (kind != w83783s) {
-               if ((err = device_create_file(dev, &dev_attr_temp3_input))
-                   || (err = device_create_file(dev, &dev_attr_temp3_max))
-                   || (err = device_create_file(dev,
-                                                &dev_attr_temp3_max_hyst)))
-                       goto ERROR4;
-       }
-
-       if (kind != w83781d && kind != as99127f) {
-               if ((err = device_create_file(dev, &dev_attr_pwm1))
-                   || (err = device_create_file(dev, &dev_attr_pwm2))
-                   || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
-                       goto ERROR4;
-       }
-       if (kind == w83782d && !is_isa) {
-               if ((err = device_create_file(dev, &dev_attr_pwm3))
-                   || (err = device_create_file(dev, &dev_attr_pwm4)))
-                       goto ERROR4;
-       }
-
-       if (kind != as99127f && kind != w83781d) {
-               if ((err = device_create_file(dev, &dev_attr_temp1_type))
-                   || (err = device_create_file(dev,
-                                                &dev_attr_temp2_type)))
-                       goto ERROR4;
-               if (kind != w83783s) {
-                       if ((err = device_create_file(dev,
-                                                     &dev_attr_temp3_type)))
-                               goto ERROR4;
-               }
-       }
-
        data->class_dev = hwmon_device_register(dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
@@ -1287,9 +1181,6 @@ ERROR3:
 ERROR2:
        kfree(data);
 ERROR1:
-       if (is_isa)
-               release_region(address, W83781D_EXTENT);
-ERROR0:
        return err;
 }
 
@@ -1305,8 +1196,6 @@ w83781d_detach_client(struct i2c_client *client)
                sysfs_remove_group(&client->dev.kobj, &w83781d_group);
                sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
        }
-       if (i2c_is_isa_client(client))
-               release_region(client->addr, W83781D_EXTENT);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -1322,6 +1211,88 @@ w83781d_detach_client(struct i2c_client *client)
        return 0;
 }
 
+static int __devinit
+w83781d_isa_probe(struct platform_device *pdev)
+{
+       int err, reg;
+       struct w83781d_data *data;
+       struct resource *res;
+       const char *name;
+
+       /* Reserve the ISA region */
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, W83781D_EXTENT, "w83781d")) {
+               err = -EBUSY;
+               goto exit;
+       }
+
+       if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit_release_region;
+       }
+       mutex_init(&data->lock);
+       data->client.addr = res->start;
+       i2c_set_clientdata(&data->client, data);
+       platform_set_drvdata(pdev, data);
+
+       reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
+       switch (reg) {
+       case 0x21:
+               data->type = w83627hf;
+               name = "w83627hf";
+               break;
+       case 0x30:
+               data->type = w83782d;
+               name = "w83782d";
+               break;
+       default:
+               data->type = w83781d;
+               name = "w83781d";
+       }
+       strlcpy(data->client.name, name, I2C_NAME_SIZE);
+
+       /* Initialize the W83781D chip */
+       w83781d_init_device(&pdev->dev);
+
+       /* Register sysfs hooks */
+       err = w83781d_create_files(&pdev->dev, data->type, 1);
+       if (err)
+               goto exit_remove_files;
+
+       data->class_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
+       }
+
+       return 0;
+
+ exit_remove_files:
+       sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
+       sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       kfree(data);
+ exit_release_region:
+       release_region(res->start, W83781D_EXTENT);
+ exit:
+       return err;
+}
+
+static int __devexit
+w83781d_isa_remove(struct platform_device *pdev)
+{
+       struct w83781d_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
+       sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       release_region(data->client.addr, W83781D_EXTENT);
+       kfree(data);
+
+       return 0;
+}
+
 /* The SMBus locks itself, usually, but nothing may access the Winbond between
    bank switches. ISA access must always be locked explicitly! 
    We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
@@ -1329,14 +1300,14 @@ w83781d_detach_client(struct i2c_client *client)
    There are some ugly typecasts here, but the good news is - they should
    nowhere else be necessary! */
 static int
-w83781d_read_value(struct i2c_client *client, u16 reg)
+w83781d_read_value(struct w83781d_data *data, u16 reg)
 {
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct i2c_client *client = &data->client;
        int res, word_sized, bank;
        struct i2c_client *cl;
 
        mutex_lock(&data->lock);
-       if (i2c_is_isa_client(client)) {
+       if (!client->driver) { /* ISA device */
                word_sized = (((reg & 0xff00) == 0x100)
                              || ((reg & 0xff00) == 0x200))
                    && (((reg & 0x00ff) == 0x50)
@@ -1398,14 +1369,14 @@ w83781d_read_value(struct i2c_client *client, u16 reg)
 }
 
 static int
-w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
+w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
 {
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct i2c_client *client = &data->client;
        int word_sized, bank;
        struct i2c_client *cl;
 
        mutex_lock(&data->lock);
-       if (i2c_is_isa_client(client)) {
+       if (!client->driver) { /* ISA device */
                word_sized = (((reg & 0xff00) == 0x100)
                              || ((reg & 0xff00) == 0x200))
                    && (((reg & 0x00ff) == 0x53)
@@ -1462,13 +1433,18 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
 }
 
 static void
-w83781d_init_client(struct i2c_client *client)
+w83781d_init_device(struct device *dev)
 {
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct w83781d_data *data = dev_get_drvdata(dev);
        int i, p;
        int type = data->type;
        u8 tmp;
 
+       if (type == w83627hf)
+               dev_info(dev, "The W83627HF chip is better supported by the "
+                        "w83627hf driver, support will be dropped from the "
+                        "w83781d driver soon\n");
+
        if (reset && type != as99127f) { /* this resets registers we don't have
                                           documentation for on the as99127f */
                /* Resetting the chip has been the default for a long time,
@@ -1477,42 +1453,42 @@ w83781d_init_client(struct i2c_client *client)
                   It might even go away if nobody reports it as being useful,
                   as I see very little reason why this would be needed at
                   all. */
-               dev_info(&client->dev, "If reset=1 solved a problem you were "
+               dev_info(dev, "If reset=1 solved a problem you were "
                         "having, please report!\n");
 
                /* save these registers */
-               i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
-               p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+               i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
+               p = w83781d_read_value(data, W83781D_REG_PWMCLK12);
                /* Reset all except Watchdog values and last conversion values
                   This sets fan-divs to 2, among others */
-               w83781d_write_value(client, W83781D_REG_CONFIG, 0x80);
+               w83781d_write_value(data, W83781D_REG_CONFIG, 0x80);
                /* Restore the registers and disable power-on abnormal beep.
                   This saves FAN 1/2/3 input/output values set by BIOS. */
-               w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
-               w83781d_write_value(client, W83781D_REG_PWMCLK12, p);
+               w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
+               w83781d_write_value(data, W83781D_REG_PWMCLK12, p);
                /* Disable master beep-enable (reset turns it on).
                   Individual beep_mask should be reset to off but for some reason
                   disabling this bit helps some people not get beeped */
-               w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
+               w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
        }
 
        /* Disable power-on abnormal beep, as advised by the datasheet.
           Already done if reset=1. */
        if (init && !reset && type != as99127f) {
-               i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
-               w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
+               i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
+               w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
        }
 
        data->vrm = vid_which_vrm();
 
        if ((type != w83781d) && (type != as99127f)) {
-               tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+               tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
                for (i = 1; i <= 3; i++) {
                        if (!(tmp & BIT_SCFG1[i - 1])) {
                                data->sens[i - 1] = W83781D_DEFAULT_BETA;
                        } else {
                                if (w83781d_read_value
-                                   (client,
+                                   (data,
                                     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
                                        data->sens[i - 1] = 1;
                                else
@@ -1525,38 +1501,46 @@ w83781d_init_client(struct i2c_client *client)
 
        if (init && type != as99127f) {
                /* Enable temp2 */
-               tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG);
+               tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
                if (tmp & 0x01) {
-                       dev_warn(&client->dev, "Enabling temp2, readings "
+                       dev_warn(dev, "Enabling temp2, readings "
                                 "might not make sense\n");
-                       w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG,
+                       w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
                                tmp & 0xfe);
                }
 
                /* Enable temp3 */
                if (type != w83783s) {
-                       tmp = w83781d_read_value(client,
+                       tmp = w83781d_read_value(data,
                                W83781D_REG_TEMP3_CONFIG);
                        if (tmp & 0x01) {
-                               dev_warn(&client->dev, "Enabling temp3, "
+                               dev_warn(dev, "Enabling temp3, "
                                         "readings might not make sense\n");
-                               w83781d_write_value(client,
+                               w83781d_write_value(data,
                                        W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
                        }
                }
        }
 
        /* Start monitoring */
-       w83781d_write_value(client, W83781D_REG_CONFIG,
-                           (w83781d_read_value(client,
+       w83781d_write_value(data, W83781D_REG_CONFIG,
+                           (w83781d_read_value(data,
                                                W83781D_REG_CONFIG) & 0xf7)
                            | 0x01);
+
+       /* A few vars need to be filled upon startup */
+       for (i = 0; i < 3; i++) {
+               data->fan_min[i] = w83781d_read_value(data,
+                                       W83781D_REG_FAN_MIN(i));
+       }
+
+       mutex_init(&data->update_lock);
 }
 
 static struct w83781d_data *w83781d_update_device(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
+       struct w83781d_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = &data->client;
        int i;
 
        mutex_lock(&data->update_lock);
@@ -1569,98 +1553,97 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                        if (data->type == w83783s && i == 1)
                                continue;       /* 783S has no in1 */
                        data->in[i] =
-                           w83781d_read_value(client, W83781D_REG_IN(i));
+                           w83781d_read_value(data, W83781D_REG_IN(i));
                        data->in_min[i] =
-                           w83781d_read_value(client, W83781D_REG_IN_MIN(i));
+                           w83781d_read_value(data, W83781D_REG_IN_MIN(i));
                        data->in_max[i] =
-                           w83781d_read_value(client, W83781D_REG_IN_MAX(i));
+                           w83781d_read_value(data, W83781D_REG_IN_MAX(i));
                        if ((data->type != w83782d)
                            && (data->type != w83627hf) && (i == 6))
                                break;
                }
-               for (i = 1; i <= 3; i++) {
-                       data->fan[i - 1] =
-                           w83781d_read_value(client, W83781D_REG_FAN(i));
-                       data->fan_min[i - 1] =
-                           w83781d_read_value(client, W83781D_REG_FAN_MIN(i));
+               for (i = 0; i < 3; i++) {
+                       data->fan[i] =
+                           w83781d_read_value(data, W83781D_REG_FAN(i));
+                       data->fan_min[i] =
+                           w83781d_read_value(data, W83781D_REG_FAN_MIN(i));
                }
                if (data->type != w83781d && data->type != as99127f) {
-                       for (i = 1; i <= 4; i++) {
-                               data->pwm[i - 1] =
-                                   w83781d_read_value(client,
-                                                      W83781D_REG_PWM(i));
-                               if ((data->type != w83782d
-                                    || i2c_is_isa_client(client))
-                                   && i == 2)
+                       for (i = 0; i < 4; i++) {
+                               data->pwm[i] =
+                                   w83781d_read_value(data,
+                                                      W83781D_REG_PWM[i]);
+                               if ((data->type != w83782d || !client->driver)
+                                   && i == 1)
                                        break;
                        }
                        /* Only PWM2 can be disabled */
-                       data->pwmenable[1] = (w83781d_read_value(client,
+                       data->pwm2_enable = (w83781d_read_value(data,
                                              W83781D_REG_PWMCLK12) & 0x08) >> 3;
                }
 
-               data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
+               data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1));
                data->temp_max =
-                   w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
+                   w83781d_read_value(data, W83781D_REG_TEMP_OVER(1));
                data->temp_max_hyst =
-                   w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
+                   w83781d_read_value(data, W83781D_REG_TEMP_HYST(1));
                data->temp_add[0] =
-                   w83781d_read_value(client, W83781D_REG_TEMP(2));
+                   w83781d_read_value(data, W83781D_REG_TEMP(2));
                data->temp_max_add[0] =
-                   w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
+                   w83781d_read_value(data, W83781D_REG_TEMP_OVER(2));
                data->temp_max_hyst_add[0] =
-                   w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
+                   w83781d_read_value(data, W83781D_REG_TEMP_HYST(2));
                if (data->type != w83783s) {
                        data->temp_add[1] =
-                           w83781d_read_value(client, W83781D_REG_TEMP(3));
+                           w83781d_read_value(data, W83781D_REG_TEMP(3));
                        data->temp_max_add[1] =
-                           w83781d_read_value(client,
+                           w83781d_read_value(data,
                                               W83781D_REG_TEMP_OVER(3));
                        data->temp_max_hyst_add[1] =
-                           w83781d_read_value(client,
+                           w83781d_read_value(data,
                                               W83781D_REG_TEMP_HYST(3));
                }
-               i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
+               i = w83781d_read_value(data, W83781D_REG_VID_FANDIV);
                data->vid = i & 0x0f;
-               data->vid |= (w83781d_read_value(client,
+               data->vid |= (w83781d_read_value(data,
                                        W83781D_REG_CHIPID) & 0x01) << 4;
                data->fan_div[0] = (i >> 4) & 0x03;
                data->fan_div[1] = (i >> 6) & 0x03;
-               data->fan_div[2] = (w83781d_read_value(client,
+               data->fan_div[2] = (w83781d_read_value(data,
                                        W83781D_REG_PIN) >> 6) & 0x03;
                if ((data->type != w83781d) && (data->type != as99127f)) {
-                       i = w83781d_read_value(client, W83781D_REG_VBAT);
+                       i = w83781d_read_value(data, W83781D_REG_VBAT);
                        data->fan_div[0] |= (i >> 3) & 0x04;
                        data->fan_div[1] |= (i >> 4) & 0x04;
                        data->fan_div[2] |= (i >> 5) & 0x04;
                }
                if ((data->type == w83782d) || (data->type == w83627hf)) {
-                       data->alarms = w83781d_read_value(client,
+                       data->alarms = w83781d_read_value(data,
                                                W83782D_REG_ALARM1)
-                                    | (w83781d_read_value(client,
+                                    | (w83781d_read_value(data,
                                                W83782D_REG_ALARM2) << 8)
-                                    | (w83781d_read_value(client,
+                                    | (w83781d_read_value(data,
                                                W83782D_REG_ALARM3) << 16);
                } else if (data->type == w83783s) {
-                       data->alarms = w83781d_read_value(client,
+                       data->alarms = w83781d_read_value(data,
                                                W83782D_REG_ALARM1)
-                                    | (w83781d_read_value(client,
+                                    | (w83781d_read_value(data,
                                                W83782D_REG_ALARM2) << 8);
                } else {
                        /* No real-time status registers, fall back to
                           interrupt status registers */
-                       data->alarms = w83781d_read_value(client,
+                       data->alarms = w83781d_read_value(data,
                                                W83781D_REG_ALARM1)
-                                    | (w83781d_read_value(client,
+                                    | (w83781d_read_value(data,
                                                W83781D_REG_ALARM2) << 8);
                }
-               i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
+               i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
                data->beep_enable = i >> 7;
                data->beep_mask = ((i & 0x7f) << 8) +
-                   w83781d_read_value(client, W83781D_REG_BEEP_INTS1);
+                   w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
                if ((data->type != w83781d) && (data->type != as99127f)) {
                        data->beep_mask |=
-                           w83781d_read_value(client,
+                           w83781d_read_value(data,
                                               W83781D_REG_BEEP_INTS3) << 16;
                }
                data->last_updated = jiffies;
@@ -1672,6 +1655,133 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
        return data;
 }
 
+/* return 1 if a supported chip is found, 0 otherwise */
+static int __init
+w83781d_isa_found(unsigned short address)
+{
+       int val, save, found = 0;
+
+       if (!request_region(address, W83781D_EXTENT, "w83781d"))
+               return 0;
+
+#define REALLY_SLOW_IO
+       /* We need the timeouts for at least some W83781D-like
+          chips. But only if we read 'undefined' registers. */
+       val = inb_p(address + 1);
+       if (inb_p(address + 2) != val
+        || inb_p(address + 3) != val
+        || inb_p(address + 7) != val) {
+               pr_debug("w83781d: Detection failed at step 1\n");
+               goto release;
+       }
+#undef REALLY_SLOW_IO
+
+       /* We should be able to change the 7 LSB of the address port. The
+          MSB (busy flag) should be clear initially, set after the write. */
+       save = inb_p(address + W83781D_ADDR_REG_OFFSET);
+       if (save & 0x80) {
+               pr_debug("w83781d: Detection failed at step 2\n");
+               goto release;
+       }
+       val = ~save & 0x7f;
+       outb_p(val, address + W83781D_ADDR_REG_OFFSET);
+       if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
+               outb_p(save, address + W83781D_ADDR_REG_OFFSET);
+               pr_debug("w83781d: Detection failed at step 3\n");
+               goto release;
+       }
+
+       /* We found a device, now see if it could be a W83781D */
+       outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
+       val = inb_p(address + W83781D_DATA_REG_OFFSET);
+       if (val & 0x80) {
+               pr_debug("w83781d: Detection failed at step 4\n");
+               goto release;
+       }
+       outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
+       save = inb_p(address + W83781D_DATA_REG_OFFSET);
+       outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET);
+       val = inb_p(address + W83781D_DATA_REG_OFFSET);
+       if ((!(save & 0x80) && (val != 0xa3))
+        || ((save & 0x80) && (val != 0x5c))) {
+               pr_debug("w83781d: Detection failed at step 5\n");
+               goto release;
+       }
+       outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
+       val = inb_p(address + W83781D_DATA_REG_OFFSET);
+       if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */
+               pr_debug("w83781d: Detection failed at step 6\n");
+               goto release;
+       }
+
+       /* The busy flag should be clear again */
+       if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
+               pr_debug("w83781d: Detection failed at step 7\n");
+               goto release;
+       }
+
+       /* Determine the chip type */
+       outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
+       save = inb_p(address + W83781D_DATA_REG_OFFSET);
+       outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET);
+       outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
+       val = inb_p(address + W83781D_DATA_REG_OFFSET);
+       if ((val & 0xfe) == 0x10        /* W83781D */
+        || val == 0x30                 /* W83782D */
+        || val == 0x21)                /* W83627HF */
+               found = 1;
+
+       if (found)
+               pr_info("w83781d: Found a %s chip at %#x\n",
+                       val == 0x21 ? "W83627HF" :
+                       val == 0x30 ? "W83782D" : "W83781D", (int)address);
+
+ release:
+       release_region(address, W83781D_EXTENT);
+       return found;
+}
+
+static int __init
+w83781d_isa_device_add(unsigned short address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + W83781D_EXTENT,
+               .name   = "w83781d",
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc("w83781d", address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR "w83781d: Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR "w83781d: Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR "w83781d: Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+ exit_device_put:
+       platform_device_put(pdev);
+ exit:
+       pdev = NULL;
+       return err;
+}
+
 static int __init
 sensors_w83781d_init(void)
 {
@@ -1679,21 +1789,36 @@ sensors_w83781d_init(void)
 
        res = i2c_add_driver(&w83781d_driver);
        if (res)
-               return res;
+               goto exit;
+
+       if (w83781d_isa_found(isa_address)) {
+               res = platform_driver_register(&w83781d_isa_driver);
+               if (res)
+                       goto exit_unreg_i2c_driver;
 
-       /* Don't exit if this one fails, we still want the I2C variants
-          to work! */
-       if (i2c_isa_add_driver(&w83781d_isa_driver))
-               isa_address = 0;
+               /* Sets global pdev as a side effect */
+               res = w83781d_isa_device_add(isa_address);
+               if (res)
+                       goto exit_unreg_isa_driver;
+       }
 
        return 0;
+
+ exit_unreg_isa_driver:
+       platform_driver_unregister(&w83781d_isa_driver);
+ exit_unreg_i2c_driver:
+       i2c_del_driver(&w83781d_driver);
+ exit:
+       return res;
 }
 
 static void __exit
 sensors_w83781d_exit(void)
 {
-       if (isa_address)
-               i2c_isa_del_driver(&w83781d_isa_driver);
+       if (pdev) {
+               platform_device_unregister(pdev);
+               platform_driver_unregister(&w83781d_isa_driver);
+       }
        i2c_del_driver(&w83781d_driver);
 }
 
index 8c953707253fad6abec1c9b9cb7020c4d9f82f61..039a07fde908f679851fb990e1e6ad04667002fd 100644 (file)
@@ -175,6 +175,7 @@ static void i2c_parport_attach (struct parport *port)
        }
        adapter->algo_data.data = port;
        adapter->adapter.algo_data = &adapter->algo_data;
+       adapter->adapter.dev.parent = port->physport->dev;
 
        if (parport_claim_or_block(adapter->pdev) < 0) {
                printk(KERN_ERR "i2c-parport: Could not claim parallel port\n");
index 0db56e7bc34e95369f18edd027e34ed487d0579e..0d6bd4f7b7fa6a782c53148f386dd623a6edc811 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
index 7ed92dc3d833304da757d7e99aed88023df232fc..3c3f2ebf3fc9786eecf042ed4aa1d1ae9a56c9c3 100644 (file)
@@ -354,7 +354,7 @@ static void tps65010_interrupt(struct tps65010 *tps)
                         * also needs to get error handling and probably
                         * an #ifdef CONFIG_SOFTWARE_SUSPEND
                         */
-                       pm_suspend(PM_SUSPEND_DISK);
+                       hibernate();
 #endif
                        poll = 1;
                }
index cb4fa9bef8cd5ef1602a3ddf9bc02d1557d5d744..e7a7097105923296482dcc37acef6a8bc53fddb9 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/i2c.h>
index 2da5cbb5356669c63b998813476cd166779c3106..2cdd629c653db9f2a61438d02b3e49d68e93ac8f 100644 (file)
@@ -395,7 +395,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
        unsigned int class_rev = 0;
        u8 conf;
 
-       if (np == NULL || !device_is_compatible(np, "kiwi-root"))
+       if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
                return;
 
        pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
index c0188de3cc66509fc07a6ba886bb3599a6533ebb..79cec50a242f6912f9c74c03b160cd859440dc41 100644 (file)
@@ -831,7 +831,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
 
        /*
         *      Now set up the hw. We have to do this ourselves as
-        *      the MMIO layout isnt the same as the the standard port
+        *      the MMIO layout isnt the same as the standard port
         *      based I/O
         */
 
index 071a030ec26edd6cfc35ffb62a7bd2efc9700cec..a49ebe44babd1d5f0d97c92b3fdd963be0fc7f70 100644 (file)
@@ -1157,32 +1157,32 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 
        pmif->cable_80 = 0;
        pmif->broken_dma = pmif->broken_dma_warn = 0;
-       if (device_is_compatible(np, "shasta-ata"))
+       if (of_device_is_compatible(np, "shasta-ata"))
                pmif->kind = controller_sh_ata6;
-       else if (device_is_compatible(np, "kauai-ata"))
+       else if (of_device_is_compatible(np, "kauai-ata"))
                pmif->kind = controller_un_ata6;
-       else if (device_is_compatible(np, "K2-UATA"))
+       else if (of_device_is_compatible(np, "K2-UATA"))
                pmif->kind = controller_k2_ata6;
-       else if (device_is_compatible(np, "keylargo-ata")) {
+       else if (of_device_is_compatible(np, "keylargo-ata")) {
                if (strcmp(np->name, "ata-4") == 0)
                        pmif->kind = controller_kl_ata4;
                else
                        pmif->kind = controller_kl_ata3;
-       } else if (device_is_compatible(np, "heathrow-ata"))
+       } else if (of_device_is_compatible(np, "heathrow-ata"))
                pmif->kind = controller_heathrow;
        else {
                pmif->kind = controller_ohare;
                pmif->broken_dma = 1;
        }
 
-       bidp = get_property(np, "AAPL,bus-id", NULL);
+       bidp = of_get_property(np, "AAPL,bus-id", NULL);
        pmif->aapl_bus_id =  bidp ? *bidp : 0;
 
        /* Get cable type from device-tree */
        if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6
            || pmif->kind == controller_k2_ata6
            || pmif->kind == controller_sh_ata6) {
-               const char* cable = get_property(np, "cable-type", NULL);
+               const char* cable = of_get_property(np, "cable-type", NULL);
                if (cable && !strncmp(cable, "80-", 3))
                        pmif->cable_80 = 1;
        }
@@ -1190,8 +1190,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
         * they have a 80 conductor cable, this seem to be always the case unless
         * the user mucked around
         */
-       if (device_is_compatible(np, "K2-UATA") ||
-           device_is_compatible(np, "shasta-ata"))
+       if (of_device_is_compatible(np, "K2-UATA") ||
+           of_device_is_compatible(np, "shasta-ata"))
                pmif->cable_80 = 1;
 
        /* On Kauai-type controllers, we make sure the FCR is correct */
index 026e38face5c7d18a13274c451b3c6638af4bd6a..20814137761220e5ebbf00dd86e2ee0e21421a3e 100644 (file)
@@ -94,7 +94,6 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/bitops.h>
 #include <asm/byteorder.h>
index 6a1a0572275e96a8a72fbc87c730c9ce200f5544..835937e385292d648ba3d2b131e906d66bbb5f09 100644 (file)
@@ -1702,7 +1702,7 @@ static int nodemgr_host_thread(void *__hi)
                        generation = get_hpsb_generation(host);
 
                        /* If we get a reset before we are done waiting, then
-                        * start the the waiting over again */
+                        * start the waiting over again */
                        if (generation != g)
                                g = generation, i = 0;
                }
index c6aefd9ad0e836fff8ca4aab262e98347d7d91fd..d382500f4210b89896a4d47607cc7d7c7fc8feac 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
 #include <linux/cdev.h>
index 95ca26d7527297354021b2b18b2e89637c53dc7b..87ebd0846c3410d56afbc520180046322bc44cdc 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
index f284be1c916645067aa3b6659925e81040c55fe4..82dda2faf4d0b6b271193b92ec421f60151801b3 100644 (file)
@@ -745,6 +745,7 @@ static int comp_pool_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu);
                if(!create_comp_task(pool, cpu)) {
                        ehca_gen_err("Can't create comp_task for cpu: %x", cpu);
@@ -752,24 +753,29 @@ static int comp_pool_callback(struct notifier_block *nfb,
                }
                break;
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu);
                cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
                kthread_bind(cct->task, any_online_cpu(cpu_online_map));
                destroy_comp_task(pool, cpu);
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu);
                cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
                kthread_bind(cct->task, cpu);
                wake_up_process(cct->task);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu);
                break;
        case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu);
                destroy_comp_task(pool, cpu);
                take_over_work(pool, cpu);
index 2d370543e96d1e1e5a1ba7840b8598efc747df97..fe90e7454560c98884f91e184dcd0e5284db127e 100644 (file)
@@ -570,7 +570,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
        struct ib_pd *ibpd;
        int ret;
 
-       handle = get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
+       handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
        if (!handle) {
                ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
                             dev->ofdev.node->full_name);
index 036ed1ef17960a5f2e9f5078b4752d91b9fc57a0..ebd5c7bd2cdbec4680163237360ee88b12822b67 100644 (file)
@@ -523,7 +523,7 @@ static int ipathfs_fill_super(struct super_block *sb, void *data,
        int ret;
 
        static struct tree_descr files[] = {
-               [1] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
+               [2] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
                {""},
        };
 
index 89d6008bb673aa385c56811f785d6f896abdb0fa..3702e2375553eff0517a5ef58418cfa050496bd7 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/version.h>
 
index 96232313b1b97fc277aeb4c67ebff59d205eb6aa..0e9b69535ad6990a0766b346412b352562860375 100644 (file)
@@ -153,6 +153,8 @@ source "drivers/input/mouse/Kconfig"
 
 source "drivers/input/joystick/Kconfig"
 
+source "drivers/input/tablet/Kconfig"
+
 source "drivers/input/touchscreen/Kconfig"
 
 source "drivers/input/misc/Kconfig"
index b4cd10653c4f4996e7dde138db36f1171070d504..8a2dd987546c3c86a4587d9e6de9cb6862a7e3d4 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_INPUT_EVBUG)     += evbug.o
 obj-$(CONFIG_INPUT_KEYBOARD)   += keyboard/
 obj-$(CONFIG_INPUT_MOUSE)      += mouse/
 obj-$(CONFIG_INPUT_JOYSTICK)   += joystick/
+obj-$(CONFIG_INPUT_TABLET)     += tablet/
 obj-$(CONFIG_INPUT_TOUCHSCREEN)        += touchscreen/
 obj-$(CONFIG_INPUT_MISC)       += misc/
 
index 1f6fcec0c6fc31491e60f543c18d5f2899d8d4a5..55a72592704cf5e1a497ae2805f6ff3c3f802c85 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/major.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/compat.h>
 
@@ -512,7 +511,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
 
-                                       long *bits;
+                                       unsigned long *bits;
                                        int len;
 
                                        switch (_IOC_NR(cmd) & EV_MAX) {
@@ -557,7 +556,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
-                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       t = _IOC_NR(cmd) & ABS_MAX;
 
                                        abs.value = dev->abs[t];
                                        abs.minimum = dev->absmin[t];
@@ -577,7 +576,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
-                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       t = _IOC_NR(cmd) & ABS_MAX;
 
                                        if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
                                                return -EFAULT;
index 783b3412ceadad32b77430c483ce3375faafc481..eebc72465fc9beb44d2ecfa77a78d24cbd31f891 100644 (file)
@@ -281,7 +281,8 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
                break;
 
        default:
-               ff->playback(dev, code, value);
+               if (check_effect_access(ff, code, NULL) == 0)
+                       ff->playback(dev, code, value);
                break;
        }
 
index 915e9ab7cab0faad95ad5391b9493eb946bb1d7f..ccd8abafcb708c2f4aedf962c5f27f4dbe9ca0dc 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
index 9bcc5425049be22160039e6f6ad6073d126ff4d8..06f0541b24daaaed730d448d7f5f68bfa2b05c40 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
index 271263443c37c1405cf014fd43ba607cf70cbff5..82f563e24fdbc39e0e0945ff16f8fca980da05a8 100644 (file)
@@ -2,7 +2,7 @@
 # Joystick driver configuration
 #
 menuconfig INPUT_JOYSTICK
-       bool "Joysticks"
+       bool "Joysticks/Gamepads"
        help
          If you have a joystick, 6dof controller, gamepad, steering wheel,
          weapon control system or something like that you can say Y here
@@ -196,7 +196,7 @@ config JOYSTICK_TWIDJOY
 config JOYSTICK_DB9
        tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
        depends on PARPORT
-       ---help---
+       help
          Say Y here if you have a Sega Master System gamepad, Sega Genesis
          gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
          Commodore, Amstrad CPC joystick connected to your parallel port.
@@ -253,4 +253,18 @@ config JOYSTICK_JOYDUMP
          To compile this driver as a module, choose M here: the
          module will be called joydump.
 
+config JOYSTICK_XPAD
+       tristate "X-Box gamepad support"
+       select USB
+       help
+         Say Y here if you want to use the X-Box pad with your computer.
+         Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV)
+         and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well.
+
+         For information about how to connect the X-Box pad to USB, see
+         <file:Documentation/input/xpad.txt>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called xpad.
+
 endif
index 5231f6ff75b8a9dc281691ba70ddc67e0bb1f5df..e855abb0cc5175e0ffc9692e9e3f5b20efb937ef 100644 (file)
@@ -26,5 +26,6 @@ obj-$(CONFIG_JOYSTICK_TMDC)           += tmdc.o
 obj-$(CONFIG_JOYSTICK_TURBOGRAFX)      += turbografx.o
 obj-$(CONFIG_JOYSTICK_TWIDJOY)         += twidjoy.o
 obj-$(CONFIG_JOYSTICK_WARRIOR)         += warrior.o
+obj-$(CONFIG_JOYSTICK_XPAD)            += xpad.o
 
 obj-$(CONFIG_JOYSTICK_IFORCE)          += iforce/
index 1c1afb5d46842c5c3954275ca0cffcbb9e1a32de..bdd157c1ebf8929b763a9d56815ce209c5d906f2 100644 (file)
@@ -53,7 +53,7 @@ MODULE_LICENSE("GPL");
 #define ANALOG_PORTS           16
 
 static char *js[ANALOG_PORTS];
-static int js_nargs;
+static unsigned int js_nargs;
 static int analog_options[ANALOG_PORTS];
 module_param_array_named(map, js, charp, &js_nargs, 0);
 MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
index c27593bf99789fe148a907a29cf7befecf0cb7c5..86ad1027e12a1ceabeedc5df8911fdfd30fdbc12 100644 (file)
@@ -46,17 +46,17 @@ MODULE_LICENSE("GPL");
 
 struct db9_config {
        int args[2];
-       int nargs;
+       unsigned int nargs;
 };
 
 #define DB9_MAX_PORTS          3
-static struct db9_config db9[DB9_MAX_PORTS] __initdata;
+static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata;
 
-module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
+module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
 MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
-module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
+module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[0].nargs, 0);
 MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
-module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
+module_param_array_named(dev3, db9_cfg[2].args, int, &db9_cfg[2].nargs, 0);
 MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
 
 #define DB9_ARG_PARPORT                0
@@ -680,17 +680,17 @@ static int __init db9_init(void)
        int err = 0;
 
        for (i = 0; i < DB9_MAX_PORTS; i++) {
-               if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
+               if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0)
                        continue;
 
-               if (db9[i].nargs < 2) {
+               if (db9_cfg[i].nargs < 2) {
                        printk(KERN_ERR "db9.c: Device type must be specified.\n");
                        err = -EINVAL;
                        break;
                }
 
-               db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
-                                       db9[i].args[DB9_ARG_MODE]);
+               db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT],
+                                       db9_cfg[i].args[DB9_ARG_MODE]);
                if (IS_ERR(db9_base[i])) {
                        err = PTR_ERR(db9_base[i]);
                        break;
index c71b58fe225db3a05ded9186b82ee600db734534..1a452e0e5f25788e37c972998912245747ec1657 100644 (file)
@@ -48,16 +48,16 @@ MODULE_LICENSE("GPL");
 
 struct gc_config {
        int args[GC_MAX_DEVICES + 1];
-       int nargs;
+       unsigned int nargs;
 };
 
-static struct gc_config gc[GC_MAX_PORTS] __initdata;
+static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata;
 
-module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
+module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0);
 MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
-module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
+module_param_array_named(map2, gc_cfg[1].args, int, &gc_cfg[1].nargs, 0);
 MODULE_PARM_DESC(map2, "Describes second set of devices");
-module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
+module_param_array_named(map3, gc_cfg[2].args, int, &gc_cfg[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
 /* see also gs_psx_delay parameter in PSX support section */
@@ -810,16 +810,17 @@ static int __init gc_init(void)
        int err = 0;
 
        for (i = 0; i < GC_MAX_PORTS; i++) {
-               if (gc[i].nargs == 0 || gc[i].args[0] < 0)
+               if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
                        continue;
 
-               if (gc[i].nargs < 2) {
+               if (gc_cfg[i].nargs < 2) {
                        printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
                        err = -EINVAL;
                        break;
                }
 
-               gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
+               gc_base[i] = gc_probe(gc_cfg[i].args[0],
+                                     gc_cfg[i].args + 1, gc_cfg[i].nargs - 1);
                if (IS_ERR(gc_base[i])) {
                        err = PTR_ERR(gc_base[i]);
                        break;
index dadcf4fb92aefd9d5ab1357328937ced02e825cb..40a853ac21c795c2e3db467be967f203a91f1d0b 100644 (file)
@@ -124,7 +124,7 @@ struct iforce {
        /* Buffer used for asynchronous sending of bytes to the device */
        struct circ_buf xmit;
        unsigned char xmit_data[XMIT_SIZE];
-       long xmit_flags[1];
+       unsigned long xmit_flags[1];
 
                                        /* Force Feedback */
        wait_queue_head_t wait;
index 0f2c60823b0b81890c163d8a0f6998908819a1bf..8381c6f143735f69af27b714cfcd7d79d2a37ed7 100644 (file)
@@ -48,16 +48,16 @@ MODULE_LICENSE("GPL");
 
 struct tgfx_config {
        int args[TGFX_MAX_DEVICES + 1];
-       int nargs;
+       unsigned int nargs;
 };
 
-static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
+static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata;
 
-module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
+module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0);
 MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
-module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
+module_param_array_named(map2, tgfx_cfg[1].args, int, &tgfx_cfg[1].nargs, 0);
 MODULE_PARM_DESC(map2, "Describes second set of devices");
-module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
+module_param_array_named(map3, tgfx_cfg[2].args, int, &tgfx_cfg[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
 #define TGFX_REFRESH_TIME      HZ/100  /* 10 ms */
@@ -283,16 +283,18 @@ static int __init tgfx_init(void)
        int err = 0;
 
        for (i = 0; i < TGFX_MAX_PORTS; i++) {
-               if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
+               if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0)
                        continue;
 
-               if (tgfx[i].nargs < 2) {
+               if (tgfx_cfg[i].nargs < 2) {
                        printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
                        err = -EINVAL;
                        break;
                }
 
-               tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1);
+               tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0],
+                                         tgfx_cfg[i].args + 1,
+                                         tgfx_cfg[i].nargs - 1);
                if (IS_ERR(tgfx_base[i])) {
                        err = PTR_ERR(tgfx_base[i]);
                        break;
similarity index 99%
rename from drivers/usb/input/xpad.c
rename to drivers/input/joystick/xpad.c
index 73572391295082f8747d2546fd7109799b882c73..8c8cd95a6989dbf8ffd5c2105b08c0837867dc9e 100644 (file)
@@ -74,7 +74,6 @@
 #include <linux/stat.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/smp_lock.h>
 #include <linux/usb/input.h>
 
 #define DRIVER_VERSION "v0.0.6"
index 9f42e4d3649efe83178e2e89a2b9fd6c9debef72..bd707b86c114a9b7fa323a46b51ccb15fd410b9f 100644 (file)
@@ -226,6 +226,7 @@ config KEYBOARD_PXA27x
 config KEYBOARD_AAED2000
        tristate "AAED-2000 keyboard"
        depends on MACH_AAED2000
+       select INPUT_POLLDEV
        default y
        help
          Say Y here to enable the keyboard on the Agilent AAED-2000
index 3a37505f067cc8cae3f551b1b26f0d7752133860..63d6ead6b877051baf18392140cd9e23a2df9f68 100644 (file)
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/workqueue.h>
 
 #include <asm/arch/hardware.h>
 #include <asm/arch/aaed2000.h>
@@ -46,8 +45,7 @@ static unsigned char aaedkbd_keycode[NR_SCANCODES] = {
 
 struct aaedkbd {
        unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)];
-       struct input_dev *input;
-       struct work_struct workq;
+       struct input_polled_dev *poll_dev;
        int kbdscan_state[KB_COLS];
        int kbdscan_count[KB_COLS];
 };
@@ -64,14 +62,15 @@ static void aaedkbd_report_col(struct aaedkbd *aaedkbd,
                scancode = SCANCODE(row, col);
                pressed = rowd & KB_ROWMASK(row);
 
-               input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed);
+               input_report_key(aaedkbd->poll_dev->input,
+                                aaedkbd->keycode[scancode], pressed);
        }
 }
 
 /* Scan the hardware keyboard and push any changes up through the input layer */
-static void aaedkbd_work(void *data)
+static void aaedkbd_poll(struct input_polled_dev *dev)
 {
-       struct aaedkbd *aaedkbd = data;
+       struct aaedkbd *aaedkbd = dev->private;
        unsigned int col, rowd;
 
        col = 0;
@@ -90,51 +89,34 @@ static void aaedkbd_work(void *data)
        } while (col < KB_COLS);
 
        AAEC_GPIO_KSCAN = 0x07;
-       input_sync(aaedkbd->input);
-
-       schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
-}
-
-static int aaedkbd_open(struct input_dev *indev)
-{
-       struct aaedkbd *aaedkbd = input_get_drvdata(indev);
-
-       schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
-
-       return 0;
-}
-
-static void aaedkbd_close(struct input_dev *indev)
-{
-       struct aaedkbd *aaedkbd = input_get_drvdata(indev);
-
-       cancel_delayed_work(&aaedkbd->workq);
-       flush_scheduled_work();
+       input_sync(dev->input);
 }
 
 static int __devinit aaedkbd_probe(struct platform_device *pdev)
 {
        struct aaedkbd *aaedkbd;
+       struct input_polled_dev *poll_dev;
        struct input_dev *input_dev;
        int i;
        int error;
 
        aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!aaedkbd || !input_dev) {
+       poll_dev = input_allocate_polled_device();
+       if (!aaedkbd || !poll_dev) {
                error = -ENOMEM;
                goto fail;
        }
 
        platform_set_drvdata(pdev, aaedkbd);
 
-       aaedkbd->input = input_dev;
-
-       /* Init keyboard rescan workqueue */
-       INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd);
-
+       aaedkbd->poll_dev = poll_dev;
        memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode));
 
+       poll_dev->private = aaedkbd;
+       poll_dev->poll = aaedkbd_poll;
+       poll_dev->poll_interval = SCAN_INTERVAL;
+
+       input_dev = poll_dev->input;
        input_dev->name = "AAED-2000 Keyboard";
        input_dev->phys = "aaedkbd/input0";
        input_dev->id.bustype = BUS_HOST;
@@ -143,8 +125,6 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev)
        input_dev->id.version = 0x0100;
        input_dev->dev.parent = &pdev->dev;
 
-       input_set_drvdata(input_dev, aaedkbd);
-
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = aaedkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
@@ -154,17 +134,14 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev)
                set_bit(aaedkbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
 
-       input_dev->open = aaedkbd_open;
-       input_dev->close = aaedkbd_close;
-
-       error = input_register_device(aaedkbd->input);
+       error = input_register_polled_device(aaedkbd->poll_dev);
        if (error)
                goto fail;
 
        return 0;
 
  fail: kfree(aaedkbd);
-       input_free_device(input_dev);
+       input_free_polled_device(poll_dev);
        return error;
 }
 
@@ -172,7 +149,8 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
 {
        struct aaedkbd *aaedkbd = platform_get_drvdata(pdev);
 
-       input_unregister_device(aaedkbd->input);
+       input_unregister_polled_device(aaedkbd->poll_dev);
+       input_free_polled_device(aaedkbd->poll_dev);
        kfree(aaedkbd);
 
        return 0;
index 1d0d3e765db67a1ee0919dcbf2202b88c505a3db..6013ace94d98675a1ba1b47781d9470db82ca161 100644 (file)
@@ -40,6 +40,18 @@ config INPUT_M68K_BEEP
        tristate "M68k Beeper support"
        depends on M68K
 
+config INPUT_IXP4XX_BEEPER
+       tristate "IXP4XX Beeper support"
+       depends on ARCH_IXP4XX
+       help
+         If you say yes here, you can connect a beeper to the
+         ixp4xx gpio pins. This is used by the LinkSys NSLU2.
+
+         If unsure, say Y.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ixp4xx-beeper.
+
 config INPUT_COBALT_BTNS
        tristate "Cobalt button interface"
        depends on MIPS_COBALT
@@ -70,17 +82,79 @@ config INPUT_ATLAS_BTNS
          To compile this driver as a module, choose M here: the module will
          be called atlas_btns.
 
-config INPUT_IXP4XX_BEEPER
-       tristate "IXP4XX Beeper support"
-       depends on ARCH_IXP4XX
+config INPUT_ATI_REMOTE
+       tristate "ATI / X10 USB RF remote control"
+       select USB
        help
-         If you say yes here, you can connect a beeper to the
-         ixp4xx gpio pins. This is used by the LinkSys NSLU2.
+         Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
+         These are RF remotes with USB receivers.
+         The ATI remote comes with many of ATI's All-In-Wonder video cards.
+         The X10 "Lola" remote is available at:
+            <http://www.x10.com/products/lola_sg1.htm>
+         This driver provides mouse pointer, left and right mouse buttons,
+         and maps all the other remote buttons to keypress events.
+
+         To compile this driver as a module, choose M here: the module will be
+         called ati_remote.
+
+config INPUT_ATI_REMOTE2
+       tristate "ATI / Philips USB RF remote control"
+       select USB
+       help
+         Say Y here if you want to use an ATI or Philips USB RF remote control.
+         These are RF remotes with USB receivers.
+         ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
+         and is also available as a separate product.
+         This driver provides mouse pointer, left and right mouse buttons,
+         and maps all the other remote buttons to keypress events.
+
+         To compile this driver as a module, choose M here: the module will be
+         called ati_remote2.
+
+config INPUT_KEYSPAN_REMOTE
+       tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       select USB
+       help
+         Say Y here if you want to use a Keyspan DMR USB remote control.
+         Currently only the UIA-11 type of receiver has been tested.  The tag
+         on the receiver that connects to the USB port should have a P/N that
+         will tell you what type of DMR you have.  The UIA-10 type is not
+         supported at this time.  This driver maps all buttons to keypress
+         events.
 
-         If unsure, say Y.
+         To compile this driver as a module, choose M here: the module will
+         be called keyspan_remote.
+
+config INPUT_POWERMATE
+       tristate "Griffin PowerMate and Contour Jog support"
+       select USB
+       help
+         Say Y here if you want to use Griffin PowerMate or Contour Jog devices.
+         These are aluminum dials which can measure clockwise and anticlockwise
+         rotation.  The dial also acts as a pushbutton.  The base contains an LED
+         which can be instructed to pulse or to switch to a particular intensity.
+
+         You can download userspace tools from
+         <http://sowerbutts.com/powermate/>.
 
          To compile this driver as a module, choose M here: the
-         module will be called ixp4xx-beeper.
+         module will be called powermate.
+
+config INPUT_YEALINK
+       tristate "Yealink usb-p1k voip phone"
+       depends EXPERIMENTAL
+       select USB
+       help
+         Say Y here if you want to enable keyboard and LCD functions of the
+         Yealink usb-p1k usb phones. The audio part is enabled by the generic
+         usb sound driver, so you might want to enable that as well.
+
+         For information about how to use these additional functions, see
+         <file:Documentation/input/yealink.txt>.
+
+         To compile this driver as a module, choose M here: the module will be
+         called yealink.
 
 config INPUT_UINPUT
        tristate "User level driver support"
index 21e3cca0d33e13667c0cb90661d1d82a1b04b893..8b2f7799e25c98e2e33668b6cdfb6d0299c796ce 100644 (file)
@@ -8,9 +8,14 @@ obj-$(CONFIG_INPUT_POLLDEV)            += input-polldev.o
 obj-$(CONFIG_INPUT_SPARCSPKR)          += sparcspkr.o
 obj-$(CONFIG_INPUT_PCSPKR)             += pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
-obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
+obj-$(CONFIG_INPUT_IXP4XX_BEEPER)      += ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)                += cobalt_btns.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)       += wistron_btns.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)         += atlas_btns.o
+obj-$(CONFIG_INPUT_ATI_REMOTE)         += ati_remote.o
+obj-$(CONFIG_INPUT_ATI_REMOTE2)                += ati_remote2.o
+obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
+obj-$(CONFIG_INPUT_POWERMATE)          += powermate.o
+obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
-obj-$(CONFIG_INPUT_IXP4XX_BEEPER)      += ixp4xx-beeper.o
+obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
similarity index 99%
rename from drivers/usb/input/ati_remote2.c
rename to drivers/input/misc/ati_remote2.c
index a9032aa3465f7bb5d70806af6bb4d55b0cee041a..1031543e5c3f3e1f71e4e15bcae5ae600aa0f087 100644 (file)
@@ -405,9 +405,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
 
        for (i = 0; i < 2; i++) {
                usb_free_urb(ar2->urb[i]);
-
-               if (ar2->buf[i])
-                       usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
+               usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
        }
 }
 
similarity index 98%
rename from drivers/usb/input/powermate.c
rename to drivers/input/misc/powermate.c
index 4f93a760faeed74c699c23704178341359d2cdad..448a470d28f264d4ee6f666438d162a17225f694 100644 (file)
@@ -291,12 +291,10 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
 
 static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm)
 {
-       if (pm->data)
-               usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX,
-                               pm->data, pm->data_dma);
-       if (pm->configcr)
-               usb_buffer_free(udev, sizeof(*(pm->configcr)),
-                               pm->configcr, pm->configcr_dma);
+       usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX,
+                       pm->data, pm->data_dma);
+       usb_buffer_free(udev, sizeof(*(pm->configcr)),
+                       pm->configcr, pm->configcr_dma);
 }
 
 /* Called whenever a USB device matching one in our supported devices table is connected */
index 031467eadd31c28a4e0a614588681c3cb7307990..a56ad4ba8fe2eb482ee4a26f1f36baa56753e1c5 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/input.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
similarity index 98%
rename from drivers/usb/input/yealink.c
rename to drivers/input/misc/yealink.c
index c54f1a5dcb4a480ba19fe04d907fa0a9184f4503..ab15880fd5663ab63cd0bbbc085dbea617eb7410 100644 (file)
@@ -29,7 +29,7 @@
  * This driver is based on:
  *   - the usbb2k-api  http://savannah.nongnu.org/projects/usbb2k-api/
  *   - information from        http://memeteau.free.fr/usbb2k
- *   - the xpad-driver drivers/usb/input/xpad.c
+ *   - the xpad-driver drivers/input/joystick/xpad.c
  *
  * Thanks to:
  *   - Olivier Vandorpe, for providing the usbb2k-api.
@@ -818,18 +818,17 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
                else
                        input_unregister_device(yld->idev);
        }
-       if (yld->ctl_req)
-               usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
-                               yld->ctl_req, yld->ctl_req_dma);
-       if (yld->ctl_data)
-               usb_buffer_free(yld->udev, USB_PKT_LEN,
-                               yld->ctl_data, yld->ctl_dma);
-       if (yld->irq_data)
-               usb_buffer_free(yld->udev, USB_PKT_LEN,
-                               yld->irq_data, yld->irq_dma);
-
-       usb_free_urb(yld->urb_irq);     /* parameter validation in core/urb */
-       usb_free_urb(yld->urb_ctl);     /* parameter validation in core/urb */
+
+       usb_free_urb(yld->urb_irq);
+       usb_free_urb(yld->urb_ctl);
+
+       usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
+                       yld->ctl_req, yld->ctl_req_dma);
+       usb_buffer_free(yld->udev, USB_PKT_LEN,
+                       yld->ctl_data, yld->ctl_dma);
+       usb_buffer_free(yld->udev, USB_PKT_LEN,
+                       yld->irq_data, yld->irq_dma);
+
        kfree(yld);
        return err;
 }
index 81dd8c7211a74f66feccb86342bd9f9ad1ec2c8b..2ccc114b3ff6b612e94d2ce6ac92c70126c3cdda 100644 (file)
@@ -2,7 +2,7 @@
 # Mouse driver configuration
 #
 menuconfig INPUT_MOUSE
-       bool "Mouse"
+       bool "Mice"
        default y
        help
          Say Y here, and a list of supported mice will be displayed.
@@ -19,7 +19,7 @@ config MOUSE_PS2
        select SERIO_LIBPS2
        select SERIO_I8042 if X86_PC
        select SERIO_GSCPS2 if GSC
-       ---help---
+       help
          Say Y here if you have a PS/2 mouse connected to your system. This
          includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
          mice with wheels and extra buttons, Microsoft, Logitech or Genius
@@ -41,7 +41,7 @@ config MOUSE_PS2_ALPS
        bool "ALPS PS/2 mouse protocol extension" if EMBEDDED
        default y
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have an ALPS PS/2 touchpad connected to
          your system.
 
@@ -51,7 +51,7 @@ config MOUSE_PS2_LOGIPS2PP
        bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
        default y
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have a Logictech PS/2++ mouse connected to
          your system.
 
@@ -61,7 +61,7 @@ config MOUSE_PS2_SYNAPTICS
        bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED
        default y
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have a Synaptics PS/2 TouchPad connected to
          your system.
 
@@ -71,7 +71,7 @@ config MOUSE_PS2_LIFEBOOK
        bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
        default y
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have a Fujitsu B-series Lifebook PS/2
          TouchScreen connected to your system.
 
@@ -81,7 +81,7 @@ config MOUSE_PS2_TRACKPOINT
        bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED
        default y
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have an IBM Trackpoint PS/2 mouse connected
          to your system.
 
@@ -90,7 +90,7 @@ config MOUSE_PS2_TRACKPOINT
 config MOUSE_PS2_TOUCHKIT
        bool "eGalax TouchKit PS/2 protocol extension"
        depends on MOUSE_PS2
-       ---help---
+       help
          Say Y here if you have an eGalax TouchKit PS/2 touchscreen
          connected to your system.
 
@@ -99,7 +99,7 @@ config MOUSE_PS2_TOUCHKIT
 config MOUSE_SERIAL
        tristate "Serial mouse"
        select SERIO
-       ---help---
+       help
          Say Y here if you have a serial (RS-232, COM port) mouse connected
          to your system. This includes Sun, MouseSystems, Microsoft,
          Logitech and all other compatible serial mice.
@@ -109,6 +109,26 @@ config MOUSE_SERIAL
          To compile this driver as a module, choose M here: the
          module will be called sermouse.
 
+config MOUSE_APPLETOUCH
+       tristate "Apple USB Touchpad support"
+       select USB
+       help
+         Say Y here if you want to use an Apple USB Touchpad.
+
+         These are the touchpads that can be found on post-February 2005
+         Apple Powerbooks (prior models have a Synaptics touchpad connected
+         to the ADB bus).
+
+         This driver provides a basic mouse driver but can be interfaced
+         with the synaptics X11 driver to provide acceleration and
+         scrolling in X11.
+
+         For further information, see
+         <file:Documentation/input/appletouch.txt>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called appletouch.
+
 config MOUSE_INPORT
        tristate "InPort/MS/ATIXL busmouse"
        depends on ISA
index 6a8f622927f25710250f16a1c733ef8092096a2a..aa4ba878533f13956b7afe867639fc43714fc894 100644 (file)
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_MOUSE_AMIGA)      += amimouse.o
+obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
 obj-$(CONFIG_MOUSE_ATARI)      += atarimouse.o
 obj-$(CONFIG_MOUSE_RISCPC)     += rpcmouse.o
 obj-$(CONFIG_MOUSE_INPORT)     += inport.o
index c77788bf932dfc586506c6784a8643eb78ffc86c..666ad3a53fdbfe74b9d978cd5cbdd22763075c78 100644 (file)
@@ -185,7 +185,7 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
        int retries = 0;
 
        while ((retries++ < 3) && psmouse_reset(psmouse))
-               printk(KERN_ERR "synaptics reset failed\n");
+               /* empty */;
 
        if (synaptics_identify(psmouse))
                return -1;
index 7678e987655022d7e9ab32d9e2db96ce6e16c081..8675f95093935069718d6fe8cf49d8c80ac1fbd9 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/input.h>
-#include <linux/smp_lock.h>
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/device.h>
index 7c17377a65b96b99cb342158ad449d60c7f8619d..3888dc307e0ce09d47aebc89eeb983df02be5f40 100644 (file)
@@ -526,6 +526,33 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/*
+ * i8042_toggle_aux - enables or disables AUX port on i8042 via command and
+ * verifies success by readinng CTR. Used when testing for presence of AUX
+ * port.
+ */
+static int __devinit i8042_toggle_aux(int on)
+{
+       unsigned char param;
+       int i;
+
+       if (i8042_command(&param,
+                       on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE))
+               return -1;
+
+       /* some chips need some time to set the I8042_CTR_AUXDIS bit */
+       for (i = 0; i < 100; i++) {
+               udelay(50);
+
+               if (i8042_command(&param, I8042_CMD_CTL_RCTR))
+                       return -1;
+
+               if (!(param & I8042_CTR_AUXDIS) == on)
+                       return 0;
+       }
+
+       return -1;
+}
 
 /*
  * i8042_check_aux() applies as much paranoia as it can at detecting
@@ -580,16 +607,12 @@ static int __devinit i8042_check_aux(void)
  * Bit assignment test - filters out PS/2 i8042's in AT mode
  */
 
-       if (i8042_command(&param, I8042_CMD_AUX_DISABLE))
-               return -1;
-       if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) {
+       if (i8042_toggle_aux(0)) {
                printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n");
                printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n");
        }
 
-       if (i8042_command(&param, I8042_CMD_AUX_ENABLE))
-               return -1;
-       if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS))
+       if (i8042_toggle_aux(1))
                return -1;
 
 /*
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
new file mode 100644 (file)
index 0000000..12dfb0e
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Tablet driver configuration
+#
+menuconfig INPUT_TABLET
+       bool "Tablets"
+       help
+         Say Y here, and a list of supported tablets will be displayed.
+         This option doesn't affect the kernel.
+
+         If unsure, say Y.
+
+if INPUT_TABLET
+
+config TABLET_USB_ACECAD
+       tristate "Acecad Flair tablet support (USB)"
+       select USB
+       help
+         Say Y here if you want to use the USB version of the Acecad Flair
+         tablet.  Make sure to say Y to "Mouse support"
+         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+         (CONFIG_INPUT_EVDEV) as well.
+
+         To compile this driver as a module, choose M here: the
+         module will be called acecad.
+
+config TABLET_USB_AIPTEK
+       tristate "Aiptek 6000U/8000U tablet support (USB)"
+       select USB
+       help
+         Say Y here if you want to use the USB version of the Aiptek 6000U
+         or Aiptek 8000U tablet.  Make sure to say Y to "Mouse support"
+         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+         (CONFIG_INPUT_EVDEV) as well.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aiptek.
+
+config TABLET_USB_GTCO
+        tristate "GTCO CalComp/InterWrite USB Support"
+        depends on USB && INPUT
+        help
+          Say Y here if you want to use the USB version of the GTCO
+          CalComp/InterWrite Tablet.  Make sure to say Y to "Mouse support"
+          (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+          (CONFIG_INPUT_EVDEV) as well.
+
+          To compile this driver as a module, choose M here: the
+          module will be called gtco.
+
+config TABLET_USB_KBTAB
+       tristate "KB Gear JamStudio tablet support (USB)"
+       select USB
+       help
+         Say Y here if you want to use the USB version of the KB Gear
+         JamStudio tablet.  Make sure to say Y to "Mouse support"
+         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+         (CONFIG_INPUT_EVDEV) as well.
+
+         To compile this driver as a module, choose M here: the
+         module will be called kbtab.
+
+config TABLET_USB_WACOM
+       tristate "Wacom Intuos/Graphire tablet support (USB)"
+       select USB
+       help
+         Say Y here if you want to use the USB version of the Wacom Intuos
+         or Graphire tablet.  Make sure to say Y to "Mouse support"
+         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+         (CONFIG_INPUT_EVDEV) as well.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wacom.
+
+endif
diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile
new file mode 100644 (file)
index 0000000..ce8b9a9
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the tablet drivers
+#
+
+# Multipart objects.
+wacom-objs     := wacom_wac.o wacom_sys.o
+
+obj-$(CONFIG_TABLET_USB_ACECAD)        += acecad.o
+obj-$(CONFIG_TABLET_USB_AIPTEK)        += aiptek.o
+obj-$(CONFIG_TABLET_USB_GTCO)  += gtco.o
+obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
+obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o
similarity index 99%
rename from drivers/usb/input/acecad.c
rename to drivers/input/tablet/acecad.c
index be8e9243c06203579e81b2e5a2ccff27c7a8fe8b..dd2310458c46a87aafaf0d2873a54f535dde0781 100644 (file)
@@ -54,7 +54,7 @@ struct usb_acecad {
        struct input_dev *input;
        struct urb *irq;
 
-       signed char *data;
+       unsigned char *data;
        dma_addr_t data_dma;
 };
 
similarity index 99%
rename from drivers/usb/input/kbtab.c
rename to drivers/input/tablet/kbtab.c
index c4781b9d1297c025778f2cc5324816ffb2b62b6d..91e6d00d4a43ffdc4a8a26e21ea1ca9bd6e9df90 100644 (file)
@@ -29,7 +29,7 @@ module_param(kb_pressure_click, int, 0);
 MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
 
 struct kbtab {
-       signed char *data;
+       unsigned char *data;
        dma_addr_t data_dma;
        struct input_dev *dev;
        struct usb_device *usbdev;
similarity index 99%
rename from drivers/usb/input/wacom.h
rename to drivers/input/tablet/wacom.h
index d85abfc5ab58be24059330f91e1fcc1c96a0740a..ef01a807ec0f9b6e0cd95eaafacc5030e0f2a308 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/usb/input/wacom.h
+ * drivers/input/tablet/wacom.h
  *
  *  USB Wacom Graphire and Wacom Intuos tablet support
  *
similarity index 99%
rename from drivers/usb/input/wacom_sys.c
rename to drivers/input/tablet/wacom_sys.c
index 1fe48208c2f4cd6d5aa875a31f1e907fd2607d10..83bddef6606770a536048c6a9250dbd084627c88 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/usb/input/wacom_sys.c
+ * drivers/input/tablet/wacom_sys.c
  *
  *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
  */
similarity index 99%
rename from drivers/usb/input/wacom_wac.c
rename to drivers/input/tablet/wacom_wac.c
index 4f3e9bc7177d236e9c1575111c0f9b4162d1c359..7661f03a2db2ab3cbb51e6d40e28db54db9ac32b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/usb/input/wacom_wac.c
+ * drivers/input/tablet/wacom_wac.c
  *
  *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
  *
similarity index 93%
rename from drivers/usb/input/wacom_wac.h
rename to drivers/input/tablet/wacom_wac.h
index a23022287248e12805f1250de2f0a41c3a079ae8..a5e12e8756de046e9bcf62ddeaaba165183246ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/usb/input/wacom_wac.h
+ * drivers/input/tablet/wacom_wac.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
@@ -39,7 +39,7 @@ struct wacom_features {
 };
 
 struct wacom_wac {
-       signed char *data;
+       unsigned char *data;
         int tool[2];
         int id[2];
         __u32 serial[2];
index 971618059a6f6a25648cf3f031548f1d5bc4a20d..5e640aeb03cdfa0ac1eb781c6232c6b3b117ff0c 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Mouse driver configuration
+# Touchscreen driver configuration
 #
 menuconfig INPUT_TOUCHSCREEN
        bool "Touchscreens"
@@ -44,9 +44,9 @@ config TOUCHSCREEN_BITSY
 config TOUCHSCREEN_CORGI
        tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
        depends on PXA_SHARPSL
-       default y       
+       default y
        help
-         Say Y here to enable the driver for the touchscreen on the 
+         Say Y here to enable the driver for the touchscreen on the
          Sharp SL-C7xx and SL-Cxx00 series of PDAs.
 
          If unsure, say N.
@@ -164,4 +164,58 @@ config TOUCHSCREEN_UCB1400
          To compile this driver as a module, choose M here: the
          module will be called ucb1400_ts.
 
+config TOUCHSCREEN_USB_COMPOSITE
+       tristate "USB Touchscreen Driver"
+       select USB
+       help
+         USB Touchscreen driver for:
+         - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
+         - PanJit TouchSet USB
+         - 3M MicroTouch USB (EX II series)
+         - ITM
+         - some other eTurboTouch
+         - Gunze AHL61
+         - DMC TSC-10/25
+
+         Have a look at <http://linux.chapter7.ch/touchkit/> for
+         a usage description and the required user-space stuff.
+
+         To compile this driver as a module, choose M here: the
+         module will be called usbtouchscreen.
+
+config TOUCHSCREEN_USB_EGALAX
+       default y
+       bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_PANJIT
+       default y
+       bool "PanJit device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_3M
+       default y
+       bool "3M/Microtouch EX II series device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ITM
+       default y
+       bool "ITM device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ETURBO
+       default y
+       bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GUNZE
+       default y
+       bool "Gunze AHL61 device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_DMC_TSC10
+       default y
+       bool "DMC TSC-10/25 device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
+
 endif
index 30e6e2217a15d86d72f153ca2fa3af9086f7ca70..2f86d6ad06d3a193fedcdd01b2a4dd7dbb498491 100644 (file)
@@ -1,17 +1,18 @@
 #
-# Makefile for the mouse drivers.
+# Makefile for the touchscreen drivers.
 #
 
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
-obj-$(CONFIG_TOUCHSCREEN_BITSY)        += h3600_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_CORGI)        += corgi_ts.o
-obj-$(CONFIG_TOUCHSCREEN_GUNZE)        += gunze.o
-obj-$(CONFIG_TOUCHSCREEN_ELO)  += elo.o
-obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
-obj-$(CONFIG_TOUCHSCREEN_MK712)        += mk712.o
-obj-$(CONFIG_TOUCHSCREEN_HP600)        += hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_CORGI)                += corgi_ts.o
+obj-$(CONFIG_TOUCHSCREEN_GUNZE)                += gunze.o
+obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
+obj-$(CONFIG_TOUCHSCREEN_MTOUCH)       += mtouch.o
+obj-$(CONFIG_TOUCHSCREEN_MK712)                += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_HP600)                += hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)        += usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)     += penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
similarity index 99%
rename from drivers/usb/input/usbtouchscreen.c
rename to drivers/input/touchscreen/usbtouchscreen.c
index e0829413336b669a3d152681982930ec2480e013..8e18e6c6477771566a33b52e12ffbc9f28b8d098 100644 (file)
@@ -668,9 +668,8 @@ static void usbtouch_close(struct input_dev *input)
 static void usbtouch_free_buffers(struct usb_device *udev,
                                  struct usbtouch_usb *usbtouch)
 {
-       if (usbtouch->data)
-               usb_buffer_free(udev, usbtouch->type->rept_size,
-                               usbtouch->data, usbtouch->data_dma);
+       usb_buffer_free(udev, usbtouch->type->rept_size,
+                       usbtouch->data, usbtouch->data_dma);
        kfree(usbtouch->buffer);
 }
 
index 5e5b5c91d75b1286451ff30b84ccf6985da12ff4..8238b13874c200f33ee5ff7534dc7264e9d81919 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/major.h>
-#include <linux/smp_lock.h>
 #include <linux/random.h>
 #include <linux/time.h>
 #include <linux/device.h>
index c921d6c522f50ef257d825894b0f059bc9f11044..c92f9d764fce68f52158f80eb686d92701c4078f 100644 (file)
@@ -17,7 +17,7 @@ config CAPI_TRACE
        help
          If you say Y here, the kernelcapi driver can make verbose traces
          of CAPI messages. This feature can be enabled/disabled via IOCTL for
-         every controler (default disabled).
+         every controller (default disabled).
          This will increase the size of the kernelcapi module by 20 KB.
          If unsure, say Y.
 
index db1260f73f10e2aee4ea40dce75c09c62a79f570..81661b8bd3a865cf1f83c09a00b9b81355a5a909 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/fcntl.h>
 #include <linux/fs.h>
 #include <linux/signal.h>
+#include <linux/mutex.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -147,7 +147,7 @@ struct capidev {
 
        struct capincci *nccis;
 
-       struct semaphore ncci_list_sem;
+       struct mutex ncci_list_mtx;
 };
 
 /* -------- global variables ---------------------------------------- */
@@ -395,7 +395,7 @@ static struct capidev *capidev_alloc(void)
        if (!cdev)
                return NULL;
 
-       init_MUTEX(&cdev->ncci_list_sem);
+       mutex_init(&cdev->ncci_list_mtx);
        skb_queue_head_init(&cdev->recvqueue);
        init_waitqueue_head(&cdev->recvwait);
        write_lock_irqsave(&capidev_list_lock, flags);
@@ -414,9 +414,9 @@ static void capidev_free(struct capidev *cdev)
        }
        skb_queue_purge(&cdev->recvqueue);
 
-       down(&cdev->ncci_list_sem);
+       mutex_lock(&cdev->ncci_list_mtx);
        capincci_free(cdev, 0xffffffff);
-       up(&cdev->ncci_list_sem);
+       mutex_unlock(&cdev->ncci_list_mtx);
 
        write_lock_irqsave(&capidev_list_lock, flags);
        list_del(&cdev->list);
@@ -603,15 +603,15 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
        if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
                u16 info = CAPIMSG_U16(skb->data, 12); // Info field
                if (info == 0) {
-                       down(&cdev->ncci_list_sem);
+                       mutex_lock(&cdev->ncci_list_mtx);
                        capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
-                       up(&cdev->ncci_list_sem);
+                       mutex_unlock(&cdev->ncci_list_mtx);
                }
        }
        if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) {
-               down(&cdev->ncci_list_sem);
+               mutex_lock(&cdev->ncci_list_mtx);
                capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
-               up(&cdev->ncci_list_sem);
+               mutex_unlock(&cdev->ncci_list_mtx);
        }
        spin_lock_irqsave(&workaround_lock, flags);
        if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
@@ -752,9 +752,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
        CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
 
        if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
-               down(&cdev->ncci_list_sem);
+               mutex_lock(&cdev->ncci_list_mtx);
                capincci_free(cdev, CAPIMSG_NCCI(skb->data));
-               up(&cdev->ncci_list_sem);
+               mutex_unlock(&cdev->ncci_list_mtx);
        }
 
        cdev->errcode = capi20_put_message(&cdev->ap, skb);
@@ -939,9 +939,9 @@ capi_ioctl(struct inode *inode, struct file *file,
                        if (copy_from_user(&ncci, argp, sizeof(ncci)))
                                return -EFAULT;
 
-                       down(&cdev->ncci_list_sem);
+                       mutex_lock(&cdev->ncci_list_mtx);
                        if ((nccip = capincci_find(cdev, (u32) ncci)) == 0) {
-                               up(&cdev->ncci_list_sem);
+                               mutex_unlock(&cdev->ncci_list_mtx);
                                return 0;
                        }
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -949,7 +949,7 @@ capi_ioctl(struct inode *inode, struct file *file,
                                count += atomic_read(&mp->ttyopencount);
                        }
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
-                       up(&cdev->ncci_list_sem);
+                       mutex_unlock(&cdev->ncci_list_mtx);
                        return count;
                }
                return 0;
@@ -964,14 +964,14 @@ capi_ioctl(struct inode *inode, struct file *file,
                        if (copy_from_user(&ncci, argp,
                                           sizeof(ncci)))
                                return -EFAULT;
-                       down(&cdev->ncci_list_sem);
+                       mutex_lock(&cdev->ncci_list_mtx);
                        nccip = capincci_find(cdev, (u32) ncci);
                        if (!nccip || (mp = nccip->minorp) == 0) {
-                               up(&cdev->ncci_list_sem);
+                               mutex_unlock(&cdev->ncci_list_mtx);
                                return -ESRCH;
                        }
                        unit = mp->minor;
-                       up(&cdev->ncci_list_sem);
+                       mutex_unlock(&cdev->ncci_list_mtx);
                        return unit;
                }
                return 0;
index ad1e2702c2d1734b00d74678ab2295e350e10274..22379b94e88f0f0a2bdaec108f3dfbb9a187d749 100644 (file)
@@ -855,7 +855,7 @@ static _cdebbuf *g_debbuf;
 static u_long g_debbuf_lock;
 static _cmsg *g_cmsg;
 
-_cdebbuf *cdebbuf_alloc(void)
+static _cdebbuf *cdebbuf_alloc(void)
 {
        _cdebbuf *cdb;
 
@@ -989,11 +989,6 @@ _cdebbuf *capi_cmsg2str(_cmsg * cmsg)
        return &g_debbuf;
 }
 
-_cdebbuf *cdebbuf_alloc(void)
-{
-       return &g_debbuf;
-}
-
 void cdebbuf_free(_cdebbuf *cdb)
 {
 }
@@ -1009,7 +1004,6 @@ void __exit cdebug_exit(void)
 
 #endif
 
-EXPORT_SYMBOL(cdebbuf_alloc);
 EXPORT_SYMBOL(cdebbuf_free);
 EXPORT_SYMBOL(capi_cmsg2message);
 EXPORT_SYMBOL(capi_message2cmsg);
index 53a189003355b125b5bf9bb7cbd2b133d4ef9147..be77ee625bb75e4d63181fbeb396f2b08cc591b6 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #else
index c8e1c357cec88870e4984233a93af30bb3bac70e..a1263019df5edec8543d25220b1e416b45a46b9e 100644 (file)
@@ -138,8 +138,6 @@ struct usb_cardstate {
        char                    bchars[6];              /* for request 0x19 */
 };
 
-struct usb_bc_state {};
-
 static inline unsigned tiocm_to_gigaset(unsigned state)
 {
        return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0);
@@ -579,25 +577,21 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
 
 static int gigaset_freebcshw(struct bc_state *bcs)
 {
-       if (!bcs->hw.usb)
-               return 0;
-       //FIXME
-       kfree(bcs->hw.usb);
+       /* unused */
        return 1;
 }
 
 /* Initialize the b-channel structure */
 static int gigaset_initbcshw(struct bc_state *bcs)
 {
-       bcs->hw.usb = kmalloc(sizeof(struct usb_bc_state), GFP_KERNEL);
-       if (!bcs->hw.usb)
-               return 0;
-
+       /* unused */
+       bcs->hw.usb = NULL;
        return 1;
 }
 
 static void gigaset_reinitbcshw(struct bc_state *bcs)
 {
+       /* nothing to do for M10x */
 }
 
 static void gigaset_freecshw(struct cardstate *cs)
index 7a74ed35b1bfa721745511bac3dcadb4f55b291e..98fcdfc7ca555ca7440923e268b4f3cf24af0862 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 
 #include "os_capi.h"
diff --git a/drivers/isdn/hardware/eicon/dbgioctl.h b/drivers/isdn/hardware/eicon/dbgioctl.h
deleted file mode 100644 (file)
index 0fb6f5e..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-
-/*
- *
-  Copyright (c) Eicon Technology Corporation, 2000.
- *
-  This source file is supplied for the use with Eicon
-  Technology Corporation's range of DIVA Server Adapters.
- *
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2, or (at your option)
-  any later version.
- *
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
-  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU General Public License for more details.
- *
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/*------------------------------------------------------------------*/
-/* file: dbgioctl.h                                                 */
-/*------------------------------------------------------------------*/
-
-#if !defined(__DBGIOCTL_H__)
-
-#define __DBGIOCTL_H__
-
-#ifdef NOT_YET_NEEDED
-/*
- * The requested operation is passed in arg0 of DbgIoctlArgs,
- * additional arguments (if any) in arg1, arg2 and arg3.
- */
-
-typedef struct
-{      ULONG   arg0 ;
-       ULONG   arg1 ;
-       ULONG   arg2 ;
-       ULONG   arg3 ;
-} DbgIoctlArgs ;
-
-#define        DBG_COPY_LOGS   0       /* copy debugs to user until buffer full        */
-                                                       /* arg1: size threshold                                         */
-                                                       /* arg2: timeout in milliseconds                        */
-
-#define DBG_FLUSH_LOGS 1       /* flush pending debugs to user buffer          */
-                                                       /* arg1: internal driver id                                     */
-
-#define DBG_LIST_DRVS  2       /* return the list of registered drivers        */
-
-#define        DBG_GET_MASK    3       /* get current debug mask of driver                     */
-                                                       /* arg1: internal driver id                                     */
-
-#define        DBG_SET_MASK    4       /* set/change debug mask of driver                      */
-                                                       /* arg1: internal driver id                                     */
-                                                       /* arg2: new debug mask                                         */
-
-#define        DBG_GET_BUFSIZE 5       /* get current buffer size of driver            */
-                                                       /* arg1: internal driver id                                     */
-                                                       /* arg2: new debug mask                                         */
-
-#define        DBG_SET_BUFSIZE 6       /* set new buffer size of driver                        */
-                                                       /* arg1: new buffer size                                        */
-
-/*
- *     common internal debug message structure
- */
-
-typedef struct
-{      unsigned short id ;             /* virtual driver id                  */
-       unsigned short type ;   /* special message type               */
-       unsigned long  seq ;    /* sequence number of message         */
-       unsigned long  size ;   /* size of message in bytes           */
-       unsigned long  next ;   /* offset to next buffered message    */
-       LARGE_INTEGER  NTtime ; /* 100 ns  since 1.1.1601             */
-       unsigned char  data[4] ;/* message data                       */
-} OldDbgMessage ;
-
-typedef struct
-{      LARGE_INTEGER  NTtime ; /* 100 ns  since 1.1.1601             */
-       unsigned short size ;   /* size of message in bytes           */
-       unsigned short ffff ;   /* always 0xffff to indicate new msg  */
-       unsigned short id ;             /* virtual driver id                  */
-       unsigned short type ;   /* special message type               */
-       unsigned long  seq ;    /* sequence number of message         */
-       unsigned char  data[4] ;/* message data                       */
-} DbgMessage ;
-
-#endif
-
-#define DRV_ID_UNKNOWN         0x0C    /* for messages via prtComp() */
-
-#define        MSG_PROC_FLAG           0x80
-#define        MSG_PROC_NO_GET(x)      (((x) & MSG_PROC_FLAG) ? (((x) >> 4) & 7) : -1)
-#define        MSG_PROC_NO_SET(x)      (MSG_PROC_FLAG | (((x) & 7) << 4))
-
-#define MSG_TYPE_DRV_ID                0x0001
-#define MSG_TYPE_FLAGS         0x0002
-#define MSG_TYPE_STRING                0x0003
-#define MSG_TYPE_BINARY                0x0004
-
-#define MSG_HEAD_SIZE  ((unsigned long)&(((DbgMessage *)0)->data[0]))
-#define MSG_ALIGN(len) (((unsigned long)(len) + MSG_HEAD_SIZE + 3) & ~3)
-#define MSG_SIZE(pMsg) MSG_ALIGN((pMsg)->size)
-#define MSG_NEXT(pMsg) ((DbgMessage *)( ((char *)(pMsg)) + MSG_SIZE(pMsg) ))
-
-#define OLD_MSG_HEAD_SIZE      ((unsigned long)&(((OldDbgMessage *)0)->data[0]))
-#define OLD_MSG_ALIGN(len)     (((unsigned long)(len)+OLD_MSG_HEAD_SIZE+3) & ~3)
-
-/*
- * manifest constants
- */
-
-#define MSG_FRAME_MAX_SIZE     2150            /* maximum size of B1 frame      */
-#define MSG_TEXT_MAX_SIZE      1024            /* maximum size of msg text      */
-#define MSG_MAX_SIZE           MSG_ALIGN(MSG_FRAME_MAX_SIZE)
-#define DBG_MIN_BUFFER_SIZE    0x00008000      /* minimal total buffer size  32 KB */
-#define DBG_DEF_BUFFER_SIZE    0x00020000      /* default total buffer size 128 KB */
-#define DBG_MAX_BUFFER_SIZE    0x00400000      /* maximal total buffer size   4 MB */
-
-#define DBGDRV_NAME            "Diehl_DIMAINT"
-#define UNIDBG_DRIVER  L"\\Device\\Diehl_DIMAINT" /* UNICODE name for kernel */
-#define DEBUG_DRIVER   "\\\\.\\" DBGDRV_NAME  /* traditional string for apps */
-#define DBGVXD_NAME            "DIMAINT"
-#define DEBUG_VXD              "\\\\.\\" DBGVXD_NAME  /* traditional string for apps */
-
-/*
- *     Special IDI interface debug construction
- */
-
-#define        DBG_IDI_SIG_REQ         (unsigned long)0xF479C402
-#define        DBG_IDI_SIG_IND         (unsigned long)0xF479C403
-#define        DBG_IDI_NL_REQ          (unsigned long)0xF479C404
-#define        DBG_IDI_NL_IND          (unsigned long)0xF479C405
-
-typedef struct
-{      unsigned long  magic_type ;
-       unsigned short data_len ;
-       unsigned char  layer_ID ;
-       unsigned char  entity_ID ;
-       unsigned char  request ;
-       unsigned char  ret_code ;
-       unsigned char  indication ;
-       unsigned char  complete ;
-       unsigned char  data[4] ;
-} DbgIdiAct, *DbgIdiAction ;
-
-/*
- * We want to use the same IOCTL codes in Win95 and WinNT.
- * The official constructor for IOCTL codes is the CTL_CODE macro
- * from <winoctl.h> (<devioctl.h> in WinNT DDK environment).
- * The problem here is that we don't know how to get <winioctl.h>
- * working in a Win95 DDK environment!
- */
-
-# ifdef CTL_CODE       /*{*/
-
-/* Assert that we have the same idea of the CTL_CODE macro.    */
-
-#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-
-# else /* !CTL_CODE */ /*}{*/
-
-/* Use the definitions stolen from <winioctl.h>.  */
-
-#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-
-#define METHOD_BUFFERED                 0
-#define METHOD_IN_DIRECT                1
-#define METHOD_OUT_DIRECT               2
-#define METHOD_NEITHER                  3
-
-#define FILE_ANY_ACCESS                 0
-#define FILE_READ_ACCESS          ( 0x0001 )    // file & pipe
-#define FILE_WRITE_ACCESS         ( 0x0002 )    // file & pipe
-
-# endif        /* CTL_CODE */ /*}*/
-
-/*
- * Now we can define WinNT/Win95 DeviceIoControl codes.
- *
- * These codes are defined in di_defs.h too, a possible mismatch will be
- * detected when the dbgtool is compiled.
- */
-
-#define IOCTL_DRIVER_LNK \
-       CTL_CODE(0x8001U,0x701,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
-#define IOCTL_DRIVER_DBG \
-       CTL_CODE(0x8001U,0x702,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
-
-#endif /* __DBGIOCTL_H__ */
index 4aba5c502d8e18759fb274f522244700b4abf752..c90928974249b6acf52996e8929a202d0ad6571f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <asm/uaccess.h>
 
index 556b19615bc76e2e8a1a0cb7458687f7449370b0..78f141e7746601591902ad8dbf4acb7684737459 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
index 5e862e2441171e029954a76a01713bd5aa8adf72..6d39f9360766a896ef33870d1bcb55f739fd7a2e 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/ioport.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/poll.h>
index af3eb9e795b500faba4eaa15eca11152b54c8872..85784a7ffb25bc6d7923b8d66fd38457346d38f9 100644 (file)
@@ -216,7 +216,7 @@ typedef struct
 #define SERIAL_HOOK_RING 0x85
 #define SERIAL_HOOK_DETACH 0x8f
  unsigned char Flags;           /* function refinements   */
- /* parameters passed by the the ATTACH request      */
+ /* parameters passed by the ATTACH request      */
  SERIAL_INT_CB InterruptHandler; /* called on each interrupt  */
  SERIAL_DPC_CB DeferredHandler; /* called on hook state changes */
  void   *HandlerContext; /* context for both handlers */
diff --git a/drivers/isdn/hardware/eicon/main_if.h b/drivers/isdn/hardware/eicon/main_if.h
deleted file mode 100644 (file)
index 0ea339a..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
-  Copyright (c) Eicon Technology Corporation, 2000.
- *
-  This source file is supplied for the use with Eicon
-  Technology Corporation's range of DIVA Server Adapters.
- *
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2, or (at your option)
-  any later version.
- *
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
-  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU General Public License for more details.
- *
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/*------------------------------------------------------------------*/
-/* file: main_if.h                                                  */
-/*------------------------------------------------------------------*/
-# ifndef MAIN_IF___H
-# define MAIN_IF___H
-
-# include "debug_if.h"
-
-void  DI_lock (void) ;
-void  DI_unlock (void) ;
-
-#ifdef NOT_YET_NEEDED
-void  DI_nttime (LARGE_INTEGER *NTtime) ;
-void  DI_ntlcltime(LARGE_INTEGER *NTtime, LARGE_INTEGER *lclNTtime) ;
-void  DI_nttimefields(LARGE_INTEGER *NTtime, TIME_FIELDS *TimeFields);
-unsigned long  DI_wintime(LARGE_INTEGER *NTtime) ;
-
-unsigned short  DiInsertProcessorNumber (int type) ;
-void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap);
-
-void  StartIoctlTimer (void (*Handler)(void), unsigned long msec) ;
-void  StopIoctlTimer (void) ;
-void  UnpendIoctl (DbgRequest *pDbgReq) ;
-#endif
-
-void add_to_q(int, char* , unsigned int);
-# endif /* MAIN_IF___H */
-
index ff09f07f440a43017aa24f9ad304abf33968a27f..15d4942de53bae5badbab4bcac2c254a31628e36 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/vmalloc.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <asm/types.h>
index 9f44d3e69fb0e78ef86362031999f0911e15c337..1f18f19933876d08ba94e2e4fde007cd7c52fa6a 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/usb.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include "hisax.h"
 #include "hisax_if.h"
 #include "hfc_usb.h"
@@ -1218,11 +1217,11 @@ usb_init(hfcusb_data * hfc)
        /* aux = output, reset off */
        write_usb(hfc, HFCUSB_CIRM, 0x10);
 
-       /* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */
+       /* set USB_SIZE to match the wMaxPacketSize for INT or BULK transfers */
        write_usb(hfc, HFCUSB_USB_SIZE,
                  (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4));
 
-       /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
+       /* set USB_SIZE_I to match the wMaxPacketSize for ISO transfers */
        write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
 
        /* enable PCM/GCI master mode */
index 84dccd526ac07dc0488db9f6c60b21031f3c8299..6cdbad3a992631f185911a62ff79309516462eba 100644 (file)
@@ -443,7 +443,7 @@ ergo_inithardware(hysdn_card * card)
        card->waitpofready = ergo_waitpofready;
        card->set_errlog_state = ergo_set_errlog_state;
        INIT_WORK(&card->irq_queue, ergo_irq_bh);
-       card->hysdn_lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&card->hysdn_lock);
 
        return (0);
 }                              /* ergo_inithardware */
index 4c7dedac0e51a5d2fd1faf831e46da63e365a167..27b3991fb0ec600e031ae1f4627b173fea4a0ce9 100644 (file)
@@ -297,8 +297,6 @@ hysdn_log_close(struct inode *ino, struct file *filep)
        struct procdata *pd;
        hysdn_card *card;
        int retval = 0;
-       unsigned long flags;
-       spinlock_t hysdn_lock = SPIN_LOCK_UNLOCKED;
 
        lock_kernel();
        if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
@@ -308,7 +306,6 @@ hysdn_log_close(struct inode *ino, struct file *filep)
                /* read access -> log/debug read, mark one further file as closed */
 
                pd = NULL;
-               spin_lock_irqsave(&hysdn_lock, flags);
                inf = *((struct log_data **) filep->private_data);      /* get first log entry */
                if (inf)
                        pd = (struct procdata *) inf->proc_ctrl;        /* still entries there */
@@ -331,7 +328,6 @@ hysdn_log_close(struct inode *ino, struct file *filep)
                        inf->usage_cnt--;       /* decrement usage count for buffers */
                        inf = inf->next;
                }
-               spin_unlock_irqrestore(&hysdn_lock, flags);
 
                if (pd)
                        if (pd->if_used <= 0)   /* delete buffers if last file closed */
index e93ad59f60bf9020bb4772fd95d75922d2e29e7d..bb92e3cd9334a0bdf2822d28ef47bf0739ef2303 100644 (file)
@@ -1462,7 +1462,7 @@ isdnloop_initcard(char *id)
                skb_queue_head_init(&card->bqueue[i]);
        }
        skb_queue_head_init(&card->dqueue);
-       card->isdnloop_lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&card->isdnloop_lock);
        card->next = cards;
        cards = card;
        if (!register_isdn(&card->interface)) {
index c8b8cfa332bb9e7ac9684b12e6efe1e60d06af1f..0d892600ff00f91f48301a871712cbe8e51bb730 100644 (file)
@@ -2889,7 +2889,9 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
 
        switch (val) {
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
                       cpu);
                decache_vcpus_on_cpu(cpu);
@@ -2897,6 +2899,7 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
                                         NULL, 0, 1);
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
                       cpu);
                smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
index 1d49d2ade5579586d7418bcccc9e3a317695c9ab..677c99325be5add863bc487c3b942ccbdd5c5cbc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/leds/h1940-leds.c
+ * drivers/leds/leds-h1940.c
  * Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  * This file is subject to the terms and conditions of the GNU General Public
index 1a86387e23be2ebd541ad6fef1fbdff2949896fa..58926da0ae18c48a977b38fd6d9c67fe879ba805 100644 (file)
@@ -1,6 +1,10 @@
 
-menu "Macintosh device drivers"
+menuconfig MACINTOSH_DRIVERS
+       bool "Macintosh device drivers"
        depends on PPC || MAC || X86
+       default y
+
+if MACINTOSH_DRIVERS
 
 config ADB
        bool "Apple Desktop Bus (ADB) support"
@@ -109,7 +113,9 @@ config PMAC_SMU
 
 config PMAC_APM_EMU
        tristate "APM emulation"
-       depends on PPC_PMAC && PPC32 && PM && ADB_PMU
+       select SYS_SUPPORTS_APM_EMULATION
+       select APM_EMULATION
+       depends on ADB_PMU && PM
 
 config PMAC_MEDIABAY
        bool "Support PowerBook hotswap media bay"
@@ -231,7 +237,7 @@ config PMAC_RACKMETER
        tristate "Support for Apple XServe front panel LEDs"
        depends on PPC_PMAC
        help
-         This driver procides some support to control the front panel
+         This driver provides some support to control the front panel
           blue LEDs "vu-meter" of the XServer macs.
 
-endmenu
+endif # MACINTOSH_DRIVERS
index cdb0bead99171f7a58198b3e62717612b87dc410..9821e6361e60bcb4e9c16e5712823a2ca66f5253 100644 (file)
@@ -1,9 +1,7 @@
-/* APM emulation layer for PowerMac
- * 
- * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+/*
+ * APM emulation for PMU-based machines
  *
- * Lots of code inherited from apm.c, see appropriate notice in
- *  arch/i386/kernel/apm.c
+ * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
  *
  * 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
  *
  */
 
-#include <linux/module.h>
-
-#include <linux/poll.h>
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
-
+#include <linux/module.h>
+#include <linux/apm-emulation.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
 
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(args...) printk(KERN_DEBUG args)
-//#define DBG(args...) xmon_printf(args)
-#else
-#define DBG(args...) do { } while (0)
-#endif
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define        APM_MINOR_DEV   134
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS         20
-
-#define FAKE_APM_BIOS_VERSION  0x0101
-
-#define APM_USER_NOTIFY_TIMEOUT        (5*HZ)
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-       int             magic;
-       struct apm_user *       next;
-       int             suser: 1;
-       int             suspend_waiting: 1;
-       int             suspends_pending;
-       int             suspends_read;
-       int             event_head;
-       int             event_tail;
-       apm_event_t     events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_user
- */
-#define APM_BIOS_MAGIC         0x4101
-
-/*
- * Local variables
- */
-static int                     suspends_pending;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user *       user_list;
-
-static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier apm_sleep_notifier = {
-       apm_notify_sleep,
-       SLEEP_LEVEL_USERLAND,
-};
-
-static const char driver_version[] = "0.5";    /* no spaces */
-
-#ifdef DEBUG
-static char *  apm_event_name[] = {
-       "system standby",
-       "system suspend",
-       "normal resume",
-       "critical resume",
-       "low battery",
-       "power status change",
-       "update time",
-       "critical suspend",
-       "user standby",
-       "user suspend",
-       "system standby resume",
-       "capabilities change"
-};
-#define NR_APM_EVENT_NAME      \
-               (sizeof(apm_event_name) / sizeof(apm_event_name[0]))
-
-#endif
-
-static int queue_empty(struct apm_user *as)
-{
-       return as->event_head == as->event_tail;
-}
-
-static apm_event_t get_queued_event(struct apm_user *as)
-{
-       as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-       return as->events[as->event_tail];
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
-       struct apm_user *       as;
-
-       DBG("apm_emu: queue_event(%s)\n", apm_event_name[event-1]);
-       if (user_list == NULL)
-               return;
-       for (as = user_list; as != NULL; as = as->next) {
-               if (as == sender)
-                       continue;
-               as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-               if (as->event_head == as->event_tail) {
-                       static int notified;
-
-                       if (notified++ == 0)
-                           printk(KERN_ERR "apm_emu: an event queue overflowed\n");
-                       as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-               }
-               as->events[as->event_head] = event;
-               if (!as->suser)
-                       continue;
-               switch (event) {
-               case APM_SYS_SUSPEND:
-               case APM_USER_SUSPEND:
-                       as->suspends_pending++;
-                       suspends_pending++;
-                       break;
-               case APM_NORMAL_RESUME:
-                       as->suspend_waiting = 0;
-                       break;
-               }
-       }
-       wake_up_interruptible(&apm_waitqueue);
-}
-
-static int check_apm_user(struct apm_user *as, const char *func)
-{
-       if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-               printk(KERN_ERR "apm_emu: %s passed bad filp\n", func);
-               return 1;
-       }
-       return 0;
-}
-
-static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
-       struct apm_user *       as;
-       size_t                  i;
-       apm_event_t             event;
-       DECLARE_WAITQUEUE(wait, current);
-
-       as = fp->private_data;
-       if (check_apm_user(as, "read"))
-               return -EIO;
-       if (count < sizeof(apm_event_t))
-               return -EINVAL;
-       if (queue_empty(as)) {
-               if (fp->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               add_wait_queue(&apm_waitqueue, &wait);
-repeat:
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (queue_empty(as) && !signal_pending(current)) {
-                       schedule();
-                       goto repeat;
-               }
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&apm_waitqueue, &wait);
-       }
-       i = count;
-       while ((i >= sizeof(event)) && !queue_empty(as)) {
-               event = get_queued_event(as);
-               DBG("apm_emu: do_read, returning: %s\n", apm_event_name[event-1]);
-               if (copy_to_user(buf, &event, sizeof(event))) {
-                       if (i < count)
-                               break;
-                       return -EFAULT;
-               }
-               switch (event) {
-               case APM_SYS_SUSPEND:
-               case APM_USER_SUSPEND:
-                       as->suspends_read++;
-                       break;
-               }
-               buf += sizeof(event);
-               i -= sizeof(event);
-       }
-       if (i < count)
-               return count - i;
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-       return 0;
-}
-
-static unsigned int do_poll(struct file *fp, poll_table * wait)
-{
-       struct apm_user * as;
-
-       as = fp->private_data;
-       if (check_apm_user(as, "poll"))
-               return 0;
-       poll_wait(fp, &apm_waitqueue, wait);
-       if (!queue_empty(as))
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-static int do_ioctl(struct inode * inode, struct file *filp,
-                   u_int cmd, u_long arg)
-{
-       struct apm_user *       as;
-       DECLARE_WAITQUEUE(wait, current);
-
-       as = filp->private_data;
-       if (check_apm_user(as, "ioctl"))
-               return -EIO;
-       if (!as->suser)
-               return -EPERM;
-       switch (cmd) {
-       case APM_IOC_SUSPEND:
-               /* If a suspend message was sent to userland, we
-                * consider this as a confirmation message
-                */
-               if (as->suspends_read > 0) {
-                       as->suspends_read--;
-                       as->suspends_pending--;
-                       suspends_pending--;
-               } else {
-                       // Route to PMU suspend ?
-                       break;
-               }
-               as->suspend_waiting = 1;
-               add_wait_queue(&apm_waitqueue, &wait);
-               DBG("apm_emu: ioctl waking up sleep waiter !\n");
-               wake_up(&apm_suspend_waitqueue);
-               mb();
-               while(as->suspend_waiting && !signal_pending(current)) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule();
-               }
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&apm_waitqueue, &wait);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int do_release(struct inode * inode, struct file * filp)
-{
-       struct apm_user *       as;
-
-       as = filp->private_data;
-       if (check_apm_user(as, "release"))
-               return 0;
-       filp->private_data = NULL;
-       lock_kernel();
-       if (as->suspends_pending > 0) {
-               suspends_pending -= as->suspends_pending;
-               if (suspends_pending <= 0)
-                       wake_up(&apm_suspend_waitqueue);
-       }
-       if (user_list == as)
-               user_list = as->next;
-       else {
-               struct apm_user *       as1;
-
-               for (as1 = user_list;
-                    (as1 != NULL) && (as1->next != as);
-                    as1 = as1->next)
-                       ;
-               if (as1 == NULL)
-                       printk(KERN_ERR "apm: filp not in user list\n");
-               else
-                       as1->next = as->next;
-       }
-       unlock_kernel();
-       kfree(as);
-       return 0;
-}
-
-static int do_open(struct inode * inode, struct file * filp)
-{
-       struct apm_user *       as;
-
-       as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (as == NULL) {
-               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-                      sizeof(*as));
-               return -ENOMEM;
-       }
-       as->magic = APM_BIOS_MAGIC;
-       as->event_tail = as->event_head = 0;
-       as->suspends_pending = 0;
-       as->suspends_read = 0;
-       /*
-        * XXX - this is a tiny bit broken, when we consider BSD
-         * process accounting. If the device is opened by root, we
-        * instantly flag that we used superuser privs. Who knows,
-        * we might close the device immediately without doing a
-        * privileged operation -- cevans
-        */
-       as->suser = capable(CAP_SYS_ADMIN);
-       as->next = user_list;
-       user_list = as;
-       filp->private_data = as;
-
-       DBG("apm_emu: opened by %s, suser: %d\n", current->comm, (int)as->suser);
-
-       return 0;
-}
-
-/* Wait for all clients to ack the suspend request. APM API
- * doesn't provide a way to NAK, but this could be added
- * here.
- */
-static void wait_all_suspend(void)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       add_wait_queue(&apm_suspend_waitqueue, &wait);
-       DBG("apm_emu: wait_all_suspend(), suspends_pending: %d\n", suspends_pending);
-       while(suspends_pending > 0) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule();
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&apm_suspend_waitqueue, &wait);
-
-       DBG("apm_emu: wait_all_suspend() - complete !\n");
-}
-
-static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
-{
-       switch(when) {
-               case PBOOK_SLEEP_REQUEST:
-                       queue_event(APM_SYS_SUSPEND, NULL);
-                       wait_all_suspend();
-                       break;
-               case PBOOK_WAKE:
-                       queue_event(APM_NORMAL_RESUME, NULL);
-                       break;
-       }
-}
-
 #define APM_CRITICAL           10
 #define APM_LOW                        30
 
-static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
+static void pmu_apm_get_power_status(struct apm_power_info *info)
 {
-       /* Arguments, with symbols from linux/apm_bios.h.  Information is
-          from the Get Power Status (0x0a) call unless otherwise noted.
+       int percentage = -1;
+       int batteries = 0;
+       int time_units = -1;
+       int real_count = 0;
+       int i;
+       char charging = 0;
+       long charge = -1;
+       long amperage = 0;
+       unsigned long btype = 0;
+
+       info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
+       info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
+       info->units = APM_UNITS_MINS;
+
+       if (pmu_power_flags & PMU_PWR_AC_PRESENT)
+               info->ac_line_status = APM_AC_ONLINE;
+       else
+               info->ac_line_status = APM_AC_OFFLINE;
 
-          0) Linux driver version (this will change if format changes)
-          1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
-          2) APM flags from APM Installation Check (0x00):
-             bit 0: APM_16_BIT_SUPPORT
-             bit 1: APM_32_BIT_SUPPORT
-             bit 2: APM_IDLE_SLOWS_CLOCK
-             bit 3: APM_BIOS_DISABLED
-             bit 4: APM_BIOS_DISENGAGED
-          3) AC line status
-             0x00: Off-line
-             0x01: On-line
-             0x02: On backup power (BIOS >= 1.1 only)
-             0xff: Unknown
-          4) Battery status
-             0x00: High
-             0x01: Low
-             0x02: Critical
-             0x03: Charging
-             0x04: Selected battery not present (BIOS >= 1.2 only)
-             0xff: Unknown
-          5) Battery flag
-             bit 0: High
-             bit 1: Low
-             bit 2: Critical
-             bit 3: Charging
-             bit 7: No system battery
-             0xff: Unknown
-          6) Remaining battery life (percentage of charge):
-             0-100: valid
-             -1: Unknown
-          7) Remaining battery life (time units):
-             Number of remaining minutes or seconds
-             -1: Unknown
-          8) min = minutes; sec = seconds */
-
-       unsigned short  ac_line_status;
-       unsigned short  battery_status = 0;
-       unsigned short  battery_flag   = 0xff;
-       int             percentage     = -1;
-       int             time_units     = -1;
-       int             real_count     = 0;
-       int             i;
-       char *          p = buf;
-       char            charging       = 0;
-       long            charge         = -1;
-       long            amperage       = 0;
-       unsigned long   btype          = 0;
-
-       ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0);
        for (i=0; i<pmu_battery_count; i++) {
                if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
-                       battery_status++;
+                       batteries++;
                        if (percentage < 0)
                                percentage = 0;
                        if (charge < 0)
@@ -456,9 +64,9 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
                                charging++;
                }
        }
-       if (0 == battery_status)
-               ac_line_status = 1;
-       battery_status = 0xff;
+       if (batteries == 0)
+               info->ac_line_status = APM_AC_ONLINE;
+
        if (real_count) {
                if (amperage < 0) {
                        if (btype == PMU_BATT_TYPE_SMART)
@@ -468,85 +76,44 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
                }
                percentage /= real_count;
                if (charging > 0) {
-                       battery_status = 0x03;
-                       battery_flag = 0x08;
+                       info->battery_status = APM_BATTERY_STATUS_CHARGING;
+                       info->battery_flag = APM_BATTERY_FLAG_CHARGING;
                } else if (percentage <= APM_CRITICAL) {
-                       battery_status = 0x02;
-                       battery_flag = 0x04;
+                       info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+                       info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
                } else if (percentage <= APM_LOW) {
-                       battery_status = 0x01;
-                       battery_flag = 0x02;
+                       info->battery_status = APM_BATTERY_STATUS_LOW;
+                       info->battery_flag = APM_BATTERY_FLAG_LOW;
                } else {
-                       battery_status = 0x00;
-                       battery_flag = 0x01;
+                       info->battery_status = APM_BATTERY_STATUS_HIGH;
+                       info->battery_flag = APM_BATTERY_FLAG_HIGH;
                }
        }
-       p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-                    driver_version,
-                    (FAKE_APM_BIOS_VERSION >> 8) & 0xff,
-                    FAKE_APM_BIOS_VERSION & 0xff,
-                    0,
-                    ac_line_status,
-                    battery_status,
-                    battery_flag,
-                    percentage,
-                    time_units,
-                    "min");
 
-       return p - buf;
+       info->battery_life = percentage;
+       info->time = time_units;
 }
 
-static const struct file_operations apm_bios_fops = {
-       .owner          = THIS_MODULE,
-       .read           = do_read,
-       .poll           = do_poll,
-       .ioctl          = do_ioctl,
-       .open           = do_open,
-       .release        = do_release,
-};
-
-static struct miscdevice apm_device = {
-       APM_MINOR_DEV,
-       "apm_bios",
-       &apm_bios_fops
-};
-
 static int __init apm_emu_init(void)
 {
-       struct proc_dir_entry *apm_proc;
-
-       if (sys_ctrler != SYS_CTRLER_PMU) {
-               printk(KERN_INFO "apm_emu: Requires a machine with a PMU.\n");
-               return -ENODEV;
-       }
-               
-       apm_proc = create_proc_info_entry("apm", 0, NULL, apm_emu_get_info);
-       if (apm_proc)
-               apm_proc->owner = THIS_MODULE;
+       apm_get_power_status = pmu_apm_get_power_status;
 
-       if (misc_register(&apm_device) != 0)
-               printk(KERN_INFO "Could not create misc. device for apm\n");
-
-       pmu_register_sleep_notifier(&apm_sleep_notifier);
-
-       printk(KERN_INFO "apm_emu: APM Emulation %s initialized.\n", driver_version);
+       printk(KERN_INFO "apm_emu: PMU APM Emulation initialized.\n");
 
        return 0;
 }
 
 static void __exit apm_emu_exit(void)
 {
-       pmu_unregister_sleep_notifier(&apm_sleep_notifier);
-       misc_deregister(&apm_device);
-       remove_proc_entry("apm", NULL);
+       if (apm_get_power_status == pmu_apm_get_power_status)
+               apm_get_power_status = NULL;
 
-       printk(KERN_INFO "apm_emu: APM Emulation removed.\n");
+       printk(KERN_INFO "apm_emu: PMU APM Emulation removed.\n");
 }
 
 module_init(apm_emu_init);
 module_exit(apm_emu_exit);
 
 MODULE_AUTHOR("Benjamin Herrenschmidt");
-MODULE_DESCRIPTION("APM emulation layer for PowerMac");
+MODULE_DESCRIPTION("APM emulation for PowerMac");
 MODULE_LICENSE("GPL");
-
index 1599dc34f15fbbfd151ecc264680bfe20191ed95..76c1e8e4a48779a9e68562802406f3ac12d4c504 100644 (file)
@@ -24,7 +24,7 @@ static int mouse_last_keycode;
 
 #if defined(CONFIG_SYSCTL)
 /* file(s) in /proc/sys/dev/mac_hid */
-ctl_table mac_hid_files[] = {
+static ctl_table mac_hid_files[] = {
        {
                .ctl_name       = DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
                .procname       = "mouse_button_emulation",
@@ -53,7 +53,7 @@ ctl_table mac_hid_files[] = {
 };
 
 /* dir in /proc/sys/dev */
-ctl_table mac_hid_dir[] = {
+static ctl_table mac_hid_dir[] = {
        {
                .ctl_name       = DEV_MAC_HID,
                .procname       = "mac_hid",
@@ -65,7 +65,7 @@ ctl_table mac_hid_dir[] = {
 };
 
 /* /proc/sys/dev itself, in case that is not there yet */
-ctl_table mac_hid_root_dir[] = {
+static ctl_table mac_hid_root_dir[] = {
        {
                .ctl_name       = CTL_DEV,
                .procname       = "dev",
@@ -127,7 +127,7 @@ static int emumousebtn_input_register(void)
        return ret;
 }
 
-int __init mac_hid_init(void)
+static int __init mac_hid_init(void)
 {
        int err;
 
index cc8267912656363a5e50545a3430b8523d09fcaa..112e5ef728f14c9c939afdc95ca5ce604e273f4f 100644 (file)
@@ -41,28 +41,15 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf)
 static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
                              char *buf)
 {
-       struct of_device *of;
-       const char *compat;
-       int cplen;
-       int length;
+       struct of_device *ofdev = to_of_device(dev);
+       int len;
 
-       of = &to_macio_device (dev)->ofdev;
-       compat = of_get_property(of->node, "compatible", &cplen);
-       if (!compat) compat = "", cplen = 1;
-       length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type);
-       buf += length;
-       while (cplen > 0) {
-               int l;
-               l = sprintf (buf, "C%s", compat);
-               length += l;
-               buf += l;
-               l = strlen (compat) + 1;
-               compat += l;
-               cplen -= l;
-       }
-       length += sprintf(buf, "\n");
+       len = of_device_get_modalias(ofdev, buf, PAGE_SIZE);
 
-       return length;
+       buf[len] = '\n';
+       buf[len+1] = 0;
+
+       return len+1;
 }
 
 macio_config_of_attr (name, "%s\n");
index a98a328b1cfcf335a637079cbc6c3b189c8c27a1..f8e1a135bf9d2db4a1c62a0962873f1df24d1bd8 100644 (file)
@@ -606,7 +606,7 @@ static void smu_expose_childs(struct work_struct *unused)
        struct device_node *np;
 
        for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;)
-               if (device_is_compatible(np, "smu-sensors"))
+               if (of_device_is_compatible(np, "smu-sensors"))
                        of_platform_device_create(np, "smu-sensors",
                                                  &smu->of_dev->dev);
 }
index 228903403cfcf78334184cf5aa3df2f99285a706..bd55e6ab99fc536164fe0c5b72a107fb6b6012f3 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
@@ -560,9 +559,9 @@ thermostat_init(void)
        np = of_find_node_by_name(NULL, "fan");
        if (!np)
                return -ENODEV;
-       if (device_is_compatible(np, "adt7460"))
+       if (of_device_is_compatible(np, "adt7460"))
                therm_type = ADT7460;
-       else if (device_is_compatible(np, "adt7467"))
+       else if (of_device_is_compatible(np, "adt7467"))
                therm_type = ADT7467;
        else
                return -ENODEV;
index 78ff186171393eaac54f54fe00a1aef4b7c276df..dbb22403979f034c5c060c17e0b4c5b1f64a82dc 100644 (file)
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/reboot.h>
 #include <linux/kmod.h>
index fc89a7047cd0b0a24925e9ec97d86efcb81e1a32..55ad95671387636c4b7d2852367baf12a3081fed 100644 (file)
@@ -31,7 +31,6 @@ static spinlock_t pmu_blink_lock;
 static struct adb_request pmu_blink_req;
 /* -1: no change, 0: request off, 1: request on */
 static int requested_change;
-static int sleeping;
 
 static void pmu_req_done(struct adb_request * req)
 {
@@ -41,7 +40,7 @@ static void pmu_req_done(struct adb_request * req)
        /* if someone requested a change in the meantime
         * (we only see the last one which is fine)
         * then apply it now */
-       if (requested_change != -1 && !sleeping)
+       if (requested_change != -1 && !pmu_sys_suspended)
                pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
        /* reset requested change */
        requested_change = -1;
@@ -66,7 +65,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
                break;
        }
        /* if request isn't done, then don't do anything */
-       if (pmu_blink_req.complete && !sleeping)
+       if (pmu_blink_req.complete && !pmu_sys_suspended)
                pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
  out:
        spin_unlock_irqrestore(&pmu_blink_lock, flags);
@@ -80,32 +79,6 @@ static struct led_classdev pmu_led = {
        .brightness_set = pmu_led_set,
 };
 
-#ifdef CONFIG_PM
-static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu_blink_lock, flags);
-
-       switch (when) {
-       case PBOOK_SLEEP_REQUEST:
-               sleeping = 1;
-               break;
-       case PBOOK_WAKE:
-               sleeping = 0;
-               break;
-       default:
-               /* do nothing */
-               break;
-       }
-       spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
-       .notifier_call = pmu_led_sleep_call,
-};
-#endif
-
 static int __init via_pmu_led_init(void)
 {
        struct device_node *dt;
@@ -135,9 +108,7 @@ static int __init via_pmu_led_init(void)
        /* no outstanding req */
        pmu_blink_req.complete = 1;
        pmu_blink_req.done = pmu_req_done;
-#ifdef CONFIG_PM
-       pmu_register_sleep_notifier(&via_pmu_led_sleep_notif);
-#endif
+
        return led_classdev_register(NULL, &pmu_led);
 }
 
index 1729d3fd7a11417ed63c784986290b9bba5b1a4c..157080b3b4688206eca50c71fc498aeeaf765c1f 100644 (file)
@@ -310,14 +310,14 @@ int __init find_via_pmu(void)
                        PMU_INT_TICK;
        
        if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
-           || device_is_compatible(vias->parent, "ohare")))
+           || of_device_is_compatible(vias->parent, "ohare")))
                pmu_kind = PMU_OHARE_BASED;
-       else if (device_is_compatible(vias->parent, "paddington"))
+       else if (of_device_is_compatible(vias->parent, "paddington"))
                pmu_kind = PMU_PADDINGTON_BASED;
-       else if (device_is_compatible(vias->parent, "heathrow"))
+       else if (of_device_is_compatible(vias->parent, "heathrow"))
                pmu_kind = PMU_HEATHROW_BASED;
-       else if (device_is_compatible(vias->parent, "Keylargo")
-                || device_is_compatible(vias->parent, "K2-Keylargo")) {
+       else if (of_device_is_compatible(vias->parent, "Keylargo")
+                || of_device_is_compatible(vias->parent, "K2-Keylargo")) {
                struct device_node *gpiop;
                struct device_node *adbp;
                u64 gaddr = OF_BAD_ADDR;
@@ -2759,7 +2759,7 @@ pmu_polled_request(struct adb_request *req)
 
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
-static int pmu_sys_suspended;
+int pmu_sys_suspended;
 
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
 {
index 94c117ef20c1d74b59e4c445ef3e006f01399c51..192b26e97777e985c6bf61b89491c5174cb56066 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
 #include <linux/reboot.h>
index ab4d1b63f63e673c70f3321a837cc4f029a380c4..a0fabf3c20081f7e35ffebd5f62b602a28ab8085 100644 (file)
@@ -188,10 +188,10 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
                if (loc == NULL || addr == 0)
                        continue;
                /* real lm75 */
-               if (device_is_compatible(dev, "lm75"))
+               if (of_device_is_compatible(dev, "lm75"))
                        wf_lm75_create(adapter, addr, 0, loc);
                /* ds1775 (compatible, better resolution */
-               else if (device_is_compatible(dev, "ds1775"))
+               else if (of_device_is_compatible(dev, "ds1775"))
                        wf_lm75_create(adapter, addr, 1, loc);
        }
        return 0;
index eaa74afa175ba44efc29aaec393b6aadc9a59c0b..5f03aab9fb5da3451b61a4ea8738ac0e647af5f5 100644 (file)
@@ -131,7 +131,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
                 */
                if (!pmac_i2c_match_adapter(dev, adapter))
                        continue;
-               if (!device_is_compatible(dev, "max6690"))
+               if (!of_device_is_compatible(dev, "max6690"))
                        continue;
                addr = pmac_i2c_get_dev_addr(dev);
                loc = of_get_property(dev, "hwsensor-location", NULL);
index ff398adc0283b720ff0ba7265e03725a3edbd5ec..58c2590f05ecd587770127ffeb55ee37b7c55cc3 100644 (file)
@@ -263,7 +263,7 @@ static int __init smu_controls_init(void)
        /* Look for RPM fans */
        for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;)
                if (!strcmp(fans->name, "rpm-fans") ||
-                   device_is_compatible(fans, "smu-rpm-fans"))
+                   of_device_is_compatible(fans, "smu-rpm-fans"))
                        break;
        for (fan = NULL;
             fans && (fan = of_get_next_child(fans, fan)) != NULL;) {
index 9a6c2cf8fd0e6e54ffaf31bfb2847210df0a5796..1043b39aa123e716b67613229e2c34229d1c4274 100644 (file)
@@ -380,7 +380,7 @@ static int wf_sat_attach(struct i2c_adapter *adapter)
        busnode = pmac_i2c_get_bus_node(bus);
 
        while ((dev = of_get_next_child(busnode, dev)) != NULL)
-               if (device_is_compatible(dev, "smu-sat"))
+               if (of_device_is_compatible(dev, "smu-sat"))
                        wf_sat_create(adapter, dev);
        return 0;
 }
index da862e4632dd0535b1c6047c3be5377b8f1bf1f8..67b8e9453b191a2c701970f4ccbdd4a5207dd1e3 100644 (file)
@@ -47,19 +47,25 @@ static int mca_bus_match (struct device *dev, struct device_driver *drv)
 {
        struct mca_device *mca_dev = to_mca_device (dev);
        struct mca_driver *mca_drv = to_mca_driver (drv);
-       const short *mca_ids = mca_drv->id_table;
-       int i;
-
-       if (!mca_ids)
-               return 0;
-
-       for(i = 0; mca_ids[i]; i++) {
-               if (mca_ids[i] == mca_dev->pos_id) {
-                       mca_dev->index = i;
-                       return 1;
+       const unsigned short *mca_ids = mca_drv->id_table;
+       int i = 0;
+
+       if (mca_ids) {
+               for(i = 0; mca_ids[i]; i++) {
+                       if (mca_ids[i] == mca_dev->pos_id) {
+                               mca_dev->index = i;
+                               return 1;
+                       }
                }
        }
-
+       /* If the integrated id is present, treat it as though it were an
+        * additional id in the id_table (it can't be because by definition,
+        * integrated id's overflow a short */
+       if (mca_drv->integrated_id && mca_dev->pos_id ==
+           mca_drv->integrated_id) {
+               mca_dev->index = i;
+               return 1;
+       }
        return 0;
 }
 
index 2223466b3d8a5d325abbf22ea3df1a69346add9b..32cd39bcc7152b5704d5746e6501dbd44724a99b 100644 (file)
@@ -36,12 +36,25 @@ int mca_register_driver(struct mca_driver *mca_drv)
                mca_drv->driver.bus = &mca_bus_type;
                if ((r = driver_register(&mca_drv->driver)) < 0)
                        return r;
+               mca_drv->integrated_id = 0;
        }
 
        return 0;
 }
 EXPORT_SYMBOL(mca_register_driver);
 
+int mca_register_driver_integrated(struct mca_driver *mca_driver,
+                                  int integrated_id)
+{
+       int r = mca_register_driver(mca_driver);
+
+       if (!r)
+               mca_driver->integrated_id = integrated_id;
+
+       return r;
+}
+EXPORT_SYMBOL(mca_register_driver_integrated);
+
 void mca_unregister_driver(struct mca_driver *mca_drv)
 {
        if (MCA_bus)
index 4540ade6b6b584385b11d65d337680c59ae96fc1..7df934d69134436cc2e1f5affb7f681dc0ab1671 100644 (file)
@@ -262,6 +262,15 @@ config DM_MULTIPATH_EMC
        ---help---
          Multipath support for EMC CX/AX series hardware.
 
+config DM_DELAY
+       tristate "I/O delaying target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+       A target that delays reads and/or writes and can send
+       them to different devices.  Useful for testing.
+
+       If unsure, say N.
+
 endmenu
 
 endif
index 34957a68d9215ac08061706c58b0fd66dc499d9d..38754084eac741462bc677f8c6911b662c719623 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_MD_FAULTY)               += faulty.o
 obj-$(CONFIG_BLK_DEV_MD)       += md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)       += dm-mod.o
 obj-$(CONFIG_DM_CRYPT)         += dm-crypt.o
+obj-$(CONFIG_DM_DELAY)         += dm-delay.o
 obj-$(CONFIG_DM_MULTIPATH)     += dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
 obj-$(CONFIG_DM_SNAPSHOT)      += dm-snapshot.o
index e61e0efe9ec71db54a91916d978ecbda05ec1314..5a4a74c1097c6ce80eb38e726954304dbb25bc53 100644 (file)
@@ -1456,10 +1456,10 @@ int bitmap_create(mddev_t *mddev)
        bitmap->offset = mddev->bitmap_offset;
        if (file) {
                get_file(file);
-               do_sync_file_range(file, 0, LLONG_MAX,
-                                  SYNC_FILE_RANGE_WAIT_BEFORE |
-                                  SYNC_FILE_RANGE_WRITE |
-                                  SYNC_FILE_RANGE_WAIT_AFTER);
+               do_sync_mapping_range(file->f_mapping, 0, LLONG_MAX,
+                                     SYNC_FILE_RANGE_WAIT_BEFORE |
+                                     SYNC_FILE_RANGE_WRITE |
+                                     SYNC_FILE_RANGE_WAIT_AFTER);
        }
        /* read superblock from bitmap file (this sets bitmap->chunksize) */
        err = bitmap_read_sb(bitmap);
index da4349649f7f2cd5c7c6d628f40d8bf1a1463b84..c6be88826fae4d7aaea55ea0f6f8da7bf3b747ee 100644 (file)
@@ -8,17 +8,43 @@
 #define DM_BIO_LIST_H
 
 #include <linux/bio.h>
+#include <linux/prefetch.h>
 
 struct bio_list {
        struct bio *head;
        struct bio *tail;
 };
 
+static inline int bio_list_empty(const struct bio_list *bl)
+{
+       return bl->head == NULL;
+}
+
+#define BIO_LIST_INIT { .head = NULL, .tail = NULL }
+
+#define BIO_LIST(bl) \
+       struct bio_list bl = BIO_LIST_INIT
+
 static inline void bio_list_init(struct bio_list *bl)
 {
        bl->head = bl->tail = NULL;
 }
 
+#define bio_list_for_each(bio, bl) \
+       for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \
+            bio = bio->bi_next)
+
+static inline unsigned bio_list_size(const struct bio_list *bl)
+{
+       unsigned sz = 0;
+       struct bio *bio;
+
+       bio_list_for_each(bio, bl)
+               sz++;
+
+       return sz;
+}
+
 static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
 {
        bio->bi_next = NULL;
index d8121234c3471e9a4f1b609e1890f02e92970d59..7b0fcfc9eaa5fc0f724d3313360a304b6bbab3a6 100644 (file)
@@ -33,7 +33,6 @@
 struct crypt_io {
        struct dm_target *target;
        struct bio *base_bio;
-       struct bio *first_clone;
        struct work_struct work;
        atomic_t pending;
        int error;
@@ -107,6 +106,8 @@ struct crypt_config {
 
 static struct kmem_cache *_crypt_io_pool;
 
+static void clone_init(struct crypt_io *, struct bio *);
+
 /*
  * Different IV generation algorithms:
  *
@@ -120,6 +121,9 @@ static struct kmem_cache *_crypt_io_pool;
  * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
  *        (needed for LRW-32-AES and possible other narrow block modes)
  *
+ * null: the initial vector is always zero.  Provides compatibility with
+ *       obsolete loop_fish2 devices.  Do not use for new devices.
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -256,6 +260,13 @@ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
        return 0;
 }
 
+static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+       memset(iv, 0, cc->iv_size);
+
+       return 0;
+}
+
 static struct crypt_iv_operations crypt_iv_plain_ops = {
        .generator = crypt_iv_plain_gen
 };
@@ -272,6 +283,10 @@ static struct crypt_iv_operations crypt_iv_benbi_ops = {
        .generator = crypt_iv_benbi_gen
 };
 
+static struct crypt_iv_operations crypt_iv_null_ops = {
+       .generator = crypt_iv_null_gen
+};
+
 static int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                           struct scatterlist *in, unsigned int length,
@@ -378,36 +393,21 @@ static int crypt_convert(struct crypt_config *cc,
  * This should never violate the device limitations
  * May return a smaller bio when running out of pages
  */
-static struct bio *
-crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
-                   struct bio *base_bio, unsigned int *bio_vec_idx)
+static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size)
 {
+       struct crypt_config *cc = io->target->private;
        struct bio *clone;
        unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
        gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
        unsigned int i;
 
-       if (base_bio) {
-               clone = bio_alloc_bioset(GFP_NOIO, base_bio->bi_max_vecs, cc->bs);
-               __bio_clone(clone, base_bio);
-       } else
-               clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
-
+       clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
        if (!clone)
                return NULL;
 
-       clone->bi_destructor = dm_crypt_bio_destructor;
-
-       /* if the last bio was not complete, continue where that one ended */
-       clone->bi_idx = *bio_vec_idx;
-       clone->bi_vcnt = *bio_vec_idx;
-       clone->bi_size = 0;
-       clone->bi_flags &= ~(1 << BIO_SEG_VALID);
-
-       /* clone->bi_idx pages have already been allocated */
-       size -= clone->bi_idx * PAGE_SIZE;
+       clone_init(io, clone);
 
-       for (i = clone->bi_idx; i < nr_iovecs; i++) {
+       for (i = 0; i < nr_iovecs; i++) {
                struct bio_vec *bv = bio_iovec_idx(clone, i);
 
                bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask);
@@ -419,7 +419,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
                 * return a partially allocated bio, the caller will then try
                 * to allocate additional bios while submitting this partial bio
                 */
-               if ((i - clone->bi_idx) == (MIN_BIO_PAGES - 1))
+               if (i == (MIN_BIO_PAGES - 1))
                        gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
 
                bv->bv_offset = 0;
@@ -438,12 +438,6 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
                return NULL;
        }
 
-       /*
-        * Remember the last bio_vec allocated to be able
-        * to correctly continue after the splitting.
-        */
-       *bio_vec_idx = clone->bi_vcnt;
-
        return clone;
 }
 
@@ -495,9 +489,6 @@ static void dec_pending(struct crypt_io *io, int error)
        if (!atomic_dec_and_test(&io->pending))
                return;
 
-       if (io->first_clone)
-               bio_put(io->first_clone);
-
        bio_endio(io->base_bio, io->base_bio->bi_size, io->error);
 
        mempool_free(io, cc->io_pool);
@@ -562,6 +553,7 @@ static void clone_init(struct crypt_io *io, struct bio *clone)
        clone->bi_end_io  = crypt_endio;
        clone->bi_bdev    = cc->dev->bdev;
        clone->bi_rw      = io->base_bio->bi_rw;
+       clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
 static void process_read(struct crypt_io *io)
@@ -585,7 +577,6 @@ static void process_read(struct crypt_io *io)
        }
 
        clone_init(io, clone);
-       clone->bi_destructor = dm_crypt_bio_destructor;
        clone->bi_idx = 0;
        clone->bi_vcnt = bio_segments(base_bio);
        clone->bi_size = base_bio->bi_size;
@@ -604,7 +595,6 @@ static void process_write(struct crypt_io *io)
        struct convert_context ctx;
        unsigned remaining = base_bio->bi_size;
        sector_t sector = base_bio->bi_sector - io->target->begin;
-       unsigned bvec_idx = 0;
 
        atomic_inc(&io->pending);
 
@@ -615,14 +605,14 @@ static void process_write(struct crypt_io *io)
         * so repeat the whole process until all the data can be handled.
         */
        while (remaining) {
-               clone = crypt_alloc_buffer(cc, base_bio->bi_size,
-                                          io->first_clone, &bvec_idx);
+               clone = crypt_alloc_buffer(io, remaining);
                if (unlikely(!clone)) {
                        dec_pending(io, -ENOMEM);
                        return;
                }
 
                ctx.bio_out = clone;
+               ctx.idx_out = 0;
 
                if (unlikely(crypt_convert(cc, &ctx) < 0)) {
                        crypt_free_buffer_pages(cc, clone, clone->bi_size);
@@ -631,31 +621,26 @@ static void process_write(struct crypt_io *io)
                        return;
                }
 
-               clone_init(io, clone);
-               clone->bi_sector = cc->start + sector;
-
-               if (!io->first_clone) {
-                       /*
-                        * hold a reference to the first clone, because it
-                        * holds the bio_vec array and that can't be freed
-                        * before all other clones are released
-                        */
-                       bio_get(clone);
-                       io->first_clone = clone;
-               }
+               /* crypt_convert should have filled the clone bio */
+               BUG_ON(ctx.idx_out < clone->bi_vcnt);
 
+               clone->bi_sector = cc->start + sector;
                remaining -= clone->bi_size;
                sector += bio_sectors(clone);
 
-               /* prevent bio_put of first_clone */
+               /* Grab another reference to the io struct
+                * before we kick off the request */
                if (remaining)
                        atomic_inc(&io->pending);
 
                generic_make_request(clone);
 
+               /* Do not reference clone after this - it
+                * may be gone already. */
+
                /* out of memory -> run queues */
                if (remaining)
-                       congestion_wait(bio_data_dir(clone), HZ/100);
+                       congestion_wait(WRITE, HZ/100);
        }
 }
 
@@ -832,6 +817,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                cc->iv_gen_ops = &crypt_iv_essiv_ops;
        else if (strcmp(ivmode, "benbi") == 0)
                cc->iv_gen_ops = &crypt_iv_benbi_ops;
+       else if (strcmp(ivmode, "null") == 0)
+               cc->iv_gen_ops = &crypt_iv_null_ops;
        else {
                ti->error = "Invalid IV mode";
                goto bad2;
@@ -954,10 +941,12 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
        struct crypt_config *cc = ti->private;
        struct crypt_io *io;
 
+       if (bio_barrier(bio))
+               return -EOPNOTSUPP;
+
        io = mempool_alloc(cc->io_pool, GFP_NOIO);
        io->target = ti;
        io->base_bio = bio;
-       io->first_clone = NULL;
        io->error = io->post_process = 0;
        atomic_set(&io->pending, 0);
        kcryptd_queue_io(io);
@@ -1057,7 +1046,7 @@ error:
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version= {1, 3, 0},
+       .version= {1, 5, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
new file mode 100644 (file)
index 0000000..52c7cf9
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2005-2007 Red Hat GmbH
+ *
+ * A target that delays reads and/or writes and can send
+ * them to different devices.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/slab.h>
+
+#include "dm.h"
+#include "dm-bio-list.h"
+
+#define DM_MSG_PREFIX "delay"
+
+struct delay_c {
+       struct timer_list delay_timer;
+       struct semaphore timer_lock;
+       struct work_struct flush_expired_bios;
+       struct list_head delayed_bios;
+       atomic_t may_delay;
+       mempool_t *delayed_pool;
+
+       struct dm_dev *dev_read;
+       sector_t start_read;
+       unsigned read_delay;
+       unsigned reads;
+
+       struct dm_dev *dev_write;
+       sector_t start_write;
+       unsigned write_delay;
+       unsigned writes;
+};
+
+struct delay_info {
+       struct delay_c *context;
+       struct list_head list;
+       struct bio *bio;
+       unsigned long expires;
+};
+
+static DEFINE_MUTEX(delayed_bios_lock);
+
+static struct workqueue_struct *kdelayd_wq;
+static struct kmem_cache *delayed_cache;
+
+static void handle_delayed_timer(unsigned long data)
+{
+       struct delay_c *dc = (struct delay_c *)data;
+
+       queue_work(kdelayd_wq, &dc->flush_expired_bios);
+}
+
+static void queue_timeout(struct delay_c *dc, unsigned long expires)
+{
+       down(&dc->timer_lock);
+
+       if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires)
+               mod_timer(&dc->delay_timer, expires);
+
+       up(&dc->timer_lock);
+}
+
+static void flush_bios(struct bio *bio)
+{
+       struct bio *n;
+
+       while (bio) {
+               n = bio->bi_next;
+               bio->bi_next = NULL;
+               generic_make_request(bio);
+               bio = n;
+       }
+}
+
+static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all)
+{
+       struct delay_info *delayed, *next;
+       unsigned long next_expires = 0;
+       int start_timer = 0;
+       BIO_LIST(flush_bios);
+
+       mutex_lock(&delayed_bios_lock);
+       list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) {
+               if (flush_all || time_after_eq(jiffies, delayed->expires)) {
+                       list_del(&delayed->list);
+                       bio_list_add(&flush_bios, delayed->bio);
+                       if ((bio_data_dir(delayed->bio) == WRITE))
+                               delayed->context->writes--;
+                       else
+                               delayed->context->reads--;
+                       mempool_free(delayed, dc->delayed_pool);
+                       continue;
+               }
+
+               if (!start_timer) {
+                       start_timer = 1;
+                       next_expires = delayed->expires;
+               } else
+                       next_expires = min(next_expires, delayed->expires);
+       }
+
+       mutex_unlock(&delayed_bios_lock);
+
+       if (start_timer)
+               queue_timeout(dc, next_expires);
+
+       return bio_list_get(&flush_bios);
+}
+
+static void flush_expired_bios(struct work_struct *work)
+{
+       struct delay_c *dc;
+
+       dc = container_of(work, struct delay_c, flush_expired_bios);
+       flush_bios(flush_delayed_bios(dc, 0));
+}
+
+/*
+ * Mapping parameters:
+ *    <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
+ *
+ * With separate write parameters, the first set is only used for reads.
+ * Delays are specified in milliseconds.
+ */
+static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+       struct delay_c *dc;
+       unsigned long long tmpll;
+
+       if (argc != 3 && argc != 6) {
+               ti->error = "requires exactly 3 or 6 arguments";
+               return -EINVAL;
+       }
+
+       dc = kmalloc(sizeof(*dc), GFP_KERNEL);
+       if (!dc) {
+               ti->error = "Cannot allocate context";
+               return -ENOMEM;
+       }
+
+       dc->reads = dc->writes = 0;
+
+       if (sscanf(argv[1], "%llu", &tmpll) != 1) {
+               ti->error = "Invalid device sector";
+               goto bad;
+       }
+       dc->start_read = tmpll;
+
+       if (sscanf(argv[2], "%u", &dc->read_delay) != 1) {
+               ti->error = "Invalid delay";
+               goto bad;
+       }
+
+       if (dm_get_device(ti, argv[0], dc->start_read, ti->len,
+                         dm_table_get_mode(ti->table), &dc->dev_read)) {
+               ti->error = "Device lookup failed";
+               goto bad;
+       }
+
+       if (argc == 3) {
+               dc->dev_write = NULL;
+               goto out;
+       }
+
+       if (sscanf(argv[4], "%llu", &tmpll) != 1) {
+               ti->error = "Invalid write device sector";
+               goto bad;
+       }
+       dc->start_write = tmpll;
+
+       if (sscanf(argv[5], "%u", &dc->write_delay) != 1) {
+               ti->error = "Invalid write delay";
+               goto bad;
+       }
+
+       if (dm_get_device(ti, argv[3], dc->start_write, ti->len,
+                         dm_table_get_mode(ti->table), &dc->dev_write)) {
+               ti->error = "Write device lookup failed";
+               dm_put_device(ti, dc->dev_read);
+               goto bad;
+       }
+
+out:
+       dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache);
+       if (!dc->delayed_pool) {
+               DMERR("Couldn't create delayed bio pool.");
+               goto bad;
+       }
+
+       init_timer(&dc->delay_timer);
+       dc->delay_timer.function = handle_delayed_timer;
+       dc->delay_timer.data = (unsigned long)dc;
+
+       INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
+       INIT_LIST_HEAD(&dc->delayed_bios);
+       init_MUTEX(&dc->timer_lock);
+       atomic_set(&dc->may_delay, 1);
+
+       ti->private = dc;
+       return 0;
+
+bad:
+       kfree(dc);
+       return -EINVAL;
+}
+
+static void delay_dtr(struct dm_target *ti)
+{
+       struct delay_c *dc = ti->private;
+
+       flush_workqueue(kdelayd_wq);
+
+       dm_put_device(ti, dc->dev_read);
+
+       if (dc->dev_write)
+               dm_put_device(ti, dc->dev_write);
+
+       mempool_destroy(dc->delayed_pool);
+       kfree(dc);
+}
+
+static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
+{
+       struct delay_info *delayed;
+       unsigned long expires = 0;
+
+       if (!delay || !atomic_read(&dc->may_delay))
+               return 1;
+
+       delayed = mempool_alloc(dc->delayed_pool, GFP_NOIO);
+
+       delayed->context = dc;
+       delayed->bio = bio;
+       delayed->expires = expires = jiffies + (delay * HZ / 1000);
+
+       mutex_lock(&delayed_bios_lock);
+
+       if (bio_data_dir(bio) == WRITE)
+               dc->writes++;
+       else
+               dc->reads++;
+
+       list_add_tail(&delayed->list, &dc->delayed_bios);
+
+       mutex_unlock(&delayed_bios_lock);
+
+       queue_timeout(dc, expires);
+
+       return 0;
+}
+
+static void delay_presuspend(struct dm_target *ti)
+{
+       struct delay_c *dc = ti->private;
+
+       atomic_set(&dc->may_delay, 0);
+       del_timer_sync(&dc->delay_timer);
+       flush_bios(flush_delayed_bios(dc, 1));
+}
+
+static void delay_resume(struct dm_target *ti)
+{
+       struct delay_c *dc = ti->private;
+
+       atomic_set(&dc->may_delay, 1);
+}
+
+static int delay_map(struct dm_target *ti, struct bio *bio,
+                    union map_info *map_context)
+{
+       struct delay_c *dc = ti->private;
+
+       if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) {
+               bio->bi_bdev = dc->dev_write->bdev;
+               bio->bi_sector = dc->start_write +
+                                (bio->bi_sector - ti->begin);
+
+               return delay_bio(dc, dc->write_delay, bio);
+       }
+
+       bio->bi_bdev = dc->dev_read->bdev;
+       bio->bi_sector = dc->start_read +
+                        (bio->bi_sector - ti->begin);
+
+       return delay_bio(dc, dc->read_delay, bio);
+}
+
+static int delay_status(struct dm_target *ti, status_type_t type,
+                       char *result, unsigned maxlen)
+{
+       struct delay_c *dc = ti->private;
+       int sz = 0;
+
+       switch (type) {
+       case STATUSTYPE_INFO:
+               DMEMIT("%u %u", dc->reads, dc->writes);
+               break;
+
+       case STATUSTYPE_TABLE:
+               DMEMIT("%s %llu %u", dc->dev_read->name,
+                      (unsigned long long) dc->start_read,
+                      dc->read_delay);
+               if (dc->dev_write)
+                       DMEMIT("%s %llu %u", dc->dev_write->name,
+                              (unsigned long long) dc->start_write,
+                              dc->write_delay);
+               break;
+       }
+
+       return 0;
+}
+
+static struct target_type delay_target = {
+       .name        = "delay",
+       .version     = {1, 0, 2},
+       .module      = THIS_MODULE,
+       .ctr         = delay_ctr,
+       .dtr         = delay_dtr,
+       .map         = delay_map,
+       .presuspend  = delay_presuspend,
+       .resume      = delay_resume,
+       .status      = delay_status,
+};
+
+static int __init dm_delay_init(void)
+{
+       int r = -ENOMEM;
+
+       kdelayd_wq = create_workqueue("kdelayd");
+       if (!kdelayd_wq) {
+               DMERR("Couldn't start kdelayd");
+               goto bad_queue;
+       }
+
+       delayed_cache = kmem_cache_create("dm-delay",
+                                         sizeof(struct delay_info),
+                                         __alignof__(struct delay_info),
+                                         0, NULL, NULL);
+       if (!delayed_cache) {
+               DMERR("Couldn't create delayed bio cache.");
+               goto bad_memcache;
+       }
+
+       r = dm_register_target(&delay_target);
+       if (r < 0) {
+               DMERR("register failed %d", r);
+               goto bad_register;
+       }
+
+       return 0;
+
+bad_register:
+       kmem_cache_destroy(delayed_cache);
+bad_memcache:
+       destroy_workqueue(kdelayd_wq);
+bad_queue:
+       return r;
+}
+
+static void __exit dm_delay_exit(void)
+{
+       int r = dm_unregister_target(&delay_target);
+
+       if (r < 0)
+               DMERR("unregister failed %d", r);
+
+       kmem_cache_destroy(delayed_cache);
+       destroy_workqueue(kdelayd_wq);
+}
+
+/* Module hooks */
+module_init(dm_delay_init);
+module_exit(dm_delay_exit);
+
+MODULE_DESCRIPTION(DM_NAME " delay target");
+MODULE_AUTHOR("Heinz Mauelshagen <mauelshagen@redhat.com>");
+MODULE_LICENSE("GPL");
index 99cdffa7fbfe0a4522330099dd80ca810f3dc796..07e0a0c84f6ef9f8d93da5b914f22dfc0f9c47fc 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * dm-snapshot.c
+ * dm-exception-store.c
  *
  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006 Red Hat GmbH
  *
  * This file is released under the GPL.
  */
@@ -123,6 +124,7 @@ struct pstore {
        atomic_t pending_count;
        uint32_t callback_count;
        struct commit_callback *callbacks;
+       struct dm_io_client *io_client;
 };
 
 static inline unsigned int sectors_to_pages(unsigned int sectors)
@@ -159,14 +161,20 @@ static void free_area(struct pstore *ps)
  */
 static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
 {
-       struct io_region where;
-       unsigned long bits;
-
-       where.bdev = ps->snap->cow->bdev;
-       where.sector = ps->snap->chunk_size * chunk;
-       where.count = ps->snap->chunk_size;
-
-       return dm_io_sync_vm(1, &where, rw, ps->area, &bits);
+       struct io_region where = {
+               .bdev = ps->snap->cow->bdev,
+               .sector = ps->snap->chunk_size * chunk,
+               .count = ps->snap->chunk_size,
+       };
+       struct dm_io_request io_req = {
+               .bi_rw = rw,
+               .mem.type = DM_IO_VMA,
+               .mem.ptr.vma = ps->area,
+               .client = ps->io_client,
+               .notify.fn = NULL,
+       };
+
+       return dm_io(&io_req, 1, &where, NULL);
 }
 
 /*
@@ -213,17 +221,18 @@ static int read_header(struct pstore *ps, int *new_snapshot)
                chunk_size_supplied = 0;
        }
 
-       r = dm_io_get(sectors_to_pages(ps->snap->chunk_size));
-       if (r)
-               return r;
+       ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
+                                                            chunk_size));
+       if (IS_ERR(ps->io_client))
+               return PTR_ERR(ps->io_client);
 
        r = alloc_area(ps);
        if (r)
-               goto bad1;
+               return r;
 
        r = chunk_io(ps, 0, READ);
        if (r)
-               goto bad2;
+               goto bad;
 
        dh = (struct disk_header *) ps->area;
 
@@ -235,7 +244,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
                DMWARN("Invalid or corrupt snapshot");
                r = -ENXIO;
-               goto bad2;
+               goto bad;
        }
 
        *new_snapshot = 0;
@@ -252,27 +261,22 @@ static int read_header(struct pstore *ps, int *new_snapshot)
               (unsigned long long)ps->snap->chunk_size);
 
        /* We had a bogus chunk_size. Fix stuff up. */
-       dm_io_put(sectors_to_pages(ps->snap->chunk_size));
        free_area(ps);
 
        ps->snap->chunk_size = chunk_size;
        ps->snap->chunk_mask = chunk_size - 1;
        ps->snap->chunk_shift = ffs(chunk_size) - 1;
 
-       r = dm_io_get(sectors_to_pages(chunk_size));
+       r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
+                               ps->io_client);
        if (r)
                return r;
 
        r = alloc_area(ps);
-       if (r)
-               goto bad1;
-
-       return 0;
+       return r;
 
-bad2:
+bad:
        free_area(ps);
-bad1:
-       dm_io_put(sectors_to_pages(ps->snap->chunk_size));
        return r;
 }
 
@@ -405,7 +409,7 @@ static void persistent_destroy(struct exception_store *store)
 {
        struct pstore *ps = get_info(store);
 
-       dm_io_put(sectors_to_pages(ps->snap->chunk_size));
+       dm_io_client_destroy(ps->io_client);
        vfree(ps->callbacks);
        free_area(ps);
        kfree(ps);
index 32eff28e4adc889f339ae7e75345c2aea42af5cf..e0832e6fcf36c0747c06ae3035c12567e80df797 100644 (file)
@@ -16,6 +16,7 @@
 struct hw_handler_type;
 struct hw_handler {
        struct hw_handler_type *type;
+       struct mapped_device *md;
        void *context;
 };
 
index 8bdc8a87b249c4b9a0b46ab0e22308e30ed7c1d6..352c6fbeac53a19dd82f8ef6994b733da4ad931d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Sistina Software
+ * Copyright (C) 2006 Red Hat GmbH
  *
  * This file is released under the GPL.
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-static struct bio_set *_bios;
+struct dm_io_client {
+       mempool_t *pool;
+       struct bio_set *bios;
+};
 
 /* FIXME: can we shrink this ? */
 struct io {
        unsigned long error;
        atomic_t count;
        struct task_struct *sleeper;
+       struct dm_io_client *client;
        io_notify_fn callback;
        void *context;
 };
@@ -26,63 +31,58 @@ struct io {
 /*
  * io contexts are only dynamically allocated for asynchronous
  * io.  Since async io is likely to be the majority of io we'll
- * have the same number of io contexts as buffer heads ! (FIXME:
- * must reduce this).
+ * have the same number of io contexts as bios! (FIXME: must reduce this).
  */
-static unsigned _num_ios;
-static mempool_t *_io_pool;
 
 static unsigned int pages_to_ios(unsigned int pages)
 {
        return 4 * pages;       /* too many ? */
 }
 
-static int resize_pool(unsigned int new_ios)
+/*
+ * Create a client with mempool and bioset.
+ */
+struct dm_io_client *dm_io_client_create(unsigned num_pages)
 {
-       int r = 0;
-
-       if (_io_pool) {
-               if (new_ios == 0) {
-                       /* free off the pool */
-                       mempool_destroy(_io_pool);
-                       _io_pool = NULL;
-                       bioset_free(_bios);
-
-               } else {
-                       /* resize the pool */
-                       r = mempool_resize(_io_pool, new_ios, GFP_KERNEL);
-               }
+       unsigned ios = pages_to_ios(num_pages);
+       struct dm_io_client *client;
 
-       } else {
-               /* create new pool */
-               _io_pool = mempool_create_kmalloc_pool(new_ios,
-                                                      sizeof(struct io));
-               if (!_io_pool)
-                       return -ENOMEM;
-
-               _bios = bioset_create(16, 16);
-               if (!_bios) {
-                       mempool_destroy(_io_pool);
-                       _io_pool = NULL;
-                       return -ENOMEM;
-               }
-       }
+       client = kmalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return ERR_PTR(-ENOMEM);
+
+       client->pool = mempool_create_kmalloc_pool(ios, sizeof(struct io));
+       if (!client->pool)
+               goto bad;
 
-       if (!r)
-               _num_ios = new_ios;
+       client->bios = bioset_create(16, 16);
+       if (!client->bios)
+               goto bad;
 
-       return r;
+       return client;
+
+   bad:
+       if (client->pool)
+               mempool_destroy(client->pool);
+       kfree(client);
+       return ERR_PTR(-ENOMEM);
 }
+EXPORT_SYMBOL(dm_io_client_create);
 
-int dm_io_get(unsigned int num_pages)
+int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client)
 {
-       return resize_pool(_num_ios + pages_to_ios(num_pages));
+       return mempool_resize(client->pool, pages_to_ios(num_pages),
+                             GFP_KERNEL);
 }
+EXPORT_SYMBOL(dm_io_client_resize);
 
-void dm_io_put(unsigned int num_pages)
+void dm_io_client_destroy(struct dm_io_client *client)
 {
-       resize_pool(_num_ios - pages_to_ios(num_pages));
+       mempool_destroy(client->pool);
+       bioset_free(client->bios);
+       kfree(client);
 }
+EXPORT_SYMBOL(dm_io_client_destroy);
 
 /*-----------------------------------------------------------------
  * We need to keep track of which region a bio is doing io for.
@@ -118,7 +118,7 @@ static void dec_count(struct io *io, unsigned int region, int error)
                        io_notify_fn fn = io->callback;
                        void *context = io->context;
 
-                       mempool_free(io, _io_pool);
+                       mempool_free(io, io->client->pool);
                        fn(r, context);
                }
        }
@@ -126,7 +126,8 @@ static void dec_count(struct io *io, unsigned int region, int error)
 
 static int endio(struct bio *bio, unsigned int done, int error)
 {
-       struct io *io = (struct io *) bio->bi_private;
+       struct io *io;
+       unsigned region;
 
        /* keep going until we've finished */
        if (bio->bi_size)
@@ -135,10 +136,17 @@ static int endio(struct bio *bio, unsigned int done, int error)
        if (error && bio_data_dir(bio) == READ)
                zero_fill_bio(bio);
 
-       dec_count(io, bio_get_region(bio), error);
+       /*
+        * The bio destructor in bio_put() may use the io object.
+        */
+       io = bio->bi_private;
+       region = bio_get_region(bio);
+
        bio->bi_max_vecs++;
        bio_put(bio);
 
+       dec_count(io, region, error);
+
        return 0;
 }
 
@@ -209,6 +217,9 @@ static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec)
        dp->context_ptr = bvec;
 }
 
+/*
+ * Functions for getting the pages from a VMA.
+ */
 static void vm_get_page(struct dpages *dp,
                 struct page **p, unsigned long *len, unsigned *offset)
 {
@@ -233,7 +244,34 @@ static void vm_dp_init(struct dpages *dp, void *data)
 
 static void dm_bio_destructor(struct bio *bio)
 {
-       bio_free(bio, _bios);
+       struct io *io = bio->bi_private;
+
+       bio_free(bio, io->client->bios);
+}
+
+/*
+ * Functions for getting the pages from kernel memory.
+ */
+static void km_get_page(struct dpages *dp, struct page **p, unsigned long *len,
+                       unsigned *offset)
+{
+       *p = virt_to_page(dp->context_ptr);
+       *offset = dp->context_u;
+       *len = PAGE_SIZE - dp->context_u;
+}
+
+static void km_next_page(struct dpages *dp)
+{
+       dp->context_ptr += PAGE_SIZE - dp->context_u;
+       dp->context_u = 0;
+}
+
+static void km_dp_init(struct dpages *dp, void *data)
+{
+       dp->get_page = km_get_page;
+       dp->next_page = km_next_page;
+       dp->context_u = ((unsigned long) data) & (PAGE_SIZE - 1);
+       dp->context_ptr = data;
 }
 
 /*-----------------------------------------------------------------
@@ -256,7 +294,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
                 * to hide it from bio_add_page().
                 */
                num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
-               bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios);
+               bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
                bio->bi_sector = where->sector + (where->count - remaining);
                bio->bi_bdev = where->bdev;
                bio->bi_end_io = endio;
@@ -311,8 +349,9 @@ static void dispatch_io(int rw, unsigned int num_regions,
        dec_count(io, 0, 0);
 }
 
-static int sync_io(unsigned int num_regions, struct io_region *where,
-           int rw, struct dpages *dp, unsigned long *error_bits)
+static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+                  struct io_region *where, int rw, struct dpages *dp,
+                  unsigned long *error_bits)
 {
        struct io io;
 
@@ -324,6 +363,7 @@ static int sync_io(unsigned int num_regions, struct io_region *where,
        io.error = 0;
        atomic_set(&io.count, 1); /* see dispatch_io() */
        io.sleeper = current;
+       io.client = client;
 
        dispatch_io(rw, num_regions, where, dp, &io, 1);
 
@@ -340,12 +380,15 @@ static int sync_io(unsigned int num_regions, struct io_region *where,
        if (atomic_read(&io.count))
                return -EINTR;
 
-       *error_bits = io.error;
+       if (error_bits)
+               *error_bits = io.error;
+
        return io.error ? -EIO : 0;
 }
 
-static int async_io(unsigned int num_regions, struct io_region *where, int rw,
-            struct dpages *dp, io_notify_fn fn, void *context)
+static int async_io(struct dm_io_client *client, unsigned int num_regions,
+                   struct io_region *where, int rw, struct dpages *dp,
+                   io_notify_fn fn, void *context)
 {
        struct io *io;
 
@@ -355,10 +398,11 @@ static int async_io(unsigned int num_regions, struct io_region *where, int rw,
                return -EIO;
        }
 
-       io = mempool_alloc(_io_pool, GFP_NOIO);
+       io = mempool_alloc(client->pool, GFP_NOIO);
        io->error = 0;
        atomic_set(&io->count, 1); /* see dispatch_io() */
        io->sleeper = NULL;
+       io->client = client;
        io->callback = fn;
        io->context = context;
 
@@ -366,61 +410,51 @@ static int async_io(unsigned int num_regions, struct io_region *where, int rw,
        return 0;
 }
 
-int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
-              struct page_list *pl, unsigned int offset,
-              unsigned long *error_bits)
+static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
 {
-       struct dpages dp;
-       list_dp_init(&dp, pl, offset);
-       return sync_io(num_regions, where, rw, &dp, error_bits);
-}
+       /* Set up dpages based on memory type */
+       switch (io_req->mem.type) {
+       case DM_IO_PAGE_LIST:
+               list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset);
+               break;
+
+       case DM_IO_BVEC:
+               bvec_dp_init(dp, io_req->mem.ptr.bvec);
+               break;
+
+       case DM_IO_VMA:
+               vm_dp_init(dp, io_req->mem.ptr.vma);
+               break;
+
+       case DM_IO_KMEM:
+               km_dp_init(dp, io_req->mem.ptr.addr);
+               break;
+
+       default:
+               return -EINVAL;
+       }
 
-int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw,
-                   struct bio_vec *bvec, unsigned long *error_bits)
-{
-       struct dpages dp;
-       bvec_dp_init(&dp, bvec);
-       return sync_io(num_regions, where, rw, &dp, error_bits);
+       return 0;
 }
 
-int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
-                 void *data, unsigned long *error_bits)
+/*
+ * New collapsed (a)synchronous interface
+ */
+int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+         struct io_region *where, unsigned long *sync_error_bits)
 {
+       int r;
        struct dpages dp;
-       vm_dp_init(&dp, data);
-       return sync_io(num_regions, where, rw, &dp, error_bits);
-}
 
-int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
-               struct page_list *pl, unsigned int offset,
-               io_notify_fn fn, void *context)
-{
-       struct dpages dp;
-       list_dp_init(&dp, pl, offset);
-       return async_io(num_regions, where, rw, &dp, fn, context);
-}
+       r = dp_init(io_req, &dp);
+       if (r)
+               return r;
 
-int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw,
-                    struct bio_vec *bvec, io_notify_fn fn, void *context)
-{
-       struct dpages dp;
-       bvec_dp_init(&dp, bvec);
-       return async_io(num_regions, where, rw, &dp, fn, context);
-}
+       if (!io_req->notify.fn)
+               return sync_io(io_req->client, num_regions, where,
+                              io_req->bi_rw, &dp, sync_error_bits);
 
-int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
-                  void *data, io_notify_fn fn, void *context)
-{
-       struct dpages dp;
-       vm_dp_init(&dp, data);
-       return async_io(num_regions, where, rw, &dp, fn, context);
+       return async_io(io_req->client, num_regions, where, io_req->bi_rw,
+                       &dp, io_req->notify.fn, io_req->notify.context);
 }
-
-EXPORT_SYMBOL(dm_io_get);
-EXPORT_SYMBOL(dm_io_put);
-EXPORT_SYMBOL(dm_io_sync);
-EXPORT_SYMBOL(dm_io_async);
-EXPORT_SYMBOL(dm_io_sync_bvec);
-EXPORT_SYMBOL(dm_io_async_bvec);
-EXPORT_SYMBOL(dm_io_sync_vm);
-EXPORT_SYMBOL(dm_io_async_vm);
+EXPORT_SYMBOL(dm_io);
index f9035bfd1a9f73aa8f8854a6c24c76a9790e7eef..f647e2cceaa673f8098fce058832a3cc55ce23c4 100644 (file)
@@ -12,7 +12,7 @@
 struct io_region {
        struct block_device *bdev;
        sector_t sector;
-       sector_t count;
+       sector_t count;         /* If this is zero the region is ignored. */
 };
 
 struct page_list {
@@ -20,55 +20,60 @@ struct page_list {
        struct page *page;
 };
 
-
-/*
- * 'error' is a bitset, with each bit indicating whether an error
- * occurred doing io to the corresponding region.
- */
 typedef void (*io_notify_fn)(unsigned long error, void *context);
 
+enum dm_io_mem_type {
+       DM_IO_PAGE_LIST,/* Page list */
+       DM_IO_BVEC,     /* Bio vector */
+       DM_IO_VMA,      /* Virtual memory area */
+       DM_IO_KMEM,     /* Kernel memory */
+};
+
+struct dm_io_memory {
+       enum dm_io_mem_type type;
+
+       union {
+               struct page_list *pl;
+               struct bio_vec *bvec;
+               void *vma;
+               void *addr;
+       } ptr;
+
+       unsigned offset;
+};
+
+struct dm_io_notify {
+       io_notify_fn fn;        /* Callback for asynchronous requests */
+       void *context;          /* Passed to callback */
+};
 
 /*
- * Before anyone uses the IO interface they should call
- * dm_io_get(), specifying roughly how many pages they are
- * expecting to perform io on concurrently.
- *
- * This function may block.
+ * IO request structure
  */
-int dm_io_get(unsigned int num_pages);
-void dm_io_put(unsigned int num_pages);
+struct dm_io_client;
+struct dm_io_request {
+       int bi_rw;                      /* READ|WRITE - not READA */
+       struct dm_io_memory mem;        /* Memory to use for io */
+       struct dm_io_notify notify;     /* Synchronous if notify.fn is NULL */
+       struct dm_io_client *client;    /* Client memory handler */
+};
 
 /*
- * Synchronous IO.
+ * For async io calls, users can alternatively use the dm_io() function below
+ * and dm_io_client_create() to create private mempools for the client.
  *
- * Please ensure that the rw flag in the next two functions is
- * either READ or WRITE, ie. we don't take READA.  Any
- * regions with a zero count field will be ignored.
+ * Create/destroy may block.
  */
-int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
-              struct page_list *pl, unsigned int offset,
-              unsigned long *error_bits);
-
-int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw,
-                   struct bio_vec *bvec, unsigned long *error_bits);
-
-int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
-                 void *data, unsigned long *error_bits);
+struct dm_io_client *dm_io_client_create(unsigned num_pages);
+int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
+void dm_io_client_destroy(struct dm_io_client *client);
 
 /*
- * Aynchronous IO.
- *
- * The 'where' array may be safely allocated on the stack since
- * the function takes a copy.
+ * IO interface using private per-client pools.
+ * Each bit in the optional 'sync_error_bits' bitset indicates whether an
+ * error occurred doing io to the corresponding region.
  */
-int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
-               struct page_list *pl, unsigned int offset,
-               io_notify_fn fn, void *context);
-
-int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw,
-                    struct bio_vec *bvec, io_notify_fn fn, void *context);
-
-int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
-                  void *data, io_notify_fn fn, void *context);
+int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+         struct io_region *region, unsigned long *sync_error_bits);
 
 #endif
index 6a9261351848ba7e3272de48a51d100345a45a7f..a66428d860fef830d3fddc6d8f48140d7a646a4b 100644 (file)
@@ -149,9 +149,12 @@ struct log_c {
                FORCESYNC,      /* Force a sync to happen */
        } sync;
 
+       struct dm_io_request io_req;
+
        /*
         * Disk log fields
         */
+       int log_dev_failed;
        struct dm_dev *log_dev;
        struct log_header header;
 
@@ -199,13 +202,20 @@ static void header_from_disk(struct log_header *core, struct log_header *disk)
        core->nr_regions = le64_to_cpu(disk->nr_regions);
 }
 
+static int rw_header(struct log_c *lc, int rw)
+{
+       lc->io_req.bi_rw = rw;
+       lc->io_req.mem.ptr.vma = lc->disk_header;
+       lc->io_req.notify.fn = NULL;
+
+       return dm_io(&lc->io_req, 1, &lc->header_location, NULL);
+}
+
 static int read_header(struct log_c *log)
 {
        int r;
-       unsigned long ebits;
 
-       r = dm_io_sync_vm(1, &log->header_location, READ,
-                         log->disk_header, &ebits);
+       r = rw_header(log, READ);
        if (r)
                return r;
 
@@ -233,11 +243,8 @@ static int read_header(struct log_c *log)
 
 static inline int write_header(struct log_c *log)
 {
-       unsigned long ebits;
-
        header_to_disk(&log->header, log->disk_header);
-       return dm_io_sync_vm(1, &log->header_location, WRITE,
-                            log->disk_header, &ebits);
+       return rw_header(log, WRITE);
 }
 
 /*----------------------------------------------------------------
@@ -256,6 +263,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
        uint32_t region_size;
        unsigned int region_count;
        size_t bitset_size, buf_size;
+       int r;
 
        if (argc < 1 || argc > 2) {
                DMWARN("wrong number of arguments to mirror log");
@@ -315,6 +323,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
                lc->disk_header = NULL;
        } else {
                lc->log_dev = dev;
+               lc->log_dev_failed = 0;
                lc->header_location.bdev = lc->log_dev->bdev;
                lc->header_location.sector = 0;
 
@@ -324,6 +333,15 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
                buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
                                       bitset_size, ti->limits.hardsect_size);
                lc->header_location.count = buf_size >> SECTOR_SHIFT;
+               lc->io_req.mem.type = DM_IO_VMA;
+               lc->io_req.client = dm_io_client_create(dm_div_up(buf_size,
+                                                                  PAGE_SIZE));
+               if (IS_ERR(lc->io_req.client)) {
+                       r = PTR_ERR(lc->io_req.client);
+                       DMWARN("couldn't allocate disk io client");
+                       kfree(lc);
+                       return -ENOMEM;
+               }
 
                lc->disk_header = vmalloc(buf_size);
                if (!lc->disk_header) {
@@ -424,6 +442,7 @@ static void disk_dtr(struct dirty_log *log)
 
        dm_put_device(lc->ti, lc->log_dev);
        vfree(lc->disk_header);
+       dm_io_client_destroy(lc->io_req.client);
        destroy_log_context(lc);
 }
 
@@ -437,6 +456,15 @@ static int count_bits32(uint32_t *addr, unsigned size)
        return count;
 }
 
+static void fail_log_device(struct log_c *lc)
+{
+       if (lc->log_dev_failed)
+               return;
+
+       lc->log_dev_failed = 1;
+       dm_table_event(lc->ti->table);
+}
+
 static int disk_resume(struct dirty_log *log)
 {
        int r;
@@ -446,8 +474,19 @@ static int disk_resume(struct dirty_log *log)
 
        /* read the disk header */
        r = read_header(lc);
-       if (r)
-               return r;
+       if (r) {
+               DMWARN("%s: Failed to read header on mirror log device",
+                      lc->log_dev->name);
+               fail_log_device(lc);
+               /*
+                * If the log device cannot be read, we must assume
+                * all regions are out-of-sync.  If we simply return
+                * here, the state will be uninitialized and could
+                * lead us to return 'in-sync' status for regions
+                * that are actually 'out-of-sync'.
+                */
+               lc->header.nr_regions = 0;
+       }
 
        /* set or clear any new bits -- device has grown */
        if (lc->sync == NOSYNC)
@@ -472,7 +511,14 @@ static int disk_resume(struct dirty_log *log)
        lc->header.nr_regions = lc->region_count;
 
        /* write the new header */
-       return write_header(lc);
+       r = write_header(lc);
+       if (r) {
+               DMWARN("%s: Failed to write header on mirror log device",
+                      lc->log_dev->name);
+               fail_log_device(lc);
+       }
+
+       return r;
 }
 
 static uint32_t core_get_region_size(struct dirty_log *log)
@@ -516,7 +562,9 @@ static int disk_flush(struct dirty_log *log)
                return 0;
 
        r = write_header(lc);
-       if (!r)
+       if (r)
+               fail_log_device(lc);
+       else
                lc->touched = 0;
 
        return r;
@@ -591,6 +639,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
 
        switch(status) {
        case STATUSTYPE_INFO:
+               DMEMIT("1 %s", log->type->name);
                break;
 
        case STATUSTYPE_TABLE:
@@ -606,17 +655,17 @@ static int disk_status(struct dirty_log *log, status_type_t status,
                       char *result, unsigned int maxlen)
 {
        int sz = 0;
-       char buffer[16];
        struct log_c *lc = log->context;
 
        switch(status) {
        case STATUSTYPE_INFO:
+               DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name,
+                      lc->log_dev_failed ? 'D' : 'A');
                break;
 
        case STATUSTYPE_TABLE:
-               format_dev_t(buffer, lc->log_dev->bdev->bd_dev);
                DMEMIT("%s %u %s %u ", log->type->name,
-                      lc->sync == DEFAULTSYNC ? 2 : 3, buffer,
+                      lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name,
                       lc->region_size);
                DMEMIT_SYNC;
        }
index 3aa0135069672d8fe7f3ed4c6e743d969478c95f..de54b39e6ffe9fb78cbad18c2a5d5b559d54d870 100644 (file)
@@ -668,6 +668,9 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m)
                return -EINVAL;
        }
 
+       m->hw_handler.md = dm_table_get_md(ti->table);
+       dm_put(m->hw_handler.md);
+
        r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);
        if (r) {
                dm_put_hw_handler(hwht);
index 23a642619bedfbbe76137f2d1e8d174782622f4e..ef124b71ccc8f1dfd9aa0fdfad0fad81010b0613 100644 (file)
 #include <linux/workqueue.h>
 
 #define DM_MSG_PREFIX "raid1"
+#define DM_IO_PAGES 64
 
-static struct workqueue_struct *_kmirrord_wq;
-static struct work_struct _kmirrord_work;
-static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
+#define DM_RAID1_HANDLE_ERRORS 0x01
 
-static inline void wake(void)
-{
-       queue_work(_kmirrord_wq, &_kmirrord_work);
-}
+static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
 
 /*-----------------------------------------------------------------
  * Region hash
@@ -125,17 +121,23 @@ struct mirror_set {
        struct list_head list;
        struct region_hash rh;
        struct kcopyd_client *kcopyd_client;
+       uint64_t features;
 
        spinlock_t lock;        /* protects the next two lists */
        struct bio_list reads;
        struct bio_list writes;
 
+       struct dm_io_client *io_client;
+
        /* recovery */
        region_t nr_regions;
        int in_sync;
 
        struct mirror *default_mirror;  /* Default mirror */
 
+       struct workqueue_struct *kmirrord_wq;
+       struct work_struct kmirrord_work;
+
        unsigned int nr_mirrors;
        struct mirror mirror[0];
 };
@@ -153,6 +155,11 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
        return region << rh->region_shift;
 }
 
+static void wake(struct mirror_set *ms)
+{
+       queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
+}
+
 /* FIXME move this */
 static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
 
@@ -398,8 +405,7 @@ static void rh_update_states(struct region_hash *rh)
                mempool_free(reg, rh->region_pool);
        }
 
-       if (!list_empty(&recovered))
-               rh->log->type->flush(rh->log);
+       rh->log->type->flush(rh->log);
 
        list_for_each_entry_safe (reg, next, &clean, list)
                mempool_free(reg, rh->region_pool);
@@ -471,7 +477,7 @@ static void rh_dec(struct region_hash *rh, region_t region)
        spin_unlock_irqrestore(&rh->region_lock, flags);
 
        if (should_wake)
-               wake();
+               wake(rh->ms);
 }
 
 /*
@@ -558,7 +564,7 @@ static void rh_recovery_end(struct region *reg, int success)
        list_add(&reg->list, &reg->rh->recovered_regions);
        spin_unlock_irq(&rh->region_lock);
 
-       wake();
+       wake(rh->ms);
 }
 
 static void rh_flush(struct region_hash *rh)
@@ -592,7 +598,7 @@ static void rh_start_recovery(struct region_hash *rh)
        for (i = 0; i < MAX_RECOVERY; i++)
                up(&rh->recovery_count);
 
-       wake();
+       wake(rh->ms);
 }
 
 /*
@@ -735,7 +741,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
                /*
                 * We can only read balance if the region is in sync.
                 */
-               if (rh_in_sync(&ms->rh, region, 0))
+               if (rh_in_sync(&ms->rh, region, 1))
                        m = choose_mirror(ms, bio->bi_sector);
                else
                        m = ms->default_mirror;
@@ -792,6 +798,14 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
        unsigned int i;
        struct io_region io[KCOPYD_MAX_REGIONS+1];
        struct mirror *m;
+       struct dm_io_request io_req = {
+               .bi_rw = WRITE,
+               .mem.type = DM_IO_BVEC,
+               .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
+               .notify.fn = write_callback,
+               .notify.context = bio,
+               .client = ms->io_client,
+       };
 
        for (i = 0; i < ms->nr_mirrors; i++) {
                m = ms->mirror + i;
@@ -802,9 +816,8 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
        }
 
        bio_set_ms(bio, ms);
-       dm_io_async_bvec(ms->nr_mirrors, io, WRITE,
-                        bio->bi_io_vec + bio->bi_idx,
-                        write_callback, bio);
+
+       (void) dm_io(&io_req, ms->nr_mirrors, io, NULL);
 }
 
 static void do_writes(struct mirror_set *ms, struct bio_list *writes)
@@ -870,11 +883,10 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
 /*-----------------------------------------------------------------
  * kmirrord
  *---------------------------------------------------------------*/
-static LIST_HEAD(_mirror_sets);
-static DECLARE_RWSEM(_mirror_sets_lock);
-
-static void do_mirror(struct mirror_set *ms)
+static void do_mirror(struct work_struct *work)
 {
+       struct mirror_set *ms =container_of(work, struct mirror_set,
+                                           kmirrord_work);
        struct bio_list reads, writes;
 
        spin_lock(&ms->lock);
@@ -890,16 +902,6 @@ static void do_mirror(struct mirror_set *ms)
        do_writes(ms, &writes);
 }
 
-static void do_work(struct work_struct *ignored)
-{
-       struct mirror_set *ms;
-
-       down_read(&_mirror_sets_lock);
-       list_for_each_entry (ms, &_mirror_sets, list)
-               do_mirror(ms);
-       up_read(&_mirror_sets_lock);
-}
-
 /*-----------------------------------------------------------------
  * Target functions
  *---------------------------------------------------------------*/
@@ -931,6 +933,13 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
        ms->in_sync = 0;
        ms->default_mirror = &ms->mirror[DEFAULT_MIRROR];
 
+       ms->io_client = dm_io_client_create(DM_IO_PAGES);
+       if (IS_ERR(ms->io_client)) {
+               ti->error = "Error creating dm_io client";
+               kfree(ms);
+               return NULL;
+       }
+
        if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
                ti->error = "Error creating dirty region hash";
                kfree(ms);
@@ -946,6 +955,7 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
        while (m--)
                dm_put_device(ti, ms->mirror[m].dev);
 
+       dm_io_client_destroy(ms->io_client);
        rh_exit(&ms->rh);
        kfree(ms);
 }
@@ -978,23 +988,6 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
        return 0;
 }
 
-static int add_mirror_set(struct mirror_set *ms)
-{
-       down_write(&_mirror_sets_lock);
-       list_add_tail(&ms->list, &_mirror_sets);
-       up_write(&_mirror_sets_lock);
-       wake();
-
-       return 0;
-}
-
-static void del_mirror_set(struct mirror_set *ms)
-{
-       down_write(&_mirror_sets_lock);
-       list_del(&ms->list);
-       up_write(&_mirror_sets_lock);
-}
-
 /*
  * Create dirty log: log_type #log_params <log_params>
  */
@@ -1037,16 +1030,55 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
        return dl;
 }
 
+static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
+                         unsigned *args_used)
+{
+       unsigned num_features;
+       struct dm_target *ti = ms->ti;
+
+       *args_used = 0;
+
+       if (!argc)
+               return 0;
+
+       if (sscanf(argv[0], "%u", &num_features) != 1) {
+               ti->error = "Invalid number of features";
+               return -EINVAL;
+       }
+
+       argc--;
+       argv++;
+       (*args_used)++;
+
+       if (num_features > argc) {
+               ti->error = "Not enough arguments to support feature count";
+               return -EINVAL;
+       }
+
+       if (!strcmp("handle_errors", argv[0]))
+               ms->features |= DM_RAID1_HANDLE_ERRORS;
+       else {
+               ti->error = "Unrecognised feature requested";
+               return -EINVAL;
+       }
+
+       (*args_used)++;
+
+       return 0;
+}
+
 /*
  * Construct a mirror mapping:
  *
  * log_type #log_params <log_params>
  * #mirrors [mirror_path offset]{2,}
+ * [#features <features>]
  *
  * log_type is "core" or "disk"
  * #log_params is between 1 and 3
+ *
+ * If present, features must be "handle_errors".
  */
-#define DM_IO_PAGES 64
 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        int r;
@@ -1070,8 +1102,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        argv++, argc--;
 
-       if (argc != nr_mirrors * 2) {
-               ti->error = "Wrong number of mirror arguments";
+       if (argc < nr_mirrors * 2) {
+               ti->error = "Too few mirror arguments";
                dm_destroy_dirty_log(dl);
                return -EINVAL;
        }
@@ -1096,13 +1128,37 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        ti->private = ms;
        ti->split_io = ms->rh.region_size;
 
+       ms->kmirrord_wq = create_singlethread_workqueue("kmirrord");
+       if (!ms->kmirrord_wq) {
+               DMERR("couldn't start kmirrord");
+               free_context(ms, ti, m);
+               return -ENOMEM;
+       }
+       INIT_WORK(&ms->kmirrord_work, do_mirror);
+
+       r = parse_features(ms, argc, argv, &args_used);
+       if (r) {
+               free_context(ms, ti, ms->nr_mirrors);
+               return r;
+       }
+
+       argv += args_used;
+       argc -= args_used;
+
+       if (argc) {
+               ti->error = "Too many mirror arguments";
+               free_context(ms, ti, ms->nr_mirrors);
+               return -EINVAL;
+       }
+
        r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
        if (r) {
+               destroy_workqueue(ms->kmirrord_wq);
                free_context(ms, ti, ms->nr_mirrors);
                return r;
        }
 
-       add_mirror_set(ms);
+       wake(ms);
        return 0;
 }
 
@@ -1110,8 +1166,9 @@ static void mirror_dtr(struct dm_target *ti)
 {
        struct mirror_set *ms = (struct mirror_set *) ti->private;
 
-       del_mirror_set(ms);
+       flush_workqueue(ms->kmirrord_wq);
        kcopyd_client_destroy(ms->kcopyd_client);
+       destroy_workqueue(ms->kmirrord_wq);
        free_context(ms, ti, ms->nr_mirrors);
 }
 
@@ -1127,7 +1184,7 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
        spin_unlock(&ms->lock);
 
        if (should_wake)
-               wake();
+               wake(ms);
 }
 
 /*
@@ -1222,11 +1279,9 @@ static void mirror_resume(struct dm_target *ti)
 static int mirror_status(struct dm_target *ti, status_type_t type,
                         char *result, unsigned int maxlen)
 {
-       unsigned int m, sz;
+       unsigned int m, sz = 0;
        struct mirror_set *ms = (struct mirror_set *) ti->private;
 
-       sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
-
        switch (type) {
        case STATUSTYPE_INFO:
                DMEMIT("%d ", ms->nr_mirrors);
@@ -1237,13 +1292,21 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
                        (unsigned long long)ms->rh.log->type->
                                get_sync_count(ms->rh.log),
                        (unsigned long long)ms->nr_regions);
+
+               sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
+
                break;
 
        case STATUSTYPE_TABLE:
+               sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
+
                DMEMIT("%d", ms->nr_mirrors);
                for (m = 0; m < ms->nr_mirrors; m++)
                        DMEMIT(" %s %llu", ms->mirror[m].dev->name,
                                (unsigned long long)ms->mirror[m].offset);
+
+               if (ms->features & DM_RAID1_HANDLE_ERRORS)
+                       DMEMIT(" 1 handle_errors");
        }
 
        return 0;
@@ -1251,7 +1314,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
 
 static struct target_type mirror_target = {
        .name    = "mirror",
-       .version = {1, 0, 2},
+       .version = {1, 0, 3},
        .module  = THIS_MODULE,
        .ctr     = mirror_ctr,
        .dtr     = mirror_dtr,
@@ -1270,20 +1333,11 @@ static int __init dm_mirror_init(void)
        if (r)
                return r;
 
-       _kmirrord_wq = create_singlethread_workqueue("kmirrord");
-       if (!_kmirrord_wq) {
-               DMERR("couldn't start kmirrord");
-               dm_dirty_log_exit();
-               return r;
-       }
-       INIT_WORK(&_kmirrord_work, do_work);
-
        r = dm_register_target(&mirror_target);
        if (r < 0) {
                DMERR("%s: Failed to register mirror target",
                      mirror_target.name);
                dm_dirty_log_exit();
-               destroy_workqueue(_kmirrord_wq);
        }
 
        return r;
@@ -1297,7 +1351,6 @@ static void __exit dm_mirror_exit(void)
        if (r < 0)
                DMERR("%s: unregister failed %d", mirror_target.name, r);
 
-       destroy_workqueue(_kmirrord_wq);
        dm_dirty_log_exit();
 }
 
index 05befa91807a332b87676bef2cc47de92417e1eb..2fc199b0016bd5c819b42572b97dbc69dc03844c 100644 (file)
@@ -425,13 +425,15 @@ static void close_dev(struct dm_dev *d, struct mapped_device *md)
 }
 
 /*
- * If possible (ie. blk_size[major] is set), this checks an area
- * of a destination device is valid.
+ * If possible, this checks an area of a destination device is valid.
  */
 static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len)
 {
-       sector_t dev_size;
-       dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT;
+       sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT;
+
+       if (!dev_size)
+               return 1;
+
        return ((start < dev_size) && (len <= (dev_size - start)));
 }
 
index 11a98df298ece4db805682edc80d9860635f5cc4..2717a355dc5bf6847243de88f78fd540da5e941b 100644 (file)
@@ -1236,6 +1236,7 @@ void dm_put(struct mapped_device *md)
                free_dev(md);
        }
 }
+EXPORT_SYMBOL_GPL(dm_put);
 
 /*
  * Process the deferred bios
index b46f6c575f7ebd5ee79dbe543525ed5459e173d6..dbc234e3c69f917fb58e7a2f7d26b89dea324b9f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006 Red Hat GmbH
  *
  * This file is released under the GPL.
  *
@@ -45,6 +46,8 @@ struct kcopyd_client {
        unsigned int nr_pages;
        unsigned int nr_free_pages;
 
+       struct dm_io_client *io_client;
+
        wait_queue_head_t destroyq;
        atomic_t nr_jobs;
 };
@@ -342,16 +345,20 @@ static void complete_io(unsigned long error, void *context)
 static int run_io_job(struct kcopyd_job *job)
 {
        int r;
+       struct dm_io_request io_req = {
+               .bi_rw = job->rw,
+               .mem.type = DM_IO_PAGE_LIST,
+               .mem.ptr.pl = job->pages,
+               .mem.offset = job->offset,
+               .notify.fn = complete_io,
+               .notify.context = job,
+               .client = job->kc->io_client,
+       };
 
        if (job->rw == READ)
-               r = dm_io_async(1, &job->source, job->rw,
-                               job->pages,
-                               job->offset, complete_io, job);
-
+               r = dm_io(&io_req, 1, &job->source, NULL);
        else
-               r = dm_io_async(job->num_dests, job->dests, job->rw,
-                               job->pages,
-                               job->offset, complete_io, job);
+               r = dm_io(&io_req, job->num_dests, job->dests, NULL);
 
        return r;
 }
@@ -670,8 +677,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
                return r;
        }
 
-       r = dm_io_get(nr_pages);
-       if (r) {
+       kc->io_client = dm_io_client_create(nr_pages);
+       if (IS_ERR(kc->io_client)) {
+               r = PTR_ERR(kc->io_client);
                client_free_pages(kc);
                kfree(kc);
                kcopyd_exit();
@@ -691,7 +699,7 @@ void kcopyd_client_destroy(struct kcopyd_client *kc)
        /* Wait for completion of all jobs submitted by this client. */
        wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
 
-       dm_io_put(kc->nr_pages);
+       dm_io_client_destroy(kc->io_client);
        client_free_pages(kc);
        client_del(kc);
        kfree(kc);
index 2b4315d7e5d6531573e7ecfedd425df19178a3f3..2901d0c0ee9ec4f166e8a6b5c8a080449e571c20 100644 (file)
@@ -33,6 +33,7 @@
 */
 
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/linkage.h>
 #include <linux/raid/md.h>
@@ -273,6 +274,7 @@ static mddev_t * mddev_find(dev_t unit)
        atomic_set(&new->active, 1);
        spin_lock_init(&new->write_lock);
        init_waitqueue_head(&new->sb_wait);
+       new->reshape_position = MaxSector;
 
        new->queue = blk_alloc_queue(GFP_KERNEL);
        if (!new->queue) {
@@ -589,14 +591,41 @@ abort:
        return ret;
 }
 
+
+static u32 md_csum_fold(u32 csum)
+{
+       csum = (csum & 0xffff) + (csum >> 16);
+       return (csum & 0xffff) + (csum >> 16);
+}
+
 static unsigned int calc_sb_csum(mdp_super_t * sb)
 {
+       u64 newcsum = 0;
+       u32 *sb32 = (u32*)sb;
+       int i;
        unsigned int disk_csum, csum;
 
        disk_csum = sb->sb_csum;
        sb->sb_csum = 0;
-       csum = csum_partial((void *)sb, MD_SB_BYTES, 0);
+
+       for (i = 0; i < MD_SB_BYTES/4 ; i++)
+               newcsum += sb32[i];
+       csum = (newcsum & 0xffffffff) + (newcsum>>32);
+
+
+#ifdef CONFIG_ALPHA
+       /* This used to use csum_partial, which was wrong for several
+        * reasons including that different results are returned on
+        * different architectures.  It isn't critical that we get exactly
+        * the same return value as before (we always csum_fold before
+        * testing, and that removes any differences).  However as we
+        * know that csum_partial always returned a 16bit value on
+        * alphas, do a fold to maximise conformity to previous behaviour.
+        */
+       sb->sb_csum = md_csum_fold(disk_csum);
+#else
        sb->sb_csum = disk_csum;
+#endif
        return csum;
 }
 
@@ -684,7 +713,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
        if (sb->raid_disks <= 0)
                goto abort;
 
-       if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) {
+       if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
                printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
                        b);
                goto abort;
@@ -694,6 +723,17 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
        rdev->data_offset = 0;
        rdev->sb_size = MD_SB_BYTES;
 
+       if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
+               if (sb->level != 1 && sb->level != 4
+                   && sb->level != 5 && sb->level != 6
+                   && sb->level != 10) {
+                       /* FIXME use a better test */
+                       printk(KERN_WARNING
+                              "md: bitmaps not supported for this level.\n");
+                       goto abort;
+               }
+       }
+
        if (sb->level == LEVEL_MULTIPATH)
                rdev->desc_nr = -1;
        else
@@ -792,16 +832,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->max_disks = MD_SB_DISKS;
 
                if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
-                   mddev->bitmap_file == NULL) {
-                       if (mddev->level != 1 && mddev->level != 4
-                           && mddev->level != 5 && mddev->level != 6
-                           && mddev->level != 10) {
-                               /* FIXME use a better test */
-                               printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
-                               return -EINVAL;
-                       }
+                   mddev->bitmap_file == NULL)
                        mddev->bitmap_offset = mddev->default_bitmap_offset;
-               }
 
        } else if (mddev->pers == NULL) {
                /* Insist on good event counter while assembling */
@@ -1058,6 +1090,18 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
                       bdevname(rdev->bdev,b));
                return -EINVAL;
        }
+       if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
+               if (sb->level != cpu_to_le32(1) &&
+                   sb->level != cpu_to_le32(4) &&
+                   sb->level != cpu_to_le32(5) &&
+                   sb->level != cpu_to_le32(6) &&
+                   sb->level != cpu_to_le32(10)) {
+                       printk(KERN_WARNING
+                              "md: bitmaps not supported for this level.\n");
+                       return -EINVAL;
+               }
+       }
+
        rdev->preferred_minor = 0xffff;
        rdev->data_offset = le64_to_cpu(sb->data_offset);
        atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
@@ -1141,14 +1185,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->max_disks =  (4096-256)/2;
 
                if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
-                   mddev->bitmap_file == NULL ) {
-                       if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
-                           && mddev->level != 10) {
-                               printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
-                               return -EINVAL;
-                       }
+                   mddev->bitmap_file == NULL )
                        mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
-               }
+
                if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
                        mddev->reshape_position = le64_to_cpu(sb->reshape_position);
                        mddev->delta_disks = le32_to_cpu(sb->delta_disks);
@@ -2204,6 +2243,10 @@ static ssize_t
 layout_show(mddev_t *mddev, char *page)
 {
        /* just a number, not meaningful for all levels */
+       if (mddev->reshape_position != MaxSector &&
+           mddev->layout != mddev->new_layout)
+               return sprintf(page, "%d (%d)\n",
+                              mddev->new_layout, mddev->layout);
        return sprintf(page, "%d\n", mddev->layout);
 }
 
@@ -2212,13 +2255,16 @@ layout_store(mddev_t *mddev, const char *buf, size_t len)
 {
        char *e;
        unsigned long n = simple_strtoul(buf, &e, 10);
-       if (mddev->pers)
-               return -EBUSY;
 
        if (!*buf || (*e && *e != '\n'))
                return -EINVAL;
 
-       mddev->layout = n;
+       if (mddev->pers)
+               return -EBUSY;
+       if (mddev->reshape_position != MaxSector)
+               mddev->new_layout = n;
+       else
+               mddev->layout = n;
        return len;
 }
 static struct md_sysfs_entry md_layout =
@@ -2230,6 +2276,10 @@ raid_disks_show(mddev_t *mddev, char *page)
 {
        if (mddev->raid_disks == 0)
                return 0;
+       if (mddev->reshape_position != MaxSector &&
+           mddev->delta_disks != 0)
+               return sprintf(page, "%d (%d)\n", mddev->raid_disks,
+                              mddev->raid_disks - mddev->delta_disks);
        return sprintf(page, "%d\n", mddev->raid_disks);
 }
 
@@ -2247,7 +2297,11 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
 
        if (mddev->pers)
                rv = update_raid_disks(mddev, n);
-       else
+       else if (mddev->reshape_position != MaxSector) {
+               int olddisks = mddev->raid_disks - mddev->delta_disks;
+               mddev->delta_disks = n - olddisks;
+               mddev->raid_disks = n;
+       } else
                mddev->raid_disks = n;
        return rv ? rv : len;
 }
@@ -2257,6 +2311,10 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
 static ssize_t
 chunk_size_show(mddev_t *mddev, char *page)
 {
+       if (mddev->reshape_position != MaxSector &&
+           mddev->chunk_size != mddev->new_chunk)
+               return sprintf(page, "%d (%d)\n", mddev->new_chunk,
+                              mddev->chunk_size);
        return sprintf(page, "%d\n", mddev->chunk_size);
 }
 
@@ -2267,12 +2325,15 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
        char *e;
        unsigned long n = simple_strtoul(buf, &e, 10);
 
-       if (mddev->pers)
-               return -EBUSY;
        if (!*buf || (*e && *e != '\n'))
                return -EINVAL;
 
-       mddev->chunk_size = n;
+       if (mddev->pers)
+               return -EBUSY;
+       else if (mddev->reshape_position != MaxSector)
+               mddev->new_chunk = n;
+       else
+               mddev->chunk_size = n;
        return len;
 }
 static struct md_sysfs_entry md_chunk_size =
@@ -2637,8 +2698,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
        minor = simple_strtoul(buf, &e, 10);
        if (e==buf || (*e && *e != '\n') )
                return -EINVAL;
-       if (major >= sizeof(super_types)/sizeof(super_types[0]) ||
-           super_types[major].name == NULL)
+       if (major >= ARRAY_SIZE(super_types) || super_types[major].name == NULL)
                return -ENOENT;
        mddev->major_version = major;
        mddev->minor_version = minor;
@@ -2859,6 +2919,37 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
 static struct md_sysfs_entry md_suspend_hi =
 __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
 
+static ssize_t
+reshape_position_show(mddev_t *mddev, char *page)
+{
+       if (mddev->reshape_position != MaxSector)
+               return sprintf(page, "%llu\n",
+                              (unsigned long long)mddev->reshape_position);
+       strcpy(page, "none\n");
+       return 5;
+}
+
+static ssize_t
+reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
+{
+       char *e;
+       unsigned long long new = simple_strtoull(buf, &e, 10);
+       if (mddev->pers)
+               return -EBUSY;
+       if (buf == e || (*e && *e != '\n'))
+               return -EINVAL;
+       mddev->reshape_position = new;
+       mddev->delta_disks = 0;
+       mddev->new_level = mddev->level;
+       mddev->new_layout = mddev->layout;
+       mddev->new_chunk = mddev->chunk_size;
+       return len;
+}
+
+static struct md_sysfs_entry md_reshape_position =
+__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
+       reshape_position_store);
+
 
 static struct attribute *md_default_attrs[] = {
        &md_level.attr,
@@ -2871,6 +2962,7 @@ static struct attribute *md_default_attrs[] = {
        &md_new_device.attr,
        &md_safe_delay.attr,
        &md_array_state.attr,
+       &md_reshape_position.attr,
        NULL,
 };
 
@@ -3012,6 +3104,7 @@ static int do_md_run(mddev_t * mddev)
        struct gendisk *disk;
        struct mdk_personality *pers;
        char b[BDEVNAME_SIZE];
+       struct block_device *bdev;
 
        if (list_empty(&mddev->disks))
                /* cannot run an array with no devices.. */
@@ -3239,7 +3332,13 @@ static int do_md_run(mddev_t * mddev)
        md_wakeup_thread(mddev->thread);
        md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
-       mddev->changed = 1;
+       bdev = bdget_disk(mddev->gendisk, 0);
+       if (bdev) {
+               bd_set_size(bdev, mddev->array_size << 1);
+               blkdev_ioctl(bdev->bd_inode, NULL, BLKRRPART, 0);
+               bdput(bdev);
+       }
+
        md_new_event(mddev);
        kobject_uevent(&mddev->gendisk->kobj, KOBJ_CHANGE);
        return 0;
@@ -3361,7 +3460,6 @@ static int do_md_stop(mddev_t * mddev, int mode)
                        mddev->pers = NULL;
 
                        set_capacity(disk, 0);
-                       mddev->changed = 1;
 
                        if (mddev->ro)
                                mddev->ro = 0;
@@ -3409,6 +3507,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
                mddev->size = 0;
                mddev->raid_disks = 0;
                mddev->recovery_cp = 0;
+               mddev->reshape_position = MaxSector;
 
        } else if (mddev->pers)
                printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -4019,7 +4118,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
        if (info->raid_disks == 0) {
                /* just setting version number for superblock loading */
                if (info->major_version < 0 ||
-                   info->major_version >= sizeof(super_types)/sizeof(super_types[0]) ||
+                   info->major_version >= ARRAY_SIZE(super_types) ||
                    super_types[info->major_version].name == NULL) {
                        /* maybe try to auto-load a module? */
                        printk(KERN_INFO 
@@ -4500,20 +4599,6 @@ static int md_release(struct inode *inode, struct file * file)
        return 0;
 }
 
-static int md_media_changed(struct gendisk *disk)
-{
-       mddev_t *mddev = disk->private_data;
-
-       return mddev->changed;
-}
-
-static int md_revalidate(struct gendisk *disk)
-{
-       mddev_t *mddev = disk->private_data;
-
-       mddev->changed = 0;
-       return 0;
-}
 static struct block_device_operations md_fops =
 {
        .owner          = THIS_MODULE,
@@ -4521,8 +4606,6 @@ static struct block_device_operations md_fops =
        .release        = md_release,
        .ioctl          = md_ioctl,
        .getgeo         = md_getgeo,
-       .media_changed  = md_media_changed,
-       .revalidate_disk= md_revalidate,
 };
 
 static int md_thread(void * arg)
@@ -4941,15 +5024,6 @@ static int md_seq_open(struct inode *inode, struct file *file)
        return error;
 }
 
-static int md_seq_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *m = file->private_data;
-       struct mdstat_info *mi = m->private;
-       m->private = NULL;
-       kfree(mi);
-       return seq_release(inode, file);
-}
-
 static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
 {
        struct seq_file *m = filp->private_data;
@@ -4971,7 +5045,7 @@ static const struct file_operations md_seq_fops = {
        .open           = md_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = md_seq_release,
+       .release        = seq_release_private,
        .poll           = mdstat_poll,
 };
 
index 97ee870b265d866ffa818bdf83dc7f551cd40d7b..1b7130cad21fc962876a7efcc37ccbd8b8c71cad 100644 (file)
@@ -2063,7 +2063,6 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
         */
        mddev->array_size = sectors>>1;
        set_capacity(mddev->gendisk, mddev->array_size << 1);
-       mddev->changed = 1;
        if (mddev->array_size > mddev->size && mddev->recovery_cp == MaxSector) {
                mddev->recovery_cp = mddev->size << 1;
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
index 8d59914f2057a6d0a06527dd8b3c872ed3c1b842..a72e70ad09754f4a5a5616639fdfd513e0d19a18 100644 (file)
@@ -353,8 +353,8 @@ static int grow_stripes(raid5_conf_t *conf, int num)
        struct kmem_cache *sc;
        int devs = conf->raid_disks;
 
-       sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev));
-       sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev));
+       sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
+       sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
        conf->active_name = 0;
        sc = kmem_cache_create(conf->cache_name[conf->active_name],
                               sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
@@ -3864,7 +3864,6 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
        sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
        mddev->array_size = (sectors * (mddev->raid_disks-conf->max_degraded))>>1;
        set_capacity(mddev->gendisk, mddev->array_size << 1);
-       mddev->changed = 1;
        if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
                mddev->recovery_cp = mddev->size << 1;
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -3999,7 +3998,6 @@ static void end_reshape(raid5_conf_t *conf)
                conf->mddev->array_size = conf->mddev->size *
                        (conf->raid_disks - conf->max_degraded);
                set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
-               conf->mddev->changed = 1;
 
                bdev = bdget_disk(conf->mddev->gendisk, 0);
                if (bdev) {
index 3bf084f2e5226b883aeca002b39e75b54de04801..87623d203a89ab70546576276a6db8e8f56a71cf 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef DST_COMMON_H
 #define DST_COMMON_H
 
-#include <linux/smp_lock.h>
 #include <linux/dvb/frontend.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
index 68ed3a788083dd1a69124fa430e440c49d55bd49..9200a30dd1b906ffad037d3351d441f56a668c2c 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
- * This file contains functions for initializing the the input-device and for handling remote-control-queries.
+ * This file contains functions for initializing the input-device and for handling remote-control-queries.
  */
 #include "dvb-usb-common.h"
 #include <linux/usb/input.h>
index f5d40aa3d27f707b021a32b4578929c7e231e362..f64546c6aeb5b63af45dffb0b6dd6efc462f602c 100644 (file)
@@ -266,7 +266,7 @@ static int dib7000m_sad_calib(struct dib7000m_state *state)
 {
 
 /* internal */
-//     dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+//     dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth
        dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
        dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
 
index 0349a4b5da3f863c5f891e98bf4753568f508efd..aece458cfe12eb50441dca12258bd23eb3be64f8 100644 (file)
@@ -223,7 +223,7 @@ static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx)
 static int dib7000p_sad_calib(struct dib7000p_state *state)
 {
 /* internal */
-//     dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+//     dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth
        dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
        dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
 
index 110536843e8e891354ab08135c677ed0f53e7b8d..e725f612a6b72c2b8d34965297aac2b73dc8e62e 100644 (file)
@@ -1,6 +1,6 @@
 /*
     TDA10021  - Single Chip Cable Channel Receiver driver module
-              used on the the Siemens DVB-C cards
+              used on the Siemens DVB-C cards
 
     Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
     Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
index 54d7b07571b8e3ac23482a5ad2acd9eb9704dd45..23fd0303c91b486a38776ab80fc8c915a0e9d364 100644 (file)
@@ -306,7 +306,7 @@ static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
         * The ves1893 sometimes returns sync values that make no sense,
         * because, e.g., the SIGNAL bit is 0, while some of the higher
         * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?).
-        * Tests showed that the the VITERBI and SYNC bits are returned
+        * Tests showed that the VITERBI and SYNC bits are returned
         * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong.
         * If such a case occurs, we read the value again, until we get a
         * valid value.
index 654c9e919e045469bf3dabda34db62e45cb5ac3d..58678c05aa53924dfd44ab4de78c3643abfac9b1 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 
 #include "av7110.h"
index e9b4e88e793231f6c49765e0103c4935d02a4d73..e1c1294bb7673ccfe9a1ec617767ef0feae6f289 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include "av7110.h"
 #include "av7110_hw.h"
index 4d7150e15d1e1378c244df17f95569bd15f44843..70aee4eb5da46f11d6ed703b08cfb2925fbd1965 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 
 #include "av7110.h"
index cde5d3ae7ec783b32f73e9ee517013daa1be59c7..fcd9994058d004077c1525814eb2e65167b25ac8 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include "av7110.h"
 #include "av7110_hw.h"
index df8d0520d1d1e304e47513552e57ff8c7f45eaf1..449df1bb00d3050914a219a8ee99d8fca498cb48 100644 (file)
@@ -79,7 +79,6 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 
 /*
  * Version Information
index 6eaa692021c58f61c52843df4e60bea7172cddb1..78392fb6f94ea3dd8b430f338024b73d86a5842c 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
 struct cpia_camera_ops
index 19711aaf9a3e4de1171db185ad45678a5ef6331f..c431df8248d659199c66da758e6afcd35a918575 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 
 #include <linux/kmod.h>
index e627062fde3a85ec7e6ee832857827d45cfdf94c..259ea08e784fdb53bd4edd4d94078b7a1a2f49c6 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 
index ff4b238090aca8a866e2e2e42b8d242522c40ae8..a5731f90be0f842d39aa1a941c50d0ab31d3f6e9 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
 #include "dabusb.h"
index 563a8319e608eedca87736e1849b4462617b8e76..54ccc6e1f92e05e00beb9327285ba1d2b4c3cd24 100644 (file)
@@ -70,7 +70,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
 
        ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
        if (ret != 2 + len) {
-               em28xx_warn("writting to i2c device failed (error=%i)\n", ret);
+               em28xx_warn("writing to i2c device failed (error=%i)\n", ret);
                return -EIO;
        }
        for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
index bec67609500fd1b1d34dbc6ac2d675af651f4169..2c7b158ce7e1bdbf9af1826701a9780ba6a3aa58 100644 (file)
@@ -1729,7 +1729,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 
        endpoint = &interface->cur_altsetting->endpoint[1].desc;
 
-       /* check if the the device has the iso in endpoint at the correct place */
+       /* check if the device has the iso in endpoint at the correct place */
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
            USB_ENDPOINT_XFER_ISOC) {
                em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
index 68b082bcee1dcf2c704f53d0b194a61a1365a506..18c64222dd11f7f4a38bab979165085e2863bf2f 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
-#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
index e976c484c058db621d52a6e90d0ac738c590382b..9ea41c6699bbdcc7b3bee873bcbf52f836f6762d 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 
index f5e8484103116045fec5912c584f46cf175ef181..f9f3584281d864a4e837c4a7489c2359c531859c 100644 (file)
@@ -54,9 +54,9 @@ fps
    Specifies the desired framerate. Is an integer in the range of 4-30.
 
 fbufs
-   This paramter specifies the number of internal buffers to use for storing
+   This parameter specifies the number of internal buffers to use for storing
    frames from the cam. This will help if the process that reads images from
-   the cam is a bit slow or momentarely busy. However, on slow machines it
+   the cam is a bit slow or momentarily busy. However, on slow machines it
    only introduces lag, so choose carefully. The default is 3, which is
    reasonable. You can set it between 2 and 5.
 
@@ -209,7 +209,7 @@ trace
 
      128   0x80   PWCX debugging                                      Off
 
-   For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+   For example, to trace the open() & read() functions, sum 8 + 4 = 12,
    so you would supply trace=12 during insmod or modprobe. If
    you want to turn the initialization and probing tracing off, set trace=0.
    The default value for trace is 35 (0x23).
index dd759d6d8d25c88a831f4b0a9689d714222717fe..7b56041186dcbc0a96bab5656754d2a2d7ecd0d9 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <asm/div64.h>
 
 #include "saa7134-reg.h"
index c0891b3e0018efd404cd585b28624a2a7cdc655d..835ef872e80375af580d676d5616ce0635f9a536 100644 (file)
@@ -5,7 +5,6 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
 #define se401_DEBUG    /* Turn on debug messages */
index a2da5d2affff6c969d7da9a24540922a13a28723..c9bf9dbc2ea3a5752b25cafe5324b24e0de19acc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/videodev.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
index 687f026753b2021bce21ac74e5b0c90e4eedc218..37ce36b9e5878bc9123691e3b859b442995b93bd 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
index 876fd276824215d35b29e3a539642c80a1df0e15..982b115193f855e5e6cdee2191b9b1ae1e11c78c 100644 (file)
@@ -28,7 +28,7 @@
  *
  * Portions of this code were also copied from usbvideo.c
  *
- * Special thanks to the the whole team at Sourceforge for help making
+ * Special thanks to the whole team at Sourceforge for help making
  * this driver become a reality.  Notably:
  * Andy Armstrong who reverse engineered the color encoding and
  * Pavel Machek and Chris Cheney who worked on reverse engineering the
index bcb551adb7e6c650be4d850fa6c80b26bf711506..9118a6227ea63034d8d63469be9335c96993aa21 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
 #include <linux/videodev.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
index 216704170a4c2075f7c53922644d57e62774007b..aa3258bbb4afe49f81b52bcd17d20d0420908e42 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
 #include <linux/videodev.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
index d2c1ae0dbfba55f4f82f0c6911717b4a857d651b..a861e150865e6c11ce5ff77264024124d0bc7b7d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/file.h>
index 49f1df74aa21d9f008717d598be1ae8a87a9c7bc..13ee550d3215d7d93d3989611da2648d8a4c135d 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
index 80ac5f86d9e561d494fbd1fa42e411d7cb5d2c4c..5263b50463e11372ea37de29f2e62b7d9de97faf 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
index 074323733352739dd1384d8c4fed9167ec332807..cf0ed6cbb0e39eb8363120e477bef27549c754ff 100644 (file)
@@ -2034,7 +2034,7 @@ zoran_do_ioctl (struct inode *inode,
         * but moving the free code outside the munmap() handler fixes
         * all this... If someone knows why, please explain me (Ronald)
         */
-       if (!!mutex_trylock(&zr->resource_lock)) {
+       if (mutex_trylock(&zr->resource_lock)) {
                /* we obtained it! Let's try to free some things */
                if (fh->jpg_buffers.ready_to_be_freed)
                        jpg_fbuffer_free(file);
index d6b4c607453bdde0cd1179e40cab7786e52ee231..ddc7ae029dd3bb9dc8f61b4e4dd9de5b825bb09d 100644 (file)
@@ -571,7 +571,7 @@ mpi_fc.h
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  12-04-00  01.01.02  Added messages for Common Transport Send and
  *                      Primitive Send.
- *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
+ *  01-09-01  01.01.03  Modified some of the new flags to have an MPI prefix
  *                      and modified the FcPrimitiveSend flags.
  *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
  *                      field.
index 97471af4309c7a7b44b011a438df6d65957ece7a..5021d1a2a1d4856e058915ea9a0d2fb8309b3f60 100644 (file)
@@ -3585,7 +3585,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
         * index = chain_idx
         *
         * Calculate the number of chain buffers needed(plus 1) per I/O
-        * then multiply the the maximum number of simultaneous cmds
+        * then multiply the maximum number of simultaneous cmds
         *
         * num_sge = num sge in request frame + last chain buffer
         * scale = num sge per chain buffer if no chain element
diff --git a/drivers/message/i2o/i2o_lan.h b/drivers/message/i2o/i2o_lan.h
deleted file mode 100644 (file)
index 6502b81..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- *     i2o_lan.h                       I2O LAN Class definitions
- *
- *      I2O LAN CLASS OSM              May 26th 2000
- *
- *      (C) Copyright 1999, 2000       University of Helsinki,
- *                                     Department of Computer Science
- *
- *      This code is still under development / test.
- *
- *     Author:         Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- *                     Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- *                     Taneli Vähäkangas <Taneli.Vahakangas@cs.Helsinki.FI>
- */
-
-#ifndef _I2O_LAN_H
-#define _I2O_LAN_H
-
-/* Default values for tunable parameters first */
-
-#define I2O_LAN_MAX_BUCKETS_OUT 96
-#define I2O_LAN_BUCKET_THRESH  18      /* 9 buckets in one message */
-#define I2O_LAN_RX_COPYBREAK   200
-#define I2O_LAN_TX_TIMEOUT     (1*HZ)
-#define I2O_LAN_TX_BATCH_MODE  2       /* 2=automatic, 1=on, 0=off */
-#define I2O_LAN_EVENT_MASK     0       /* 0=None, 0xFFC00002=All */
-
-/* LAN types */
-#define I2O_LAN_ETHERNET       0x0030
-#define I2O_LAN_100VG          0x0040
-#define I2O_LAN_TR             0x0050
-#define I2O_LAN_FDDI           0x0060
-#define I2O_LAN_FIBRE_CHANNEL  0x0070
-#define I2O_LAN_UNKNOWN                0x00000000
-
-/* Connector types */
-
-/* Ethernet */
-#define I2O_LAN_AUI            (I2O_LAN_ETHERNET << 4) + 0x00000001
-#define I2O_LAN_10BASE5                (I2O_LAN_ETHERNET << 4) + 0x00000002
-#define I2O_LAN_FIORL          (I2O_LAN_ETHERNET << 4) + 0x00000003
-#define I2O_LAN_10BASE2                (I2O_LAN_ETHERNET << 4) + 0x00000004
-#define I2O_LAN_10BROAD36      (I2O_LAN_ETHERNET << 4) + 0x00000005
-#define I2O_LAN_10BASE_T       (I2O_LAN_ETHERNET << 4) + 0x00000006
-#define I2O_LAN_10BASE_FP      (I2O_LAN_ETHERNET << 4) + 0x00000007
-#define I2O_LAN_10BASE_FB      (I2O_LAN_ETHERNET << 4) + 0x00000008
-#define I2O_LAN_10BASE_FL      (I2O_LAN_ETHERNET << 4) + 0x00000009
-#define I2O_LAN_100BASE_TX     (I2O_LAN_ETHERNET << 4) + 0x0000000A
-#define I2O_LAN_100BASE_FX     (I2O_LAN_ETHERNET << 4) + 0x0000000B
-#define I2O_LAN_100BASE_T4     (I2O_LAN_ETHERNET << 4) + 0x0000000C
-#define I2O_LAN_1000BASE_SX    (I2O_LAN_ETHERNET << 4) + 0x0000000D
-#define I2O_LAN_1000BASE_LX    (I2O_LAN_ETHERNET << 4) + 0x0000000E
-#define I2O_LAN_1000BASE_CX    (I2O_LAN_ETHERNET << 4) + 0x0000000F
-#define I2O_LAN_1000BASE_T     (I2O_LAN_ETHERNET << 4) + 0x00000010
-
-/* AnyLAN */
-#define I2O_LAN_100VG_ETHERNET (I2O_LAN_100VG << 4) + 0x00000001
-#define I2O_LAN_100VG_TR       (I2O_LAN_100VG << 4) + 0x00000002
-
-/* Token Ring */
-#define I2O_LAN_4MBIT          (I2O_LAN_TR << 4) + 0x00000001
-#define I2O_LAN_16MBIT         (I2O_LAN_TR << 4) + 0x00000002
-
-/* FDDI */
-#define I2O_LAN_125MBAUD       (I2O_LAN_FDDI << 4) + 0x00000001
-
-/* Fibre Channel */
-#define I2O_LAN_POINT_POINT    (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000001
-#define I2O_LAN_ARB_LOOP       (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000002
-#define I2O_LAN_PUBLIC_LOOP    (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000003
-#define I2O_LAN_FABRIC         (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000004
-
-#define I2O_LAN_EMULATION      0x00000F00
-#define I2O_LAN_OTHER          0x00000F01
-#define I2O_LAN_DEFAULT                0xFFFFFFFF
-
-/* LAN class functions */
-
-#define LAN_PACKET_SEND                0x3B
-#define LAN_SDU_SEND           0x3D
-#define LAN_RECEIVE_POST       0x3E
-#define LAN_RESET              0x35
-#define LAN_SUSPEND            0x37
-
-/* LAN DetailedStatusCode defines */
-#define I2O_LAN_DSC_SUCCESS                    0x00
-#define I2O_LAN_DSC_DEVICE_FAILURE             0x01
-#define I2O_LAN_DSC_DESTINATION_NOT_FOUND      0x02
-#define        I2O_LAN_DSC_TRANSMIT_ERROR              0x03
-#define I2O_LAN_DSC_TRANSMIT_ABORTED           0x04
-#define I2O_LAN_DSC_RECEIVE_ERROR              0x05
-#define I2O_LAN_DSC_RECEIVE_ABORTED            0x06
-#define I2O_LAN_DSC_DMA_ERROR                  0x07
-#define I2O_LAN_DSC_BAD_PACKET_DETECTED                0x08
-#define I2O_LAN_DSC_OUT_OF_MEMORY              0x09
-#define I2O_LAN_DSC_BUCKET_OVERRUN             0x0A
-#define I2O_LAN_DSC_IOP_INTERNAL_ERROR         0x0B
-#define I2O_LAN_DSC_CANCELED                   0x0C
-#define I2O_LAN_DSC_INVALID_TRANSACTION_CONTEXT        0x0D
-#define I2O_LAN_DSC_DEST_ADDRESS_DETECTED      0x0E
-#define I2O_LAN_DSC_DEST_ADDRESS_OMITTED       0x0F
-#define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED    0x10
-#define I2O_LAN_DSC_SUSPENDED                  0x11
-
-struct i2o_packet_info {
-       u32 offset:24;
-       u32 flags:8;
-       u32 len:24;
-       u32 status:8;
-};
-
-struct i2o_bucket_descriptor {
-       u32 context;            /* FIXME: 64bit support */
-       struct i2o_packet_info packet_info[1];
-};
-
-/* Event Indicator Mask Flags for LAN OSM */
-
-#define I2O_LAN_EVT_LINK_DOWN          0x01
-#define I2O_LAN_EVT_LINK_UP            0x02
-#define I2O_LAN_EVT_MEDIA_CHANGE       0x04
-
-#include <linux/netdevice.h>
-#include <linux/fddidevice.h>
-
-struct i2o_lan_local {
-       u8 unit;
-       struct i2o_device *i2o_dev;
-
-       struct fddi_statistics stats;   /* see also struct net_device_stats */
-       unsigned short (*type_trans) (struct sk_buff *, struct net_device *);
-       atomic_t buckets_out;   /* nbr of unused buckets on DDM */
-       atomic_t tx_out;        /* outstanding TXes */
-       u8 tx_count;            /* packets in one TX message frame */
-       u16 tx_max_out;         /* DDM's Tx queue len */
-       u8 sgl_max;             /* max SGLs in one message frame */
-       u32 m;                  /* IOP address of the batch msg frame */
-
-       struct work_struct i2o_batch_send_task;
-       int send_active;
-       struct sk_buff **i2o_fbl;       /* Free bucket list (to reuse skbs) */
-       int i2o_fbl_tail;
-       spinlock_t fbl_lock;
-
-       spinlock_t tx_lock;
-
-       u32 max_size_mc_table;  /* max number of multicast addresses */
-
-       /* LAN OSM configurable parameters are here: */
-
-       u16 max_buckets_out;    /* max nbr of buckets to send to DDM */
-       u16 bucket_thresh;      /* send more when this many used */
-       u16 rx_copybreak;
-
-       u8 tx_batch_mode;       /* Set when using batch mode sends */
-       u32 i2o_event_mask;     /* To turn on interesting event flags */
-};
-
-#endif                         /* _I2O_LAN_H */
index ce1a48108210d38f645d34caa1273ad4d0acd60d..cb8c264eaff07e7ce93883e164910d60b909f191 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
index a3c525b2616aafeaa855b03377e0f4ee4937cdc5..877e7909a0e55c34341f89ef0069be67922080fb 100644 (file)
@@ -25,6 +25,15 @@ config IBM_ASM
          information on the specific driver level and support statement
          for your IBM server.
 
+config PHANTOM
+       tristate "Sensable PHANToM"
+       depends on PCI
+       help
+         Say Y here if you want to build a driver for Sensable PHANToM device.
+
+         If you choose to build module, its name will be phantom. If unsure,
+         say N here.
+
 
          If unsure, say N.
 
@@ -178,4 +187,13 @@ config THINKPAD_ACPI_BAY
 
          If you are not sure, say Y here.
 
+config BLINK
+       tristate "Keyboard blink driver"
+       help
+         Driver that when loaded will blink the keyboard LEDs continuously.
+         This is useful for debugging and for kernels that cannot necessarily
+         output something to the screen like kexec kernels to give the user
+         a visual indication that the kernel is doing something.
+
+
 endmenu
index e325164591380bd93011840757808b3927e26eb1..5b6d46de005ca47b2f260eebbec881686a4fca8d 100644 (file)
@@ -7,9 +7,11 @@ obj-$(CONFIG_IBM_ASM)          += ibmasm/
 obj-$(CONFIG_HDPU_FEATURES)    += hdpuftrs/
 obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
 obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
+obj-$(CONFIG_BLINK)            += blink.o
 obj-$(CONFIG_LKDTM)            += lkdtm.o
 obj-$(CONFIG_TIFM_CORE)        += tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)        += tifm_7xx1.o
+obj-$(CONFIG_PHANTOM)          += phantom.o
 obj-$(CONFIG_SGI_IOC4)         += ioc4.o
 obj-$(CONFIG_SONY_LAPTOP)      += sony-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)    += thinkpad_acpi.o
diff --git a/drivers/misc/blink.c b/drivers/misc/blink.c
new file mode 100644 (file)
index 0000000..634431c
--- /dev/null
@@ -0,0 +1,27 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static void do_blink(unsigned long data);
+
+static DEFINE_TIMER(blink_timer, do_blink, 0 ,0);
+
+static void do_blink(unsigned long data)
+{
+       static long count;
+       if (panic_blink)
+               panic_blink(count++);
+       blink_timer.expires = jiffies + msecs_to_jiffies(1);
+       add_timer(&blink_timer);
+}
+
+static int blink_init(void)
+{
+       printk(KERN_INFO "Enabling keyboard blinking\n");
+       do_blink(0);
+       return 0;
+}
+
+module_init(blink_init);
+
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
new file mode 100644 (file)
index 0000000..35b139b
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ *  Copyright (C) 2005-2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  You need an userspace library to cooperate with this driver. It (and other
+ *  info) may be obtained here:
+ *  http://www.fi.muni.cz/~xslaby/phantom.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/phantom.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+
+#define PHANTOM_VERSION                "n0.9.5"
+
+#define PHANTOM_MAX_MINORS     8
+
+#define PHN_IRQCTL             0x4c    /* irq control in caddr space */
+
+#define PHB_RUNNING            1
+
+static struct class *phantom_class;
+static int phantom_major;
+
+struct phantom_device {
+       unsigned int opened;
+       void __iomem *caddr;
+       u32 __iomem *iaddr;
+       u32 __iomem *oaddr;
+       unsigned long status;
+       atomic_t counter;
+
+       wait_queue_head_t wait;
+       struct cdev cdev;
+
+       struct mutex open_lock;
+};
+
+static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
+
+static int phantom_status(struct phantom_device *dev, unsigned long newstat)
+{
+       pr_debug("phantom_status %lx %lx\n", dev->status, newstat);
+
+       if (!(dev->status & PHB_RUNNING) && (newstat & PHB_RUNNING)) {
+               atomic_set(&dev->counter, 0);
+               iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
+               iowrite32(0x43, dev->caddr + PHN_IRQCTL);
+       } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING))
+               iowrite32(0, dev->caddr + PHN_IRQCTL);
+
+       dev->status = newstat;
+
+       return 0;
+}
+
+/*
+ * File ops
+ */
+
+static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd,
+       u_long arg)
+{
+       struct phantom_device *dev = file->private_data;
+       struct phm_regs rs;
+       struct phm_reg r;
+       void __user *argp = (void __user *)arg;
+       unsigned int i;
+
+       if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
+                       _IOC_NR(cmd) > PH_IOC_MAXNR)
+               return -ENOTTY;
+
+       switch (cmd) {
+       case PHN_SET_REG:
+               if (copy_from_user(&r, argp, sizeof(r)))
+                       return -EFAULT;
+
+               if (r.reg > 7)
+                       return -EINVAL;
+
+               if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
+                               phantom_status(dev, dev->status | PHB_RUNNING))
+                       return -ENODEV;
+
+               pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
+               iowrite32(r.value, dev->iaddr + r.reg);
+
+               if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
+                       phantom_status(dev, dev->status & ~PHB_RUNNING);
+               break;
+       case PHN_SET_REGS:
+               if (copy_from_user(&rs, argp, sizeof(rs)))
+                       return -EFAULT;
+
+               pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
+               for (i = 0; i < min(rs.count, 8U); i++)
+                       if ((1 << i) & rs.mask)
+                               iowrite32(rs.values[i], dev->oaddr + i);
+               break;
+       case PHN_GET_REG:
+               if (copy_from_user(&r, argp, sizeof(r)))
+                       return -EFAULT;
+
+               if (r.reg > 7)
+                       return -EINVAL;
+
+               r.value = ioread32(dev->iaddr + r.reg);
+
+               if (copy_to_user(argp, &r, sizeof(r)))
+                       return -EFAULT;
+               break;
+       case PHN_GET_REGS:
+               if (copy_from_user(&rs, argp, sizeof(rs)))
+                       return -EFAULT;
+
+               pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
+               for (i = 0; i < min(rs.count, 8U); i++)
+                       if ((1 << i) & rs.mask)
+                               rs.values[i] = ioread32(dev->iaddr + i);
+
+               if (copy_to_user(argp, &rs, sizeof(rs)))
+                       return -EFAULT;
+               break;
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static int phantom_open(struct inode *inode, struct file *file)
+{
+       struct phantom_device *dev = container_of(inode->i_cdev,
+                       struct phantom_device, cdev);
+
+       nonseekable_open(inode, file);
+
+       if (mutex_lock_interruptible(&dev->open_lock))
+               return -ERESTARTSYS;
+
+       if (dev->opened) {
+               mutex_unlock(&dev->open_lock);
+               return -EINVAL;
+       }
+
+       file->private_data = dev;
+
+       dev->opened++;
+       mutex_unlock(&dev->open_lock);
+
+       return 0;
+}
+
+static int phantom_release(struct inode *inode, struct file *file)
+{
+       struct phantom_device *dev = file->private_data;
+
+       mutex_lock(&dev->open_lock);
+
+       dev->opened = 0;
+       phantom_status(dev, dev->status & ~PHB_RUNNING);
+
+       mutex_unlock(&dev->open_lock);
+
+       return 0;
+}
+
+static unsigned int phantom_poll(struct file *file, poll_table *wait)
+{
+       struct phantom_device *dev = file->private_data;
+       unsigned int mask = 0;
+
+       pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
+       poll_wait(file, &dev->wait, wait);
+       if (atomic_read(&dev->counter)) {
+               mask = POLLIN | POLLRDNORM;
+               atomic_dec(&dev->counter);
+       } else if ((dev->status & PHB_RUNNING) == 0)
+               mask = POLLIN | POLLRDNORM | POLLERR;
+       pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
+
+       return mask;
+}
+
+static struct file_operations phantom_file_ops = {
+       .open = phantom_open,
+       .release = phantom_release,
+       .ioctl = phantom_ioctl,
+       .poll = phantom_poll,
+};
+
+static irqreturn_t phantom_isr(int irq, void *data)
+{
+       struct phantom_device *dev = data;
+
+       if (!(ioread32(dev->iaddr + PHN_CONTROL) & PHN_CTL_IRQ))
+               return IRQ_NONE;
+
+       iowrite32(0, dev->iaddr);
+       iowrite32(0xc0, dev->iaddr);
+
+       atomic_inc(&dev->counter);
+       wake_up_interruptible(&dev->wait);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Init and deinit driver
+ */
+
+static unsigned int __devinit phantom_get_free(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < PHANTOM_MAX_MINORS; i++)
+               if (phantom_devices[i] == 0)
+                       break;
+
+       return i;
+}
+
+static int __devinit phantom_probe(struct pci_dev *pdev,
+       const struct pci_device_id *pci_id)
+{
+       struct phantom_device *pht;
+       unsigned int minor;
+       int retval;
+
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto err;
+
+       minor = phantom_get_free();
+       if (minor == PHANTOM_MAX_MINORS) {
+               dev_err(&pdev->dev, "too many devices found!\n");
+               retval = -EIO;
+               goto err_dis;
+       }
+
+       phantom_devices[minor] = 1;
+
+       retval = pci_request_regions(pdev, "phantom");
+       if (retval)
+               goto err_null;
+
+       retval = -ENOMEM;
+       pht = kzalloc(sizeof(*pht), GFP_KERNEL);
+       if (pht == NULL) {
+               dev_err(&pdev->dev, "unable to allocate device\n");
+               goto err_reg;
+       }
+
+       pht->caddr = pci_iomap(pdev, 0, 0);
+       if (pht->caddr == NULL) {
+               dev_err(&pdev->dev, "can't remap conf space\n");
+               goto err_fr;
+       }
+       pht->iaddr = pci_iomap(pdev, 2, 0);
+       if (pht->iaddr == NULL) {
+               dev_err(&pdev->dev, "can't remap input space\n");
+               goto err_unmc;
+       }
+       pht->oaddr = pci_iomap(pdev, 3, 0);
+       if (pht->oaddr == NULL) {
+               dev_err(&pdev->dev, "can't remap output space\n");
+               goto err_unmi;
+       }
+
+       mutex_init(&pht->open_lock);
+       init_waitqueue_head(&pht->wait);
+       cdev_init(&pht->cdev, &phantom_file_ops);
+       pht->cdev.owner = THIS_MODULE;
+
+       iowrite32(0, pht->caddr + PHN_IRQCTL);
+       retval = request_irq(pdev->irq, phantom_isr,
+                       IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
+       if (retval) {
+               dev_err(&pdev->dev, "can't establish ISR\n");
+               goto err_unmo;
+       }
+
+       retval = cdev_add(&pht->cdev, MKDEV(phantom_major, minor), 1);
+       if (retval) {
+               dev_err(&pdev->dev, "chardev registration failed\n");
+               goto err_irq;
+       }
+
+       if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
+                       minor), "phantom%u", minor)))
+               dev_err(&pdev->dev, "can't create device\n");
+
+       pci_set_drvdata(pdev, pht);
+
+       return 0;
+err_irq:
+       free_irq(pdev->irq, pht);
+err_unmo:
+       pci_iounmap(pdev, pht->oaddr);
+err_unmi:
+       pci_iounmap(pdev, pht->iaddr);
+err_unmc:
+       pci_iounmap(pdev, pht->caddr);
+err_fr:
+       kfree(pht);
+err_reg:
+       pci_release_regions(pdev);
+err_null:
+       phantom_devices[minor] = 0;
+err_dis:
+       pci_disable_device(pdev);
+err:
+       return retval;
+}
+
+static void __devexit phantom_remove(struct pci_dev *pdev)
+{
+       struct phantom_device *pht = pci_get_drvdata(pdev);
+       unsigned int minor = MINOR(pht->cdev.dev);
+
+       device_destroy(phantom_class, MKDEV(phantom_major, minor));
+
+       cdev_del(&pht->cdev);
+
+       iowrite32(0, pht->caddr + PHN_IRQCTL);
+       free_irq(pdev->irq, pht);
+
+       pci_iounmap(pdev, pht->oaddr);
+       pci_iounmap(pdev, pht->iaddr);
+       pci_iounmap(pdev, pht->caddr);
+
+       kfree(pht);
+
+       pci_release_regions(pdev);
+
+       phantom_devices[minor] = 0;
+
+       pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct phantom_device *dev = pci_get_drvdata(pdev);
+
+       iowrite32(0, dev->caddr + PHN_IRQCTL);
+
+       return 0;
+}
+
+static int phantom_resume(struct pci_dev *pdev)
+{
+       struct phantom_device *dev = pci_get_drvdata(pdev);
+
+       iowrite32(0, dev->caddr + PHN_IRQCTL);
+
+       return 0;
+}
+#else
+#define phantom_suspend        NULL
+#define phantom_resume NULL
+#endif
+
+static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
+       { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
+               .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
+
+static struct pci_driver phantom_pci_driver = {
+       .name = "phantom",
+       .id_table = phantom_pci_tbl,
+       .probe = phantom_probe,
+       .remove = __devexit_p(phantom_remove),
+       .suspend = phantom_suspend,
+       .resume = phantom_resume
+};
+
+static ssize_t phantom_show_version(struct class *cls, char *buf)
+{
+       return sprintf(buf, PHANTOM_VERSION "\n");
+}
+
+static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
+
+static int __init phantom_init(void)
+{
+       int retval;
+       dev_t dev;
+
+       phantom_class = class_create(THIS_MODULE, "phantom");
+       if (IS_ERR(phantom_class)) {
+               retval = PTR_ERR(phantom_class);
+               printk(KERN_ERR "phantom: can't register phantom class\n");
+               goto err;
+       }
+       retval = class_create_file(phantom_class, &class_attr_version);
+       if (retval) {
+               printk(KERN_ERR "phantom: can't create sysfs version file\n");
+               goto err_class;
+       }
+
+       retval = alloc_chrdev_region(&dev, 0, PHANTOM_MAX_MINORS, "phantom");
+       if (retval) {
+               printk(KERN_ERR "phantom: can't register character device\n");
+               goto err_attr;
+       }
+       phantom_major = MAJOR(dev);
+
+       retval = pci_register_driver(&phantom_pci_driver);
+       if (retval) {
+               printk(KERN_ERR "phantom: can't register pci driver\n");
+               goto err_unchr;
+       }
+
+       printk(KERN_INFO "Phantom Linux Driver, version " PHANTOM_VERSION ", "
+                       "init OK\n");
+
+       return 0;
+err_unchr:
+       unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
+err_attr:
+       class_remove_file(phantom_class, &class_attr_version);
+err_class:
+       class_destroy(phantom_class);
+err:
+       return retval;
+}
+
+static void __exit phantom_exit(void)
+{
+       pci_unregister_driver(&phantom_pci_driver);
+
+       unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
+
+       class_remove_file(phantom_class, &class_attr_version);
+       class_destroy(phantom_class);
+
+       pr_debug("phantom: module successfully removed\n");
+}
+
+module_init(phantom_init);
+module_exit(phantom_exit);
+
+MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
+MODULE_DESCRIPTION("Sensable Phantom driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PHANTOM_VERSION);
index 1ba6c085419a243fb3afcbf59acf092a90559d05..c08ad8f823d233657b9f076f8aee62b4135e0e3b 100644 (file)
@@ -105,7 +105,8 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
            == TIFM_TYPE_XD)
                msleep(40);
 
-       writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
+       writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00,
+              sock_addr + SOCK_CONTROL);
        /* wait for power to stabilize */
        msleep(20);
        for (cnt = 16; cnt <= 256; cnt <<= 1) {
@@ -122,6 +123,12 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
        return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
 }
 
+inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr)
+{
+       writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL),
+              sock_addr + SOCK_CONTROL);
+}
+
 inline static char __iomem *
 tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
 {
@@ -133,6 +140,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work)
        struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
                                               media_switcher);
        struct tifm_dev *sock;
+       char __iomem *sock_addr;
        unsigned long flags;
        unsigned char media_id;
        unsigned int socket_change_set, cnt;
@@ -158,11 +166,12 @@ static void tifm_7xx1_switch_media(struct work_struct *work)
                               "%s : demand removing card from socket %u:%u\n",
                               fm->cdev.class_id, fm->id, cnt);
                        fm->sockets[cnt] = NULL;
+                       sock_addr = sock->addr;
                        spin_unlock_irqrestore(&fm->lock, flags);
                        device_unregister(&sock->dev);
                        spin_lock_irqsave(&fm->lock, flags);
-                       writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt)
-                              + SOCK_CONTROL);
+                       tifm_7xx1_sock_power_off(sock_addr);
+                       writel(0x0e00, sock_addr + SOCK_CONTROL);
                }
 
                spin_unlock_irqrestore(&fm->lock, flags);
@@ -205,8 +214,16 @@ static void tifm_7xx1_switch_media(struct work_struct *work)
 
 static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
 {
+       struct tifm_adapter *fm = pci_get_drvdata(dev);
+       int cnt;
+
        dev_dbg(&dev->dev, "suspending host\n");
 
+       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+               if (fm->sockets[cnt])
+                       tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr);
+       }
+
        pci_save_state(dev);
        pci_enable_wake(dev, pci_choose_state(dev, state), 0);
        pci_disable_device(dev);
@@ -357,6 +374,7 @@ err_out:
 static void tifm_7xx1_remove(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
+       int cnt;
 
        fm->eject = tifm_7xx1_dummy_eject;
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
@@ -365,6 +383,9 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
 
        tifm_remove_adapter(fm);
 
+       for (cnt = 0; cnt < fm->num_sockets; cnt++)
+               tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
+
        pci_set_drvdata(dev, NULL);
 
        iounmap(fm->addr);
index 6c97491543dbd80949eb89914c5c23f90f31fe16..45b7d53b949c00f9ff187bb24215145cc2abd7a6 100644 (file)
@@ -2,10 +2,8 @@
 # MMC subsystem configuration
 #
 
-menu "MMC/SD Card support"
-
-config MMC
-       tristate "MMC support"
+menuconfig MMC
+       tristate "MMC/SD card support"
        help
          MMC is the "multi-media card" bus protocol.
 
@@ -19,10 +17,12 @@ config MMC_DEBUG
          This is an option for use by developers; most people should
          say N here.  This enables MMC core and driver debugging.
 
+if MMC
+
 source "drivers/mmc/core/Kconfig"
 
 source "drivers/mmc/card/Kconfig"
 
 source "drivers/mmc/host/Kconfig"
 
-endmenu
+endif # MMC
index 01a9fd376a1f15ac9e5e6715722356a7789961f8..9320a8c73239ceff909e30a045bb06aec60bd5ee 100644 (file)
@@ -3,11 +3,10 @@
 #
 
 comment "MMC/SD Card Drivers"
-       depends MMC
 
 config MMC_BLOCK
        tristate "MMC block device driver"
-       depends on MMC && BLOCK
+       depends on BLOCK
        default y
        help
          Say Y here to enable the MMC block device driver support.
index 94222b9a15ea4668e32cad6ca67a72661e49a947..ab37a6d9d32a046d7318b3a89a6358c8456b5ef9 100644 (file)
@@ -4,7 +4,6 @@
 
 config MMC_UNSAFE_RESUME
        bool "Allow unsafe resume (DANGEROUS)"
-       depends on MMC != n
        help
          If you say Y here, the MMC layer will assume that all cards
          stayed in their respective slots during the suspend. The
index 72c7cf4a9f9dbdc6683999b28f9c7e86eda2e0fb..7385acfa1dd939a29e77fc414f89be7b47bed576 100644 (file)
@@ -500,9 +500,10 @@ void __mmc_release_bus(struct mmc_host *host)
 void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
 #ifdef CONFIG_MMC_DEBUG
-       mmc_claim_host(host);
+       unsigned long flags;
+       spin_lock_irqsave(&host->lock, flags);
        BUG_ON(host->removed);
-       mmc_release_host(host);
+       spin_unlock_irqrestore(&host->lock, flags);
 #endif
 
        mmc_schedule_delayed_work(&host->detect, delay);
@@ -625,9 +626,10 @@ EXPORT_SYMBOL(mmc_add_host);
 void mmc_remove_host(struct mmc_host *host)
 {
 #ifdef CONFIG_MMC_DEBUG
-       mmc_claim_host(host);
+       unsigned long flags;
+       spin_lock_irqsave(&host->lock, flags);
        host->removed = 1;
-       mmc_release_host(host);
+       spin_unlock_irqrestore(&host->lock, flags);
 #endif
 
        mmc_flush_scheduled_work();
index ed4deab2203d26382500a3da8528e60e97245d8d..e23082fe88d0ddebac4921b54631fb75bed935e0 100644 (file)
@@ -3,11 +3,10 @@
 #
 
 comment "MMC/SD Host Controller Drivers"
-       depends on MMC
 
 config MMC_ARMMMCI
        tristate "ARM AMBA Multimedia Card Interface support"
-       depends on ARM_AMBA && MMC
+       depends on ARM_AMBA
        help
          This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
          Interface (PL180 and PL181) support.  If you have an ARM(R)
@@ -17,7 +16,7 @@ config MMC_ARMMMCI
 
 config MMC_PXA
        tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
-       depends on ARCH_PXA && MMC
+       depends on ARCH_PXA
        help
          This selects the Intel(R) PXA(R) Multimedia card Interface.
          If you have a PXA(R) platform with a Multimedia Card slot,
@@ -27,7 +26,7 @@ config MMC_PXA
 
 config MMC_SDHCI
        tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-       depends on PCI && MMC && EXPERIMENTAL
+       depends on PCI && EXPERIMENTAL
        help
          This select the generic Secure Digital Host Controller Interface.
          It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -38,7 +37,7 @@ config MMC_SDHCI
 
 config MMC_OMAP
        tristate "TI OMAP Multimedia Card Interface support"
-       depends on ARCH_OMAP && MMC
+       depends on ARCH_OMAP
        select TPS65010 if MACH_OMAP_H2
        help
          This selects the TI OMAP Multimedia card Interface.
@@ -49,7 +48,7 @@ config MMC_OMAP
 
 config MMC_WBSD
        tristate "Winbond W83L51xD SD/MMC Card Interface support"
-       depends on MMC && ISA_DMA_API
+       depends on ISA_DMA_API
        help
          This selects the Winbond(R) W83L51xD Secure digital and
           Multimedia card Interface.
@@ -60,7 +59,7 @@ config MMC_WBSD
 
 config MMC_AU1X
        tristate "Alchemy AU1XX0 MMC Card Interface support"
-       depends on MMC && SOC_AU1200
+       depends on SOC_AU1200
        help
          This selects the AMD Alchemy(R) Multimedia card interface.
          If you have a Alchemy platform with a MMC slot, say Y or M here.
@@ -69,7 +68,7 @@ config MMC_AU1X
 
 config MMC_AT91
        tristate "AT91 SD/MMC Card Interface support"
-       depends on ARCH_AT91 && MMC
+       depends on ARCH_AT91
        help
          This selects the AT91 MCI controller.
 
@@ -77,7 +76,7 @@ config MMC_AT91
 
 config MMC_IMX
        tristate "Motorola i.MX Multimedia Card Interface support"
-       depends on ARCH_IMX && MMC
+       depends on ARCH_IMX
        help
          This selects the Motorola i.MX Multimedia card Interface.
          If you have a i.MX platform with a Multimedia Card slot,
@@ -87,7 +86,7 @@ config MMC_IMX
 
 config MMC_TIFM_SD
        tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-       depends on MMC && EXPERIMENTAL && PCI
+       depends on EXPERIMENTAL && PCI
        select TIFM_CORE
        help
          Say Y here if you want to be able to access MMC/SD cards with
index 7511f961c67b78351754f9a07b24ba04fb81d9ec..8b736e9684477236604e54932f1cf788a90db858 100644 (file)
@@ -1021,10 +1021,6 @@ static void tifm_sd_remove(struct tifm_dev *sock)
        mmc_remove_host(mmc);
        dev_dbg(&sock->dev, "after remove\n");
 
-       /* The meaning of the bit majority in this constant is unknown. */
-       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-
        mmc_free_host(mmc);
 }
 
@@ -1032,14 +1028,7 @@ static void tifm_sd_remove(struct tifm_dev *sock)
 
 static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
 {
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       int rc;
-
-       rc = mmc_suspend_host(mmc, state);
-       /* The meaning of the bit majority in this constant is unknown. */
-       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-       return rc;
+       return mmc_suspend_host(tifm_get_drvdata(sock), state);
 }
 
 static int tifm_sd_resume(struct tifm_dev *sock)
index d28e0fc85e12c2e0bad8810551b1a3a8a4cffd42..479d32b57a1eb54b20b731855274bd9d343a62ae 100644 (file)
@@ -1,5 +1,4 @@
 # drivers/mtd/chips/Kconfig
-# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $
 
 menu "RAM/ROM/Flash chip drivers"
        depends on MTD!=n
@@ -231,45 +230,6 @@ config MTD_ABSENT
          the system regardless of media presence.  Device nodes created
          with this driver will return -ENODEV upon access.
 
-config MTD_OBSOLETE_CHIPS
-       bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
-       help
-         This option does not enable any code directly, but will allow you to
-         select some other chip drivers which are now considered obsolete,
-         because the generic CONFIG_JEDECPROBE code above should now detect
-         the chips which are supported by these drivers, and allow the generic
-         CFI-compatible drivers to drive the chips. Say 'N' here unless you have
-         already tried the CONFIG_JEDECPROBE method and reported its failure
-         to the MTD mailing list at <linux-mtd@lists.infradead.org>
-
-config MTD_AMDSTD
-       tristate "AMD compatible flash chip support (non-CFI)"
-       depends on MTD_OBSOLETE_CHIPS && BROKEN
-       help
-         This option enables support for flash chips using AMD-compatible
-         commands, including some which are not CFI-compatible and hence
-         cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
-
-         It also works on AMD compatible chips that do conform to CFI.
-
-config MTD_SHARP
-       tristate "pre-CFI Sharp chip support"
-       depends on MTD_OBSOLETE_CHIPS
-       help
-         This option enables support for flash chips using Sharp-compatible
-         commands, including some which are not CFI-compatible and hence
-         cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
-
-config MTD_JEDEC
-       tristate "JEDEC device support"
-       depends on MTD_OBSOLETE_CHIPS && BROKEN
-       help
-         Enable older JEDEC flash interface devices for self
-         programming flash.  It is commonly used in older AMD chips.  It is
-         only called JEDEC because the JEDEC association
-         <http://www.jedec.org/> distributes the identification codes for the
-         chips.
-
 config MTD_XIP
        bool "XIP aware MTD support"
        depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
index 75bc1c2a0f431b9954447921f03b7246ed2fb395..36582412ccdaeb2c2aea2c0752f8b62e51554154 100644 (file)
@@ -1,19 +1,15 @@
 #
 # linux/drivers/chips/Makefile
 #
-# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
 
 obj-$(CONFIG_MTD)              += chipreg.o
-obj-$(CONFIG_MTD_AMDSTD)       += amd_flash.o
 obj-$(CONFIG_MTD_CFI)          += cfi_probe.o
 obj-$(CONFIG_MTD_CFI_UTIL)     += cfi_util.o
 obj-$(CONFIG_MTD_CFI_STAA)     += cfi_cmdset_0020.o
 obj-$(CONFIG_MTD_CFI_AMDSTD)   += cfi_cmdset_0002.o
 obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
 obj-$(CONFIG_MTD_GEN_PROBE)    += gen_probe.o
-obj-$(CONFIG_MTD_JEDEC)                += jedec.o
 obj-$(CONFIG_MTD_JEDECPROBE)   += jedec_probe.o
 obj-$(CONFIG_MTD_RAM)          += map_ram.o
 obj-$(CONFIG_MTD_ROM)          += map_rom.o
-obj-$(CONFIG_MTD_SHARP)                += sharp.o
 obj-$(CONFIG_MTD_ABSENT)       += map_absent.o
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
deleted file mode 100644 (file)
index e7999f1..0000000
+++ /dev/null
@@ -1,1396 +0,0 @@
-/*
- * MTD map driver for AMD compatible flash chips (non-CFI)
- *
- * Author: Jonas Holmberg <jonas.holmberg@axis.com>
- *
- * $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * This file is under GPL.
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/flashchip.h>
-
-/* There's no limit. It exists only to avoid realloc. */
-#define MAX_AMD_CHIPS 8
-
-#define DEVICE_TYPE_X8 (8 / 8)
-#define DEVICE_TYPE_X16        (16 / 8)
-#define DEVICE_TYPE_X32        (32 / 8)
-
-/* Addresses */
-#define ADDR_MANUFACTURER              0x0000
-#define ADDR_DEVICE_ID                 0x0001
-#define ADDR_SECTOR_LOCK               0x0002
-#define ADDR_HANDSHAKE                 0x0003
-#define ADDR_UNLOCK_1                  0x0555
-#define ADDR_UNLOCK_2                  0x02AA
-
-/* Commands */
-#define CMD_UNLOCK_DATA_1              0x00AA
-#define CMD_UNLOCK_DATA_2              0x0055
-#define CMD_MANUFACTURER_UNLOCK_DATA   0x0090
-#define CMD_UNLOCK_BYPASS_MODE         0x0020
-#define CMD_PROGRAM_UNLOCK_DATA                0x00A0
-#define CMD_RESET_DATA                 0x00F0
-#define CMD_SECTOR_ERASE_UNLOCK_DATA   0x0080
-#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x0030
-
-#define CMD_UNLOCK_SECTOR              0x0060
-
-/* Manufacturers */
-#define MANUFACTURER_AMD       0x0001
-#define MANUFACTURER_ATMEL     0x001F
-#define MANUFACTURER_FUJITSU   0x0004
-#define MANUFACTURER_ST                0x0020
-#define MANUFACTURER_SST       0x00BF
-#define MANUFACTURER_TOSHIBA   0x0098
-
-/* AMD */
-#define AM29F800BB     0x2258
-#define AM29F800BT     0x22D6
-#define AM29LV800BB    0x225B
-#define AM29LV800BT    0x22DA
-#define AM29LV160DT    0x22C4
-#define AM29LV160DB    0x2249
-#define AM29BDS323D     0x22D1
-
-/* Atmel */
-#define AT49xV16x      0x00C0
-#define AT49xV16xT     0x00C2
-
-/* Fujitsu */
-#define MBM29LV160TE   0x22C4
-#define MBM29LV160BE   0x2249
-#define MBM29LV800BB   0x225B
-
-/* ST - www.st.com */
-#define M29W800T       0x00D7
-#define M29W160DT      0x22C4
-#define M29W160DB      0x2249
-
-/* SST */
-#define SST39LF800     0x2781
-#define SST39LF160     0x2782
-
-/* Toshiba */
-#define TC58FVT160     0x00C2
-#define TC58FVB160     0x0043
-
-#define D6_MASK        0x40
-
-struct amd_flash_private {
-       int device_type;
-       int interleave;
-       int numchips;
-       unsigned long chipshift;
-       struct flchip chips[0];
-};
-
-struct amd_flash_info {
-       const __u16 mfr_id;
-       const __u16 dev_id;
-       const char *name;
-       const u_long size;
-       const int numeraseregions;
-       const struct mtd_erase_region_info regions[4];
-};
-
-
-
-static int amd_flash_read(struct mtd_info *, loff_t, size_t, size_t *,
-                         u_char *);
-static int amd_flash_write(struct mtd_info *, loff_t, size_t, size_t *,
-                          const u_char *);
-static int amd_flash_erase(struct mtd_info *, struct erase_info *);
-static void amd_flash_sync(struct mtd_info *);
-static int amd_flash_suspend(struct mtd_info *);
-static void amd_flash_resume(struct mtd_info *);
-static void amd_flash_destroy(struct mtd_info *);
-static struct mtd_info *amd_flash_probe(struct map_info *map);
-
-
-static struct mtd_chip_driver amd_flash_chipdrv = {
-       .probe = amd_flash_probe,
-       .destroy = amd_flash_destroy,
-       .name = "amd_flash",
-       .module = THIS_MODULE
-};
-
-static inline __u32 wide_read(struct map_info *map, __u32 addr)
-{
-       if (map->buswidth == 1) {
-               return map_read8(map, addr);
-       } else if (map->buswidth == 2) {
-               return map_read16(map, addr);
-       } else if (map->buswidth == 4) {
-               return map_read32(map, addr);
-        }
-
-       return 0;
-}
-
-static inline void wide_write(struct map_info *map, __u32 val, __u32 addr)
-{
-       if (map->buswidth == 1) {
-               map_write8(map, val, addr);
-       } else if (map->buswidth == 2) {
-               map_write16(map, val, addr);
-       } else if (map->buswidth == 4) {
-               map_write32(map, val, addr);
-       }
-}
-
-static inline __u32 make_cmd(struct map_info *map, __u32 cmd)
-{
-       const struct amd_flash_private *private = map->fldrv_priv;
-       if ((private->interleave == 2) &&
-           (private->device_type == DEVICE_TYPE_X16)) {
-               cmd |= (cmd << 16);
-       }
-
-       return cmd;
-}
-
-static inline void send_unlock(struct map_info *map, unsigned long base)
-{
-       wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1,
-                  base + (map->buswidth * ADDR_UNLOCK_1));
-       wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2,
-                  base + (map->buswidth * ADDR_UNLOCK_2));
-}
-
-static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd)
-{
-       send_unlock(map, base);
-       wide_write(map, make_cmd(map, cmd),
-                  base + (map->buswidth * ADDR_UNLOCK_1));
-}
-
-static inline void send_cmd_to_addr(struct map_info *map, unsigned long base,
-                                   __u32 cmd, unsigned long addr)
-{
-       send_unlock(map, base);
-       wide_write(map, make_cmd(map, cmd), addr);
-}
-
-static inline int flash_is_busy(struct map_info *map, unsigned long addr,
-                               int interleave)
-{
-
-       if ((interleave == 2) && (map->buswidth == 4)) {
-               __u32 read1, read2;
-
-               read1 = wide_read(map, addr);
-               read2 = wide_read(map, addr);
-
-               return (((read1 >> 16) & D6_MASK) !=
-                       ((read2 >> 16) & D6_MASK)) ||
-                      (((read1 & 0xffff) & D6_MASK) !=
-                       ((read2 & 0xffff) & D6_MASK));
-       }
-
-       return ((wide_read(map, addr) & D6_MASK) !=
-               (wide_read(map, addr) & D6_MASK));
-}
-
-static inline void unlock_sector(struct map_info *map, unsigned long sect_addr,
-                                int unlock)
-{
-       /* Sector lock address. A6 = 1 for unlock, A6 = 0 for lock */
-       int SLA = unlock ?
-               (sect_addr |  (0x40 * map->buswidth)) :
-               (sect_addr & ~(0x40 * map->buswidth)) ;
-
-       __u32 cmd = make_cmd(map, CMD_UNLOCK_SECTOR);
-
-       wide_write(map, make_cmd(map, CMD_RESET_DATA), 0);
-       wide_write(map, cmd, SLA); /* 1st cycle: write cmd to any address */
-       wide_write(map, cmd, SLA); /* 2nd cycle: write cmd to any address */
-       wide_write(map, cmd, SLA); /* 3rd cycle: write cmd to SLA */
-}
-
-static inline int is_sector_locked(struct map_info *map,
-                                  unsigned long sect_addr)
-{
-       int status;
-
-       wide_write(map, CMD_RESET_DATA, 0);
-       send_cmd(map, sect_addr, CMD_MANUFACTURER_UNLOCK_DATA);
-
-       /* status is 0x0000 for unlocked and 0x0001 for locked */
-       status = wide_read(map, sect_addr + (map->buswidth * ADDR_SECTOR_LOCK));
-       wide_write(map, CMD_RESET_DATA, 0);
-       return status;
-}
-
-static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len,
-                              int is_unlock)
-{
-       struct map_info *map;
-       struct mtd_erase_region_info *merip;
-       int eraseoffset, erasesize, eraseblocks;
-       int i;
-       int retval = 0;
-       int lock_status;
-
-       map = mtd->priv;
-
-       /* Pass the whole chip through sector by sector and check for each
-          sector if the sector and the given interval overlap */
-       for(i = 0; i < mtd->numeraseregions; i++) {
-               merip = &mtd->eraseregions[i];
-
-               eraseoffset = merip->offset;
-               erasesize = merip->erasesize;
-               eraseblocks = merip->numblocks;
-
-               if (ofs > eraseoffset + erasesize)
-                       continue;
-
-               while (eraseblocks > 0) {
-                       if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) {
-                               unlock_sector(map, eraseoffset, is_unlock);
-
-                               lock_status = is_sector_locked(map, eraseoffset);
-
-                               if (is_unlock && lock_status) {
-                                       printk("Cannot unlock sector at address %x length %xx\n",
-                                              eraseoffset, merip->erasesize);
-                                       retval = -1;
-                               } else if (!is_unlock && !lock_status) {
-                                       printk("Cannot lock sector at address %x length %x\n",
-                                              eraseoffset, merip->erasesize);
-                                       retval = -1;
-                               }
-                       }
-                       eraseoffset += erasesize;
-                       eraseblocks --;
-               }
-       }
-       return retval;
-}
-
-static int amd_flash_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-       return amd_flash_do_unlock(mtd, ofs, len, 1);
-}
-
-static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-       return amd_flash_do_unlock(mtd, ofs, len, 0);
-}
-
-
-/*
- * Reads JEDEC manufacturer ID and device ID and returns the index of the first
- * matching table entry (-1 if not found or alias for already found chip).
- */
-static int probe_new_chip(struct mtd_info *mtd, __u32 base,
-                         struct flchip *chips,
-                         struct amd_flash_private *private,
-                         const struct amd_flash_info *table, int table_size)
-{
-       __u32 mfr_id;
-       __u32 dev_id;
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private temp;
-       int i;
-
-       temp.device_type = DEVICE_TYPE_X16;     // Assume X16 (FIXME)
-       temp.interleave = 2;
-       map->fldrv_priv = &temp;
-
-       /* Enter autoselect mode. */
-       send_cmd(map, base, CMD_RESET_DATA);
-       send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA);
-
-       mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER));
-       dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID));
-
-       if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) &&
-           ((dev_id >> 16) == (dev_id & 0xffff))) {
-               mfr_id &= 0xffff;
-               dev_id &= 0xffff;
-       } else {
-               temp.interleave = 1;
-       }
-
-       for (i = 0; i < table_size; i++) {
-               if ((mfr_id == table[i].mfr_id) &&
-                   (dev_id == table[i].dev_id)) {
-                       if (chips) {
-                               int j;
-
-                               /* Is this an alias for an already found chip?
-                                * In that case that chip should be in
-                                * autoselect mode now.
-                                */
-                               for (j = 0; j < private->numchips; j++) {
-                                       __u32 mfr_id_other;
-                                       __u32 dev_id_other;
-
-                                       mfr_id_other =
-                                               wide_read(map, chips[j].start +
-                                                              (map->buswidth *
-                                                               ADDR_MANUFACTURER
-                                                              ));
-                                       dev_id_other =
-                                               wide_read(map, chips[j].start +
-                                                              (map->buswidth *
-                                                               ADDR_DEVICE_ID));
-                                       if (temp.interleave == 2) {
-                                               mfr_id_other &= 0xffff;
-                                               dev_id_other &= 0xffff;
-                                       }
-                                       if ((mfr_id_other == mfr_id) &&
-                                           (dev_id_other == dev_id)) {
-
-                                               /* Exit autoselect mode. */
-                                               send_cmd(map, base,
-                                                        CMD_RESET_DATA);
-
-                                               return -1;
-                                       }
-                               }
-
-                               if (private->numchips == MAX_AMD_CHIPS) {
-                                       printk(KERN_WARNING
-                                              "%s: Too many flash chips "
-                                              "detected. Increase "
-                                              "MAX_AMD_CHIPS from %d.\n",
-                                              map->name, MAX_AMD_CHIPS);
-
-                                       return -1;
-                               }
-
-                               chips[private->numchips].start = base;
-                               chips[private->numchips].state = FL_READY;
-                               chips[private->numchips].mutex =
-                                       &chips[private->numchips]._spinlock;
-                               private->numchips++;
-                       }
-
-                       printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name,
-                              temp.interleave, (table[i].size)/(1024*1024),
-                              table[i].name, base);
-
-                       mtd->size += table[i].size * temp.interleave;
-                       mtd->numeraseregions += table[i].numeraseregions;
-
-                       break;
-               }
-       }
-
-       /* Exit autoselect mode. */
-       send_cmd(map, base, CMD_RESET_DATA);
-
-       if (i == table_size) {
-               printk(KERN_DEBUG "%s: unknown flash device at 0x%x, "
-                      "mfr id 0x%x, dev id 0x%x\n", map->name,
-                      base, mfr_id, dev_id);
-               map->fldrv_priv = NULL;
-
-               return -1;
-       }
-
-       private->device_type = temp.device_type;
-       private->interleave = temp.interleave;
-
-       return i;
-}
-
-
-
-static struct mtd_info *amd_flash_probe(struct map_info *map)
-{
-       static const struct amd_flash_info table[] = {
-       {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29LV160DT,
-               .name = "AMD AM29LV160DT",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-                       { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29LV160DB,
-               .name = "AMD AM29LV160DB",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_TOSHIBA,
-               .dev_id = TC58FVT160,
-               .name = "Toshiba TC58FVT160",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-                       { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_FUJITSU,
-               .dev_id = MBM29LV160TE,
-               .name = "Fujitsu MBM29LV160TE",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-                       { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_TOSHIBA,
-               .dev_id = TC58FVB160,
-               .name = "Toshiba TC58FVB160",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_FUJITSU,
-               .dev_id = MBM29LV160BE,
-               .name = "Fujitsu MBM29LV160BE",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29LV800BB,
-               .name = "AMD AM29LV800BB",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29F800BB,
-               .name = "AMD AM29F800BB",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29LV800BT,
-               .name = "AMD AM29LV800BT",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-                       { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29F800BT,
-               .name = "AMD AM29F800BT",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-                       { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29LV800BB,
-               .name = "AMD AM29LV800BB",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-                       { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_FUJITSU,
-               .dev_id = MBM29LV800BB,
-               .name = "Fujitsu MBM29LV800BB",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_ST,
-               .dev_id = M29W800T,
-               .name = "ST M29W800T",
-               .size = 0x00100000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-                       { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_ST,
-               .dev_id = M29W160DT,
-               .name = "ST M29W160DT",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-                       { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_ST,
-               .dev_id = M29W160DB,
-               .name = "ST M29W160DB",
-               .size = 0x00200000,
-               .numeraseregions = 4,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-                       { .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-                       { .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29BDS323D,
-               .name = "AMD AM29BDS323D",
-               .size = 0x00400000,
-               .numeraseregions = 3,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 },
-                       { .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 },
-                       { .offset = 0x3f0000, .erasesize = 0x02000, .numblocks =  8 },
-               }
-       }, {
-               .mfr_id = MANUFACTURER_ATMEL,
-               .dev_id = AT49xV16x,
-               .name = "Atmel AT49xV16x",
-               .size = 0x00200000,
-               .numeraseregions = 2,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x02000, .numblocks =  8 },
-                       { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-               }
-       }, {
-               .mfr_id = MANUFACTURER_ATMEL,
-               .dev_id = AT49xV16xT,
-               .name = "Atmel AT49xV16xT",
-               .size = 0x00200000,
-               .numeraseregions = 2,
-               .regions = {
-                       { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-                       { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks =  8 }
-               }
-       }
-       };
-
-       struct mtd_info *mtd;
-       struct flchip chips[MAX_AMD_CHIPS];
-       int table_pos[MAX_AMD_CHIPS];
-       struct amd_flash_private temp;
-       struct amd_flash_private *private;
-       u_long size;
-       unsigned long base;
-       int i;
-       int reg_idx;
-       int offset;
-
-       mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-       if (!mtd) {
-               printk(KERN_WARNING
-                      "%s: kmalloc failed for info structure\n", map->name);
-               return NULL;
-       }
-       mtd->priv = map;
-
-       memset(&temp, 0, sizeof(temp));
-
-       printk("%s: Probing for AMD compatible flash...\n", map->name);
-
-       if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,
-                                          ARRAY_SIZE(table)))
-           == -1) {
-               printk(KERN_WARNING
-                      "%s: Found no AMD compatible device at location zero\n",
-                      map->name);
-               kfree(mtd);
-
-               return NULL;
-       }
-
-       chips[0].start = 0;
-       chips[0].state = FL_READY;
-       chips[0].mutex = &chips[0]._spinlock;
-       temp.numchips = 1;
-       for (size = mtd->size; size > 1; size >>= 1) {
-               temp.chipshift++;
-       }
-       switch (temp.interleave) {
-               case 2:
-                       temp.chipshift += 1;
-                       break;
-               case 4:
-                       temp.chipshift += 2;
-                       break;
-       }
-
-       /* Find out if there are any more chips in the map. */
-       for (base = (1 << temp.chipshift);
-            base < map->size;
-            base += (1 << temp.chipshift)) {
-               int numchips = temp.numchips;
-               table_pos[numchips] = probe_new_chip(mtd, base, chips,
-                       &temp, table, ARRAY_SIZE(table));
-       }
-
-       mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
-                                   mtd->numeraseregions, GFP_KERNEL);
-       if (!mtd->eraseregions) {
-               printk(KERN_WARNING "%s: Failed to allocate "
-                      "memory for MTD erase region info\n", map->name);
-               kfree(mtd);
-               map->fldrv_priv = NULL;
-               return NULL;
-       }
-
-       reg_idx = 0;
-       offset = 0;
-       for (i = 0; i < temp.numchips; i++) {
-               int dev_size;
-               int j;
-
-               dev_size = 0;
-               for (j = 0; j < table[table_pos[i]].numeraseregions; j++) {
-                       mtd->eraseregions[reg_idx].offset = offset +
-                               (table[table_pos[i]].regions[j].offset *
-                                temp.interleave);
-                       mtd->eraseregions[reg_idx].erasesize =
-                               table[table_pos[i]].regions[j].erasesize *
-                               temp.interleave;
-                       mtd->eraseregions[reg_idx].numblocks =
-                               table[table_pos[i]].regions[j].numblocks;
-                       if (mtd->erasesize <
-                           mtd->eraseregions[reg_idx].erasesize) {
-                               mtd->erasesize =
-                                       mtd->eraseregions[reg_idx].erasesize;
-                       }
-                       dev_size += mtd->eraseregions[reg_idx].erasesize *
-                                   mtd->eraseregions[reg_idx].numblocks;
-                       reg_idx++;
-               }
-               offset += dev_size;
-       }
-       mtd->type = MTD_NORFLASH;
-       mtd->writesize = 1;
-       mtd->flags = MTD_CAP_NORFLASH;
-       mtd->name = map->name;
-       mtd->erase = amd_flash_erase;
-       mtd->read = amd_flash_read;
-       mtd->write = amd_flash_write;
-       mtd->sync = amd_flash_sync;
-       mtd->suspend = amd_flash_suspend;
-       mtd->resume = amd_flash_resume;
-       mtd->lock = amd_flash_lock;
-       mtd->unlock = amd_flash_unlock;
-
-       private = kmalloc(sizeof(*private) + (sizeof(struct flchip) *
-                                             temp.numchips), GFP_KERNEL);
-       if (!private) {
-               printk(KERN_WARNING
-                      "%s: kmalloc failed for private structure\n", map->name);
-               kfree(mtd);
-               map->fldrv_priv = NULL;
-               return NULL;
-       }
-       memcpy(private, &temp, sizeof(temp));
-       memcpy(private->chips, chips,
-              sizeof(struct flchip) * private->numchips);
-       for (i = 0; i < private->numchips; i++) {
-               init_waitqueue_head(&private->chips[i].wq);
-               spin_lock_init(&private->chips[i]._spinlock);
-       }
-
-       map->fldrv_priv = private;
-
-       map->fldrv = &amd_flash_chipdrv;
-
-       __module_get(THIS_MODULE);
-       return mtd;
-}
-
-
-
-static inline int read_one_chip(struct map_info *map, struct flchip *chip,
-                              loff_t adr, size_t len, u_char *buf)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       unsigned long timeo = jiffies + HZ;
-
-retry:
-       spin_lock_bh(chip->mutex);
-
-       if (chip->state != FL_READY){
-               printk(KERN_INFO "%s: waiting for chip to read, state = %d\n",
-                      map->name, chip->state);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               add_wait_queue(&chip->wq, &wait);
-
-               spin_unlock_bh(chip->mutex);
-
-               schedule();
-               remove_wait_queue(&chip->wq, &wait);
-
-               if(signal_pending(current)) {
-                       return -EINTR;
-               }
-
-               timeo = jiffies + HZ;
-
-               goto retry;
-       }
-
-       adr += chip->start;
-
-       chip->state = FL_READY;
-
-       map_copy_from(map, buf, adr, len);
-
-       wake_up(&chip->wq);
-       spin_unlock_bh(chip->mutex);
-
-       return 0;
-}
-
-
-
-static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
-                         size_t *retlen, u_char *buf)
-{
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private *private = map->fldrv_priv;
-       unsigned long ofs;
-       int chipnum;
-       int ret = 0;
-
-       if ((from + len) > mtd->size) {
-               printk(KERN_WARNING "%s: read request past end of device "
-                      "(0x%lx)\n", map->name, (unsigned long)from + len);
-
-               return -EINVAL;
-       }
-
-       /* Offset within the first chip that the first read should start. */
-       chipnum = (from >> private->chipshift);
-       ofs = from - (chipnum <<  private->chipshift);
-
-       *retlen = 0;
-
-       while (len) {
-               unsigned long this_len;
-
-               if (chipnum >= private->numchips) {
-                       break;
-               }
-
-               if ((len + ofs - 1) >> private->chipshift) {
-                       this_len = (1 << private->chipshift) - ofs;
-               } else {
-                       this_len = len;
-               }
-
-               ret = read_one_chip(map, &private->chips[chipnum], ofs,
-                                   this_len, buf);
-               if (ret) {
-                       break;
-               }
-
-               *retlen += this_len;
-               len -= this_len;
-               buf += this_len;
-
-               ofs = 0;
-               chipnum++;
-       }
-
-       return ret;
-}
-
-
-
-static int write_one_word(struct map_info *map, struct flchip *chip,
-                         unsigned long adr, __u32 datum)
-{
-       unsigned long timeo = jiffies + HZ;
-       struct amd_flash_private *private = map->fldrv_priv;
-       DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
-       int times_left;
-
-retry:
-       spin_lock_bh(chip->mutex);
-
-       if (chip->state != FL_READY){
-               printk("%s: waiting for chip to write, state = %d\n",
-                      map->name, chip->state);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               add_wait_queue(&chip->wq, &wait);
-
-               spin_unlock_bh(chip->mutex);
-
-               schedule();
-               remove_wait_queue(&chip->wq, &wait);
-               printk(KERN_INFO "%s: woke up to write\n", map->name);
-               if(signal_pending(current))
-                       return -EINTR;
-
-               timeo = jiffies + HZ;
-
-               goto retry;
-       }
-
-       chip->state = FL_WRITING;
-
-       adr += chip->start;
-       ENABLE_VPP(map);
-       send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA);
-       wide_write(map, datum, adr);
-
-       times_left = 500000;
-       while (times_left-- && flash_is_busy(map, adr, private->interleave)) {
-               if (need_resched()) {
-                       spin_unlock_bh(chip->mutex);
-                       schedule();
-                       spin_lock_bh(chip->mutex);
-               }
-       }
-
-       if (!times_left) {
-               printk(KERN_WARNING "%s: write to 0x%lx timed out!\n",
-                      map->name, adr);
-               ret = -EIO;
-       } else {
-               __u32 verify;
-               if ((verify = wide_read(map, adr)) != datum) {
-                       printk(KERN_WARNING "%s: write to 0x%lx failed. "
-                              "datum = %x, verify = %x\n",
-                              map->name, adr, datum, verify);
-                       ret = -EIO;
-               }
-       }
-
-       DISABLE_VPP(map);
-       chip->state = FL_READY;
-       wake_up(&chip->wq);
-       spin_unlock_bh(chip->mutex);
-
-       return ret;
-}
-
-
-
-static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
-                          size_t *retlen, const u_char *buf)
-{
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private *private = map->fldrv_priv;
-       int ret = 0;
-       int chipnum;
-       unsigned long ofs;
-       unsigned long chipstart;
-
-       *retlen = 0;
-       if (!len) {
-               return 0;
-       }
-
-       chipnum = to >> private->chipshift;
-       ofs = to  - (chipnum << private->chipshift);
-       chipstart = private->chips[chipnum].start;
-
-       /* If it's not bus-aligned, do the first byte write. */
-       if (ofs & (map->buswidth - 1)) {
-               unsigned long bus_ofs = ofs & ~(map->buswidth - 1);
-               int i = ofs - bus_ofs;
-               int n = 0;
-               u_char tmp_buf[4];
-               __u32 datum;
-
-               map_copy_from(map, tmp_buf,
-                              bus_ofs + private->chips[chipnum].start,
-                              map->buswidth);
-               while (len && i < map->buswidth)
-                       tmp_buf[i++] = buf[n++], len--;
-
-               if (map->buswidth == 2) {
-                       datum = *(__u16*)tmp_buf;
-               } else if (map->buswidth == 4) {
-                       datum = *(__u32*)tmp_buf;
-               } else {
-                       return -EINVAL;  /* should never happen, but be safe */
-               }
-
-               ret = write_one_word(map, &private->chips[chipnum], bus_ofs,
-                                    datum);
-               if (ret) {
-                       return ret;
-               }
-
-               ofs += n;
-               buf += n;
-               (*retlen) += n;
-
-               if (ofs >> private->chipshift) {
-                       chipnum++;
-                       ofs = 0;
-                       if (chipnum == private->numchips) {
-                               return 0;
-                       }
-               }
-       }
-
-       /* We are now aligned, write as much as possible. */
-       while(len >= map->buswidth) {
-               __u32 datum;
-
-               if (map->buswidth == 1) {
-                       datum = *(__u8*)buf;
-               } else if (map->buswidth == 2) {
-                       datum = *(__u16*)buf;
-               } else if (map->buswidth == 4) {
-                       datum = *(__u32*)buf;
-               } else {
-                       return -EINVAL;
-               }
-
-               ret = write_one_word(map, &private->chips[chipnum], ofs, datum);
-
-               if (ret) {
-                       return ret;
-               }
-
-               ofs += map->buswidth;
-               buf += map->buswidth;
-               (*retlen) += map->buswidth;
-               len -= map->buswidth;
-
-               if (ofs >> private->chipshift) {
-                       chipnum++;
-                       ofs = 0;
-                       if (chipnum == private->numchips) {
-                               return 0;
-                       }
-                       chipstart = private->chips[chipnum].start;
-               }
-       }
-
-       if (len & (map->buswidth - 1)) {
-               int i = 0, n = 0;
-               u_char tmp_buf[2];
-               __u32 datum;
-
-               map_copy_from(map, tmp_buf,
-                              ofs + private->chips[chipnum].start,
-                              map->buswidth);
-               while (len--) {
-                       tmp_buf[i++] = buf[n++];
-               }
-
-               if (map->buswidth == 2) {
-                       datum = *(__u16*)tmp_buf;
-               } else if (map->buswidth == 4) {
-                       datum = *(__u32*)tmp_buf;
-               } else {
-                       return -EINVAL;  /* should never happen, but be safe */
-               }
-
-               ret = write_one_word(map, &private->chips[chipnum], ofs, datum);
-
-               if (ret) {
-                       return ret;
-               }
-
-               (*retlen) += n;
-       }
-
-       return 0;
-}
-
-
-
-static inline int erase_one_block(struct map_info *map, struct flchip *chip,
-                                 unsigned long adr, u_long size)
-{
-       unsigned long timeo = jiffies + HZ;
-       struct amd_flash_private *private = map->fldrv_priv;
-       DECLARE_WAITQUEUE(wait, current);
-
-retry:
-       spin_lock_bh(chip->mutex);
-
-       if (chip->state != FL_READY){
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               add_wait_queue(&chip->wq, &wait);
-
-               spin_unlock_bh(chip->mutex);
-
-               schedule();
-               remove_wait_queue(&chip->wq, &wait);
-
-               if (signal_pending(current)) {
-                       return -EINTR;
-               }
-
-               timeo = jiffies + HZ;
-
-               goto retry;
-       }
-
-       chip->state = FL_ERASING;
-
-       adr += chip->start;
-       ENABLE_VPP(map);
-       send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA);
-       send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr);
-
-       timeo = jiffies + (HZ * 20);
-
-       spin_unlock_bh(chip->mutex);
-       msleep(1000);
-       spin_lock_bh(chip->mutex);
-
-       while (flash_is_busy(map, adr, private->interleave)) {
-
-               if (chip->state != FL_ERASING) {
-                       /* Someone's suspended the erase. Sleep */
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       add_wait_queue(&chip->wq, &wait);
-
-                       spin_unlock_bh(chip->mutex);
-                       printk(KERN_INFO "%s: erase suspended. Sleeping\n",
-                              map->name);
-                       schedule();
-                       remove_wait_queue(&chip->wq, &wait);
-
-                       if (signal_pending(current)) {
-                               return -EINTR;
-                       }
-
-                       timeo = jiffies + (HZ*2); /* FIXME */
-                       spin_lock_bh(chip->mutex);
-                       continue;
-               }
-
-               /* OK Still waiting */
-               if (time_after(jiffies, timeo)) {
-                       chip->state = FL_READY;
-                       spin_unlock_bh(chip->mutex);
-                       printk(KERN_WARNING "%s: waiting for erase to complete "
-                              "timed out.\n", map->name);
-                       DISABLE_VPP(map);
-
-                       return -EIO;
-               }
-
-               /* Latency issues. Drop the lock, wait a while and retry */
-               spin_unlock_bh(chip->mutex);
-
-               if (need_resched())
-                       schedule();
-               else
-                       udelay(1);
-
-               spin_lock_bh(chip->mutex);
-       }
-
-       /* Verify every single word */
-       {
-               int address;
-               int error = 0;
-               __u8 verify;
-
-               for (address = adr; address < (adr + size); address++) {
-                       if ((verify = map_read8(map, address)) != 0xFF) {
-                               error = 1;
-                               break;
-                       }
-               }
-               if (error) {
-                       chip->state = FL_READY;
-                       spin_unlock_bh(chip->mutex);
-                       printk(KERN_WARNING
-                              "%s: verify error at 0x%x, size %ld.\n",
-                              map->name, address, size);
-                       DISABLE_VPP(map);
-
-                       return -EIO;
-               }
-       }
-
-       DISABLE_VPP(map);
-       chip->state = FL_READY;
-       wake_up(&chip->wq);
-       spin_unlock_bh(chip->mutex);
-
-       return 0;
-}
-
-
-
-static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private *private = map->fldrv_priv;
-       unsigned long adr, len;
-       int chipnum;
-       int ret = 0;
-       int i;
-       int first;
-       struct mtd_erase_region_info *regions = mtd->eraseregions;
-
-       if (instr->addr > mtd->size) {
-               return -EINVAL;
-       }
-
-       if ((instr->len + instr->addr) > mtd->size) {
-               return -EINVAL;
-       }
-
-       /* Check that both start and end of the requested erase are
-        * aligned with the erasesize at the appropriate addresses.
-        */
-
-       i = 0;
-
-        /* Skip all erase regions which are ended before the start of
-           the requested erase. Actually, to save on the calculations,
-           we skip to the first erase region which starts after the
-           start of the requested erase, and then go back one.
-        */
-
-        while ((i < mtd->numeraseregions) &&
-              (instr->addr >= regions[i].offset)) {
-               i++;
-       }
-        i--;
-
-       /* OK, now i is pointing at the erase region in which this
-        * erase request starts. Check the start of the requested
-        * erase range is aligned with the erase size which is in
-        * effect here.
-        */
-
-       if (instr->addr & (regions[i].erasesize-1)) {
-               return -EINVAL;
-       }
-
-       /* Remember the erase region we start on. */
-
-       first = i;
-
-       /* Next, check that the end of the requested erase is aligned
-        * with the erase region at that address.
-        */
-
-       while ((i < mtd->numeraseregions) &&
-              ((instr->addr + instr->len) >= regions[i].offset)) {
-                i++;
-       }
-
-       /* As before, drop back one to point at the region in which
-        * the address actually falls.
-        */
-
-       i--;
-
-       if ((instr->addr + instr->len) & (regions[i].erasesize-1)) {
-                return -EINVAL;
-       }
-
-       chipnum = instr->addr >> private->chipshift;
-       adr = instr->addr - (chipnum << private->chipshift);
-       len = instr->len;
-
-       i = first;
-
-       while (len) {
-               ret = erase_one_block(map, &private->chips[chipnum], adr,
-                                     regions[i].erasesize);
-
-               if (ret) {
-                       return ret;
-               }
-
-               adr += regions[i].erasesize;
-               len -= regions[i].erasesize;
-
-               if ((adr % (1 << private->chipshift)) ==
-                   ((regions[i].offset + (regions[i].erasesize *
-                                          regions[i].numblocks))
-                    % (1 << private->chipshift))) {
-                       i++;
-               }
-
-               if (adr >> private->chipshift) {
-                       adr = 0;
-                       chipnum++;
-                       if (chipnum >= private->numchips) {
-                               break;
-                       }
-               }
-       }
-
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
-       return 0;
-}
-
-
-
-static void amd_flash_sync(struct mtd_info *mtd)
-{
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private *private = map->fldrv_priv;
-       int i;
-       struct flchip *chip;
-       int ret = 0;
-       DECLARE_WAITQUEUE(wait, current);
-
-       for (i = 0; !ret && (i < private->numchips); i++) {
-               chip = &private->chips[i];
-
-       retry:
-               spin_lock_bh(chip->mutex);
-
-               switch(chip->state) {
-               case FL_READY:
-               case FL_STATUS:
-               case FL_CFI_QUERY:
-               case FL_JEDEC_QUERY:
-                       chip->oldstate = chip->state;
-                       chip->state = FL_SYNCING;
-                       /* No need to wake_up() on this state change -
-                        * as the whole point is that nobody can do anything
-                        * with the chip now anyway.
-                        */
-               case FL_SYNCING:
-                       spin_unlock_bh(chip->mutex);
-                       break;
-
-               default:
-                       /* Not an idle state */
-                       add_wait_queue(&chip->wq, &wait);
-
-                       spin_unlock_bh(chip->mutex);
-
-                       schedule();
-
-                       remove_wait_queue(&chip->wq, &wait);
-
-                       goto retry;
-               }
-       }
-
-       /* Unlock the chips again */
-       for (i--; i >= 0; i--) {
-               chip = &private->chips[i];
-
-               spin_lock_bh(chip->mutex);
-
-               if (chip->state == FL_SYNCING) {
-                       chip->state = chip->oldstate;
-                       wake_up(&chip->wq);
-               }
-               spin_unlock_bh(chip->mutex);
-       }
-}
-
-
-
-static int amd_flash_suspend(struct mtd_info *mtd)
-{
-printk("amd_flash_suspend(): not implemented!\n");
-       return -EINVAL;
-}
-
-
-
-static void amd_flash_resume(struct mtd_info *mtd)
-{
-printk("amd_flash_resume(): not implemented!\n");
-}
-
-
-
-static void amd_flash_destroy(struct mtd_info *mtd)
-{
-       struct map_info *map = mtd->priv;
-       struct amd_flash_private *private = map->fldrv_priv;
-       kfree(private);
-}
-
-int __init amd_flash_init(void)
-{
-       register_mtd_chip_driver(&amd_flash_chipdrv);
-       return 0;
-}
-
-void __exit amd_flash_exit(void)
-{
-       unregister_mtd_chip_driver(&amd_flash_chipdrv);
-}
-
-module_init(amd_flash_init);
-module_exit(amd_flash_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonas Holmberg <jonas.holmberg@axis.com>");
-MODULE_DESCRIPTION("Old MTD chip driver for AMD flash chips");
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
deleted file mode 100644 (file)
index 14e57b2..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-
-/* JEDEC Flash Interface.
- * This is an older type of interface for self programming flash. It is
- * commonly use in older AMD chips and is obsolete compared with CFI.
- * It is called JEDEC because the JEDEC association distributes the ID codes
- * for the chips.
- *
- * See the AMD flash databook for information on how to operate the interface.
- *
- * This code does not support anything wider than 8 bit flash chips, I am
- * not going to guess how to send commands to them, plus I expect they will
- * all speak CFI..
- *
- * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mtd/jedec.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
-
-static struct mtd_info *jedec_probe(struct map_info *);
-static int jedec_probe8(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv);
-static int jedec_probe16(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv);
-static int jedec_probe32(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv);
-static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
-                           unsigned long len);
-static int flash_erase(struct mtd_info *mtd, struct erase_info *instr);
-static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
-                      size_t *retlen, const u_char *buf);
-
-static unsigned long my_bank_size;
-
-/* Listing of parts and sizes. We need this table to learn the sector
-   size of the chip and the total length */
-static const struct JEDECTable JEDEC_table[] = {
-       {
-               .jedec          = 0x013D,
-               .name           = "AMD Am29F017D",
-               .size           = 2*1024*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       {
-               .jedec          = 0x01AD,
-               .name           = "AMD Am29F016",
-               .size           = 2*1024*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       {
-               .jedec          = 0x01D5,
-               .name           = "AMD Am29F080",
-               .size           = 1*1024*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       {
-               .jedec          = 0x01A4,
-               .name           = "AMD Am29F040",
-               .size           = 512*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       {
-               .jedec          = 0x20E3,
-               .name           = "AMD Am29W040B",
-               .size           = 512*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       {
-               .jedec          = 0xC2AD,
-               .name           = "Macronix MX29F016",
-               .size           = 2*1024*1024,
-               .sectorsize     = 64*1024,
-               .capabilities   = MTD_CAP_NORFLASH
-       },
-       { .jedec = 0x0 }
-};
-
-static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
-static void jedec_sync(struct mtd_info *mtd) {};
-static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
-                     size_t *retlen, u_char *buf);
-static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
-                            size_t *retlen, u_char *buf);
-
-static struct mtd_info *jedec_probe(struct map_info *map);
-
-
-
-static struct mtd_chip_driver jedec_chipdrv = {
-       .probe  = jedec_probe,
-       .name   = "jedec",
-       .module = THIS_MODULE
-};
-
-/* Probe entry point */
-
-static struct mtd_info *jedec_probe(struct map_info *map)
-{
-   struct mtd_info *MTD;
-   struct jedec_private *priv;
-   unsigned long Base;
-   unsigned long SectorSize;
-   unsigned count;
-   unsigned I,Uniq;
-   char Part[200];
-   memset(&priv,0,sizeof(priv));
-
-   MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
-   if (!MTD)
-          return NULL;
-
-   priv = (struct jedec_private *)&MTD[1];
-
-   my_bank_size = map->size;
-
-   if (map->size/my_bank_size > MAX_JEDEC_CHIPS)
-   {
-      printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
-      kfree(MTD);
-      return NULL;
-   }
-
-   for (Base = 0; Base < map->size; Base += my_bank_size)
-   {
-      // Perhaps zero could designate all tests?
-      if (map->buswidth == 0)
-        map->buswidth = 1;
-
-      if (map->buswidth == 1){
-        if (jedec_probe8(map,Base,priv) == 0) {
-                printk("did recognize jedec chip\n");
-                kfree(MTD);
-                return NULL;
-        }
-      }
-      if (map->buswidth == 2)
-        jedec_probe16(map,Base,priv);
-      if (map->buswidth == 4)
-        jedec_probe32(map,Base,priv);
-   }
-
-   // Get the biggest sector size
-   SectorSize = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-          //      printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec);
-          //      printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize);
-      if (priv->chips[I].sectorsize > SectorSize)
-        SectorSize = priv->chips[I].sectorsize;
-   }
-
-   // Quickly ensure that the other sector sizes are factors of the largest
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize)
-      {
-        printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
-        kfree(MTD);
-        return NULL;
-      }
-   }
-
-   /* Generate a part name that includes the number of different chips and
-      other configuration information */
-   count = 1;
-   strlcpy(Part,map->name,sizeof(Part)-10);
-   strcat(Part," ");
-   Uniq = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      const struct JEDECTable *JEDEC;
-
-      if (priv->chips[I+1].jedec == priv->chips[I].jedec)
-      {
-        count++;
-        continue;
-      }
-
-      // Locate the chip in the jedec table
-      JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);
-      if (JEDEC == 0)
-      {
-        printk("mtd: Internal Error, JEDEC not set\n");
-        kfree(MTD);
-        return NULL;
-      }
-
-      if (Uniq != 0)
-        strcat(Part,",");
-      Uniq++;
-
-      if (count != 1)
-        sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
-      else
-        sprintf(Part+strlen(Part),"%s",JEDEC->name);
-      if (strlen(Part) > sizeof(Part)*2/3)
-        break;
-      count = 1;
-   }
-
-   /* Determine if the chips are organized in a linear fashion, or if there
-      are empty banks. Note, the last bank does not count here, only the
-      first banks are important. Holes on non-bank boundaries can not exist
-      due to the way the detection algorithm works. */
-   if (priv->size < my_bank_size)
-      my_bank_size = priv->size;
-   priv->is_banked = 0;
-   //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size);
-   //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]);
-   if (!priv->size) {
-          printk("priv->size is zero\n");
-          kfree(MTD);
-          return NULL;
-   }
-   if (priv->size/my_bank_size) {
-          if (priv->size/my_bank_size == 1) {
-                  priv->size = my_bank_size;
-          }
-          else {
-                  for (I = 0; I != priv->size/my_bank_size - 1; I++)
-                  {
-                     if (priv->bank_fill[I] != my_bank_size)
-                        priv->is_banked = 1;
-
-                     /* This even could be eliminated, but new de-optimized read/write
-                        functions have to be written */
-                     printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);
-                     if (priv->bank_fill[I] != priv->bank_fill[0])
-                     {
-                        printk("mtd: Failed. Cannot handle unsymmetric banking\n");
-                        kfree(MTD);
-                        return NULL;
-                     }
-                  }
-          }
-   }
-   if (priv->is_banked == 1)
-      strcat(Part,", banked");
-
-   //   printk("Part: '%s'\n",Part);
-
-   memset(MTD,0,sizeof(*MTD));
-  // strlcpy(MTD->name,Part,sizeof(MTD->name));
-   MTD->name = map->name;
-   MTD->type = MTD_NORFLASH;
-   MTD->flags = MTD_CAP_NORFLASH;
-   MTD->writesize = 1;
-   MTD->erasesize = SectorSize*(map->buswidth);
-   //   printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
-   MTD->size = priv->size;
-   //   printk("MTD->size is %x\n",(unsigned int)MTD->size);
-   //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module?
-   MTD->erase = flash_erase;
-   if (priv->is_banked == 1)
-      MTD->read = jedec_read_banked;
-   else
-      MTD->read = jedec_read;
-   MTD->write = flash_write;
-   MTD->sync = jedec_sync;
-   MTD->priv = map;
-   map->fldrv_priv = priv;
-   map->fldrv = &jedec_chipdrv;
-   __module_get(THIS_MODULE);
-   return MTD;
-}
-
-/* Helper for the JEDEC function, JEDEC numbers all have odd parity */
-static int checkparity(u_char C)
-{
-   u_char parity = 0;
-   while (C != 0)
-   {
-      parity ^= C & 1;
-      C >>= 1;
-   }
-
-   return parity == 1;
-}
-
-
-/* Take an array of JEDEC numbers that represent interleved flash chips
-   and process them. Check to make sure they are good JEDEC numbers, look
-   them up and then add them to the chip list */
-static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
-                 unsigned long base,struct jedec_private *priv)
-{
-   unsigned I,J;
-   unsigned long Size;
-   unsigned long SectorSize;
-   const struct JEDECTable *JEDEC;
-
-   // Test #2 JEDEC numbers exhibit odd parity
-   for (I = 0; I != Count; I++)
-   {
-      if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
-        return 0;
-   }
-
-   // Finally, just make sure all the chip sizes are the same
-   JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
-
-   if (JEDEC == 0)
-   {
-      printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
-      return 0;
-   }
-
-   Size = JEDEC->size;
-   SectorSize = JEDEC->sectorsize;
-   for (I = 0; I != Count; I++)
-   {
-      JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
-      if (JEDEC == 0)
-      {
-        printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
-        return 0;
-      }
-
-      if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize)
-      {
-        printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
-        return 0;
-      }
-   }
-
-   // Load the Chips
-   for (I = 0; I != MAX_JEDEC_CHIPS; I++)
-   {
-      if (priv->chips[I].jedec == 0)
-        break;
-   }
-
-   if (I + Count > MAX_JEDEC_CHIPS)
-   {
-      printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
-      return 0;
-   }
-
-   // Add them to the table
-   for (J = 0; J != Count; J++)
-   {
-      unsigned long Bank;
-
-      JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
-      priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
-      priv->chips[I].size = JEDEC->size;
-      priv->chips[I].sectorsize = JEDEC->sectorsize;
-      priv->chips[I].base = base + J;
-      priv->chips[I].datashift = J*8;
-      priv->chips[I].capabilities = JEDEC->capabilities;
-      priv->chips[I].offset = priv->size + J;
-
-      // log2 n :|
-      priv->chips[I].addrshift = 0;
-      for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
-
-      // Determine how filled this bank is.
-      Bank = base & (~(my_bank_size-1));
-      if (priv->bank_fill[Bank/my_bank_size] < base +
-         (JEDEC->size << priv->chips[I].addrshift) - Bank)
-        priv->bank_fill[Bank/my_bank_size] =  base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
-      I++;
-   }
-
-   priv->size += priv->chips[I-1].size*Count;
-
-   return priv->chips[I-1].size;
-}
-
-/* Lookup the chip information from the JEDEC ID table. */
-static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
-{
-   __u16 Id = (mfr << 8) | id;
-   unsigned long I = 0;
-   for (I = 0; JEDEC_table[I].jedec != 0; I++)
-      if (JEDEC_table[I].jedec == Id)
-        return JEDEC_table + I;
-   return NULL;
-}
-
-// Look for flash using an 8 bit bus interface
-static int jedec_probe8(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv)
-{
-   #define flread(x) map_read8(map,base+x)
-   #define flwrite(v,x) map_write8(map,v,base+x)
-
-   const unsigned long AutoSel1 = 0xAA;
-   const unsigned long AutoSel2 = 0x55;
-   const unsigned long AutoSel3 = 0x90;
-   const unsigned long Reset = 0xF0;
-   __u32 OldVal;
-   __u8 Mfg[1];
-   __u8 Id[1];
-   unsigned I;
-   unsigned long Size;
-
-   // Wait for any write/erase operation to settle
-   OldVal = flread(base);
-   for (I = 0; OldVal != flread(base) && I < 10000; I++)
-      OldVal = flread(base);
-
-   // Reset the chip
-   flwrite(Reset,0x555);
-
-   // Send the sequence
-   flwrite(AutoSel1,0x555);
-   flwrite(AutoSel2,0x2AA);
-   flwrite(AutoSel3,0x555);
-
-   //  Get the JEDEC numbers
-   Mfg[0] = flread(0);
-   Id[0] = flread(1);
-   //   printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);
-
-   Size = handle_jedecs(map,Mfg,Id,1,base,priv);
-   //   printk("handle_jedecs Size is %x\n",(unsigned int)Size);
-   if (Size == 0)
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-
-   // Reset.
-   flwrite(Reset,0x555);
-
-   return 1;
-
-   #undef flread
-   #undef flwrite
-}
-
-// Look for flash using a 16 bit bus interface (ie 2 8-bit chips)
-static int jedec_probe16(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv)
-{
-   return 0;
-}
-
-// Look for flash using a 32 bit bus interface (ie 4 8-bit chips)
-static int jedec_probe32(struct map_info *map,unsigned long base,
-                 struct jedec_private *priv)
-{
-   #define flread(x) map_read32(map,base+((x)<<2))
-   #define flwrite(v,x) map_write32(map,v,base+((x)<<2))
-
-   const unsigned long AutoSel1 = 0xAAAAAAAA;
-   const unsigned long AutoSel2 = 0x55555555;
-   const unsigned long AutoSel3 = 0x90909090;
-   const unsigned long Reset = 0xF0F0F0F0;
-   __u32 OldVal;
-   __u8 Mfg[4];
-   __u8 Id[4];
-   unsigned I;
-   unsigned long Size;
-
-   // Wait for any write/erase operation to settle
-   OldVal = flread(base);
-   for (I = 0; OldVal != flread(base) && I < 10000; I++)
-      OldVal = flread(base);
-
-   // Reset the chip
-   flwrite(Reset,0x555);
-
-   // Send the sequence
-   flwrite(AutoSel1,0x555);
-   flwrite(AutoSel2,0x2AA);
-   flwrite(AutoSel3,0x555);
-
-   // Test #1, JEDEC numbers are readable from 0x??00/0x??01
-   if (flread(0) != flread(0x100) ||
-       flread(1) != flread(0x101))
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-   // Split up the JEDEC numbers
-   OldVal = flread(0);
-   for (I = 0; I != 4; I++)
-      Mfg[I] = (OldVal >> (I*8));
-   OldVal = flread(1);
-   for (I = 0; I != 4; I++)
-      Id[I] = (OldVal >> (I*8));
-
-   Size = handle_jedecs(map,Mfg,Id,4,base,priv);
-   if (Size == 0)
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-   /* Check if there is address wrap around within a single bank, if this
-      returns JEDEC numbers then we assume that it is wrap around. Notice
-      we call this routine with the JEDEC return still enabled, if two or
-      more flashes have a truncated address space the probe test will still
-      work */
-   if (base + (Size<<2)+0x555 < map->size &&
-       base + (Size<<2)+0x555 < (base & (~(my_bank_size-1))) + my_bank_size)
-   {
-      if (flread(base+Size) != flread(base+Size + 0x100) ||
-         flread(base+Size + 1) != flread(base+Size + 0x101))
-      {
-        jedec_probe32(map,base+Size,priv);
-      }
-   }
-
-   // Reset.
-   flwrite(0xF0F0F0F0,0x555);
-
-   return 1;
-
-   #undef flread
-   #undef flwrite
-}
-
-/* Linear read. */
-static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
-                     size_t *retlen, u_char *buf)
-{
-   struct map_info *map = mtd->priv;
-
-   map_copy_from(map, buf, from, len);
-   *retlen = len;
-   return 0;
-}
-
-/* Banked read. Take special care to jump past the holes in the bank
-   mapping. This version assumes symetry in the holes.. */
-static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
-                            size_t *retlen, u_char *buf)
-{
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-
-   *retlen = 0;
-   while (len > 0)
-   {
-      // Determine what bank and offset into that bank the first byte is
-      unsigned long bank = from & (~(priv->bank_fill[0]-1));
-      unsigned long offset = from & (priv->bank_fill[0]-1);
-      unsigned long get = len;
-      if (priv->bank_fill[0] - offset < len)
-        get = priv->bank_fill[0] - offset;
-
-      bank /= priv->bank_fill[0];
-      map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get);
-
-      len -= get;
-      *retlen += get;
-      from += get;
-   }
-   return 0;
-}
-
-/* Pass the flags value that the flash return before it re-entered read
-   mode. */
-static void jedec_flash_failed(unsigned char code)
-{
-   /* Bit 5 being high indicates that there was an internal device
-      failure, erasure time limits exceeded or something */
-   if ((code & (1 << 5)) != 0)
-   {
-      printk("mtd: Internal Flash failure\n");
-      return;
-   }
-   printk("mtd: Programming didn't take\n");
-}
-
-/* This uses the erasure function described in the AMD Flash Handbook,
-   it will work for flashes with a fixed sector size only. Flashes with
-   a selection of sector sizes (ie the AMD Am29F800B) will need a different
-   routine. This routine tries to parallize erasing multiple chips/sectors
-   where possible */
-static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-   // Does IO to the currently selected chip
-   #define flread(x) map_read8(map,chip->base+((x)<<chip->addrshift))
-   #define flwrite(v,x) map_write8(map,v,chip->base+((x)<<chip->addrshift))
-
-   unsigned long Time = 0;
-   unsigned long NoTime = 0;
-   unsigned long start = instr->addr, len = instr->len;
-   unsigned int I;
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-
-   // Verify the arguments..
-   if (start + len > mtd->size ||
-       (start % mtd->erasesize) != 0 ||
-       (len % mtd->erasesize) != 0 ||
-       (len/mtd->erasesize) == 0)
-      return -EINVAL;
-
-   jedec_flash_chip_scan(priv,start,len);
-
-   // Start the erase sequence on each chip
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      unsigned long off;
-      struct jedec_flash_chip *chip = priv->chips + I;
-
-      if (chip->length == 0)
-        continue;
-
-      if (chip->start + chip->length > chip->size)
-      {
-        printk("DIE\n");
-        return -EIO;
-      }
-
-      flwrite(0xF0,chip->start + 0x555);
-      flwrite(0xAA,chip->start + 0x555);
-      flwrite(0x55,chip->start + 0x2AA);
-      flwrite(0x80,chip->start + 0x555);
-      flwrite(0xAA,chip->start + 0x555);
-      flwrite(0x55,chip->start + 0x2AA);
-
-      /* Once we start selecting the erase sectors the delay between each
-         command must not exceed 50us or it will immediately start erasing
-         and ignore the other sectors */
-      for (off = 0; off < len; off += chip->sectorsize)
-      {
-        // Check to make sure we didn't timeout
-        flwrite(0x30,chip->start + off);
-        if (off == 0)
-           continue;
-        if ((flread(chip->start + off) & (1 << 3)) != 0)
-        {
-           printk("mtd: Ack! We timed out the erase timer!\n");
-           return -EIO;
-        }
-      }
-   }
-
-   /* We could split this into a timer routine and return early, performing
-      background erasure.. Maybe later if the need warrents */
-
-   /* Poll the flash for erasure completion, specs say this can take as long
-      as 480 seconds to do all the sectors (for a 2 meg flash).
-      Erasure time is dependent on chip age, temp and wear.. */
-
-   /* This being a generic routine assumes a 32 bit bus. It does read32s
-      and bundles interleved chips into the same grouping. This will work
-      for all bus widths */
-   Time = 0;
-   NoTime = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      struct jedec_flash_chip *chip = priv->chips + I;
-      unsigned long off = 0;
-      unsigned todo[4] = {0,0,0,0};
-      unsigned todo_left = 0;
-      unsigned J;
-
-      if (chip->length == 0)
-        continue;
-
-      /* Find all chips in this data line, realistically this is all
-         or nothing up to the interleve count */
-      for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
-      {
-        if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
-            (chip->base & (~((1<<chip->addrshift)-1))))
-        {
-           todo_left++;
-           todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
-        }
-      }
-
-      /*      printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
-             (short)todo[2],(short)todo[3]);
-      */
-      while (1)
-      {
-        __u32 Last[4];
-        unsigned long Count = 0;
-
-        /* During erase bit 7 is held low and bit 6 toggles, we watch this,
-           should it stop toggling or go high then the erase is completed,
-           or this is not really flash ;> */
-        switch (map->buswidth) {
-        case 1:
-           Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-           break;
-        case 2:
-           Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-           break;
-        case 3:
-           Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-           Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-           break;
-        }
-        Count = 3;
-        while (todo_left != 0)
-        {
-           for (J = 0; J != 4; J++)
-           {
-              __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF;
-              __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF;
-              __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
-              if (todo[J] == 0)
-                 continue;
-
-              if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
-              {
-//               printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
-                 continue;
-              }
-
-              if (Byte1 == Byte2)
-              {
-                 jedec_flash_failed(Byte3);
-                 return -EIO;
-              }
-
-              todo[J] = 0;
-              todo_left--;
-           }
-
-/*         if (NoTime == 0)
-              Time += HZ/10 - schedule_timeout(HZ/10);*/
-           NoTime = 0;
-
-           switch (map->buswidth) {
-           case 1:
-              Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-             break;
-           case 2:
-              Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-             break;
-           case 4:
-              Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-             break;
-           }
-           Count++;
-
-/*         // Count time, max of 15s per sector (according to AMD)
-           if (Time > 15*len/mtd->erasesize*HZ)
-           {
-              printk("mtd: Flash Erase Timed out\n");
-              return -EIO;
-           }       */
-        }
-
-        // Skip to the next chip if we used chip erase
-        if (chip->length == chip->size)
-           off = chip->size;
-        else
-           off += chip->sectorsize;
-
-        if (off >= chip->length)
-           break;
-        NoTime = 1;
-      }
-
-      for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
-      {
-        if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
-            (chip->base & (~((1<<chip->addrshift)-1))))
-           priv->chips[J].length = 0;
-      }
-   }
-
-   //printk("done\n");
-   instr->state = MTD_ERASE_DONE;
-   mtd_erase_callback(instr);
-   return 0;
-
-   #undef flread
-   #undef flwrite
-}
-
-/* This is the simple flash writing function. It writes to every byte, in
-   sequence. It takes care of how to properly address the flash if
-   the flash is interleved. It can only be used if all the chips in the
-   array are identical!*/
-static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
-                      size_t *retlen, const u_char *buf)
-{
-   /* Does IO to the currently selected chip. It takes the bank addressing
-      base (which is divisible by the chip size) adds the necessary lower bits
-      of addrshift (interleave index) and then adds the control register index. */
-   #define flread(x) map_read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
-   #define flwrite(v,x) map_write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
-
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-   unsigned long base;
-   unsigned long off;
-   size_t save_len = len;
-
-   if (start + len > mtd->size)
-      return -EIO;
-
-   //printk("Here");
-
-   //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len);
-   while (len != 0)
-   {
-      struct jedec_flash_chip *chip = priv->chips;
-      unsigned long bank;
-      unsigned long boffset;
-
-      // Compute the base of the flash.
-      off = ((unsigned long)start) % (chip->size << chip->addrshift);
-      base = start - off;
-
-      // Perform banked addressing translation.
-      bank = base & (~(priv->bank_fill[0]-1));
-      boffset = base & (priv->bank_fill[0]-1);
-      bank = (bank/priv->bank_fill[0])*my_bank_size;
-      base = bank + boffset;
-
-    //  printk("Flasing %X %X %X\n",base,chip->size,len);
-     // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift);
-
-      // Loop over this page
-      for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
-      {
-        unsigned char oldbyte = map_read8(map,base+off);
-        unsigned char Last[4];
-        unsigned long Count = 0;
-
-        if (oldbyte == *buf) {
-       //       printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len);
-           continue;
-        }
-        if (((~oldbyte) & *buf) != 0)
-           printk("mtd: warn: Trying to set a 0 to a 1\n");
-
-        // Write
-        flwrite(0xAA,0x555);
-        flwrite(0x55,0x2AA);
-        flwrite(0xA0,0x555);
-        map_write8(map,*buf,base + off);
-        Last[0] = map_read8(map,base + off);
-        Last[1] = map_read8(map,base + off);
-        Last[2] = map_read8(map,base + off);
-
-        /* Wait for the flash to finish the operation. We store the last 4
-           status bytes that have been retrieved so we can determine why
-           it failed. The toggle bits keep toggling when there is a
-           failure */
-        for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
-             Count < 10000; Count++)
-           Last[Count % 4] = map_read8(map,base + off);
-        if (Last[(Count - 1) % 4] != *buf)
-        {
-           jedec_flash_failed(Last[(Count - 3) % 4]);
-           return -EIO;
-        }
-      }
-   }
-   *retlen = save_len;
-   return 0;
-}
-
-/* This is used to enhance the speed of the erase routine,
-   when things are being done to multiple chips it is possible to
-   parallize the operations, particularly full memory erases of multi
-   chip memories benifit */
-static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
-                    unsigned long len)
-{
-   unsigned int I;
-
-   // Zero the records
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-      priv->chips[I].start = priv->chips[I].length = 0;
-
-   // Intersect the region with each chip
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      struct jedec_flash_chip *chip = priv->chips + I;
-      unsigned long ByteStart;
-      unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
-
-      // End is before this chip or the start is after it
-      if (start+len < chip->offset ||
-         ChipEndByte - (1 << chip->addrshift) < start)
-        continue;
-
-      if (start < chip->offset)
-      {
-        ByteStart = chip->offset;
-        chip->start = 0;
-      }
-      else
-      {
-        chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
-        ByteStart = start;
-      }
-
-      if (start + len >= ChipEndByte)
-        chip->length = (ChipEndByte - ByteStart) >> chip->addrshift;
-      else
-        chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift;
-   }
-}
-
-int __init jedec_init(void)
-{
-       register_mtd_chip_driver(&jedec_chipdrv);
-       return 0;
-}
-
-static void __exit jedec_exit(void)
-{
-       unregister_mtd_chip_driver(&jedec_chipdrv);
-}
-
-module_init(jedec_init);
-module_exit(jedec_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com> et al.");
-MODULE_DESCRIPTION("Old MTD chip driver for JEDEC-compliant flash chips");
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
deleted file mode 100644 (file)
index c9cd3d2..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * MTD chip driver for pre-CFI Sharp flash chips
- *
- * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
- *           2000,2001 Lineo, Inc.
- *
- * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
- *
- * Devices supported:
- *   LH28F016SCT Symmetrical block flash memory, 2Mx8
- *   LH28F008SCT Symmetrical block flash memory, 1Mx8
- *
- * Documentation:
- *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
- *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
- *   016sctl9.pdf
- *
- * Limitations:
- *   This driver only supports 4x1 arrangement of chips.
- *   Not tested on anything but PowerPC.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/cfi.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#define CMD_RESET              0xffffffff
-#define CMD_READ_ID            0x90909090
-#define CMD_READ_STATUS                0x70707070
-#define CMD_CLEAR_STATUS       0x50505050
-#define CMD_BLOCK_ERASE_1      0x20202020
-#define CMD_BLOCK_ERASE_2      0xd0d0d0d0
-#define CMD_BYTE_WRITE         0x40404040
-#define CMD_SUSPEND            0xb0b0b0b0
-#define CMD_RESUME             0xd0d0d0d0
-#define CMD_SET_BLOCK_LOCK_1   0x60606060
-#define CMD_SET_BLOCK_LOCK_2   0x01010101
-#define CMD_SET_MASTER_LOCK_1  0x60606060
-#define CMD_SET_MASTER_LOCK_2  0xf1f1f1f1
-#define CMD_CLEAR_BLOCK_LOCKS_1        0x60606060
-#define CMD_CLEAR_BLOCK_LOCKS_2        0xd0d0d0d0
-
-#define SR_READY               0x80808080 // 1 = ready
-#define SR_ERASE_SUSPEND       0x40404040 // 1 = block erase suspended
-#define SR_ERROR_ERASE         0x20202020 // 1 = error in block erase or clear lock bits
-#define SR_ERROR_WRITE         0x10101010 // 1 = error in byte write or set lock bit
-#define        SR_VPP                  0x08080808 // 1 = Vpp is low
-#define SR_WRITE_SUSPEND       0x04040404 // 1 = byte write suspended
-#define SR_PROTECT             0x02020202 // 1 = lock bit set
-#define SR_RESERVED            0x01010101
-
-#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
-
-/* Configuration options */
-
-#undef AUTOUNLOCK  /* automatically unlocks blocks before erasing */
-
-static struct mtd_info *sharp_probe(struct map_info *);
-
-static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
-
-static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, u_char *buf);
-static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, const u_char *buf);
-static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
-static void sharp_sync(struct mtd_info *mtd);
-static int sharp_suspend(struct mtd_info *mtd);
-static void sharp_resume(struct mtd_info *mtd);
-static void sharp_destroy(struct mtd_info *mtd);
-
-static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
-       unsigned long adr, __u32 datum);
-static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
-       unsigned long adr);
-#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
-       unsigned long adr);
-#endif
-
-
-struct sharp_info{
-       struct flchip *chip;
-       int bogus;
-       int chipshift;
-       int numchips;
-       struct flchip chips[1];
-};
-
-static void sharp_destroy(struct mtd_info *mtd);
-
-static struct mtd_chip_driver sharp_chipdrv = {
-       .probe          = sharp_probe,
-       .destroy        = sharp_destroy,
-       .name           = "sharp",
-       .module         = THIS_MODULE
-};
-
-
-static struct mtd_info *sharp_probe(struct map_info *map)
-{
-       struct mtd_info *mtd = NULL;
-       struct sharp_info *sharp = NULL;
-       int width;
-
-       mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-       if(!mtd)
-               return NULL;
-
-       sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
-       if(!sharp) {
-               kfree(mtd);
-               return NULL;
-       }
-
-       width = sharp_probe_map(map,mtd);
-       if(!width){
-               kfree(mtd);
-               kfree(sharp);
-               return NULL;
-       }
-
-       mtd->priv = map;
-       mtd->type = MTD_NORFLASH;
-       mtd->erase = sharp_erase;
-       mtd->read = sharp_read;
-       mtd->write = sharp_write;
-       mtd->sync = sharp_sync;
-       mtd->suspend = sharp_suspend;
-       mtd->resume = sharp_resume;
-       mtd->flags = MTD_CAP_NORFLASH;
-       mtd->writesize = 1;
-       mtd->name = map->name;
-
-       sharp->chipshift = 23;
-       sharp->numchips = 1;
-       sharp->chips[0].start = 0;
-       sharp->chips[0].state = FL_READY;
-       sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
-       sharp->chips[0].word_write_time = 0;
-       init_waitqueue_head(&sharp->chips[0].wq);
-       spin_lock_init(&sharp->chips[0]._spinlock);
-
-       map->fldrv = &sharp_chipdrv;
-       map->fldrv_priv = sharp;
-
-       __module_get(THIS_MODULE);
-       return mtd;
-}
-
-static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
-{
-       map_word map_cmd;
-       map_cmd.x[0] = cmd;
-       map_write(map, map_cmd, adr);
-}
-
-static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
-{
-       map_word tmp, read0, read4;
-       unsigned long base = 0;
-       int width = 4;
-
-       tmp = map_read(map, base+0);
-
-       sharp_send_cmd(map, CMD_READ_ID, base+0);
-
-       read0 = map_read(map, base+0);
-       read4 = map_read(map, base+4);
-       if(read0.x[0] == 0x89898989){
-               printk("Looks like sharp flash\n");
-               switch(read4.x[0]){
-               case 0xaaaaaaaa:
-               case 0xa0a0a0a0:
-                       /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
-                       /* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
-                       mtd->erasesize = 0x10000 * width;
-                       mtd->size = 0x200000 * width;
-                       return width;
-               case 0xa6a6a6a6:
-                       /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
-                       /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
-                       mtd->erasesize = 0x10000 * width;
-                       mtd->size = 0x100000 * width;
-                       return width;
-#if 0
-               case 0x00000000: /* unknown */
-                       /* XX - LH28F004SCT 512kx8, 8 64k blocks*/
-                       mtd->erasesize = 0x10000 * width;
-                       mtd->size = 0x80000 * width;
-                       return width;
-#endif
-               default:
-                       printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
-                               read0.x[0], read4.x[0]);
-               }
-       }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){
-               /* RAM, probably */
-               printk("Looks like RAM\n");
-               map_write(map, tmp, base+0);
-       }else{
-               printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
-                       read0.x[0], read4.x[0]);
-       }
-
-       return 0;
-}
-
-/* This function returns with the chip->mutex lock held. */
-static int sharp_wait(struct map_info *map, struct flchip *chip)
-{
-       int i;
-       map_word status;
-       unsigned long timeo = jiffies + HZ;
-       DECLARE_WAITQUEUE(wait, current);
-       int adr = 0;
-
-retry:
-       spin_lock_bh(chip->mutex);
-
-       switch(chip->state){
-       case FL_READY:
-               sharp_send_cmd(map, CMD_READ_STATUS, adr);
-               chip->state = FL_STATUS;
-       case FL_STATUS:
-               for(i=0;i<100;i++){
-                       status = map_read(map, adr);
-                       if((status.x[0] & SR_READY)==SR_READY)
-                               break;
-                       udelay(1);
-               }
-               break;
-       default:
-               printk("Waiting for chip\n");
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&chip->wq, &wait);
-
-               spin_unlock_bh(chip->mutex);
-
-               schedule();
-               remove_wait_queue(&chip->wq, &wait);
-
-               if(signal_pending(current))
-                       return -EINTR;
-
-               timeo = jiffies + HZ;
-
-               goto retry;
-       }
-
-       sharp_send_cmd(map, CMD_RESET, adr);
-
-       chip->state = FL_READY;
-
-       return 0;
-}
-
-static void sharp_release(struct flchip *chip)
-{
-       wake_up(&chip->wq);
-       spin_unlock_bh(chip->mutex);
-}
-
-static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, u_char *buf)
-{
-       struct map_info *map = mtd->priv;
-       struct sharp_info *sharp = map->fldrv_priv;
-       int chipnum;
-       int ret = 0;
-       int ofs = 0;
-
-       chipnum = (from >> sharp->chipshift);
-       ofs = from & ((1 << sharp->chipshift)-1);
-
-       *retlen = 0;
-
-       while(len){
-               unsigned long thislen;
-
-               if(chipnum>=sharp->numchips)
-                       break;
-
-               thislen = len;
-               if(ofs+thislen >= (1<<sharp->chipshift))
-                       thislen = (1<<sharp->chipshift) - ofs;
-
-               ret = sharp_wait(map,&sharp->chips[chipnum]);
-               if(ret<0)
-                       break;
-
-               map_copy_from(map,buf,ofs,thislen);
-
-               sharp_release(&sharp->chips[chipnum]);
-
-               *retlen += thislen;
-               len -= thislen;
-               buf += thislen;
-
-               ofs = 0;
-               chipnum++;
-       }
-       return ret;
-}
-
-static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
-       size_t *retlen, const u_char *buf)
-{
-       struct map_info *map = mtd->priv;
-       struct sharp_info *sharp = map->fldrv_priv;
-       int ret = 0;
-       int i,j;
-       int chipnum;
-       unsigned long ofs;
-       union { u32 l; unsigned char uc[4]; } tbuf;
-
-       *retlen = 0;
-
-       while(len){
-               tbuf.l = 0xffffffff;
-               chipnum = to >> sharp->chipshift;
-               ofs = to & ((1<<sharp->chipshift)-1);
-
-               j=0;
-               for(i=ofs&3;i<4 && len;i++){
-                       tbuf.uc[i] = *buf;
-                       buf++;
-                       to++;
-                       len--;
-                       j++;
-               }
-               sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
-               if(ret<0)
-                       return ret;
-               (*retlen)+=j;
-       }
-
-       return 0;
-}
-
-static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
-       unsigned long adr, __u32 datum)
-{
-       int ret;
-       int timeo;
-       int try;
-       int i;
-       map_word data, status;
-
-       status.x[0] = 0;
-       ret = sharp_wait(map,chip);
-
-       for(try=0;try<10;try++){
-               sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
-               /* cpu_to_le32 -> hack to fix the writel be->le conversion */
-               data.x[0] = cpu_to_le32(datum);
-               map_write(map, data, adr);
-
-               chip->state = FL_WRITING;
-
-               timeo = jiffies + (HZ/2);
-
-               sharp_send_cmd(map, CMD_READ_STATUS, adr);
-               for(i=0;i<100;i++){
-                       status = map_read(map, adr);
-                       if((status.x[0] & SR_READY) == SR_READY)
-                               break;
-               }
-               if(i==100){
-                       printk("sharp: timed out writing\n");
-               }
-
-               if(!(status.x[0] & SR_ERRORS))
-                       break;
-
-               printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
-
-               sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-       }
-       sharp_send_cmd(map, CMD_RESET, adr);
-       chip->state = FL_READY;
-
-       wake_up(&chip->wq);
-       spin_unlock_bh(chip->mutex);
-
-       return 0;
-}
-
-static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-       struct map_info *map = mtd->priv;
-       struct sharp_info *sharp = map->fldrv_priv;
-       unsigned long adr,len;
-       int chipnum, ret=0;
-
-//printk("sharp_erase()\n");
-       if(instr->addr & (mtd->erasesize - 1))
-               return -EINVAL;
-       if(instr->len & (mtd->erasesize - 1))
-               return -EINVAL;
-       if(instr->len + instr->addr > mtd->size)
-               return -EINVAL;
-
-       chipnum = instr->addr >> sharp->chipshift;
-       adr = instr->addr & ((1<<sharp->chipshift)-1);
-       len = instr->len;
-
-       while(len){
-               ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
-               if(ret)return ret;
-
-               adr += mtd->erasesize;
-               len -= mtd->erasesize;
-               if(adr >> sharp->chipshift){
-                       adr = 0;
-                       chipnum++;
-                       if(chipnum>=sharp->numchips)
-                               break;
-               }
-       }
-
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
-       return 0;
-}
-
-static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
-       unsigned long adr)
-{
-       int ret;
-       unsigned long timeo;
-       map_word status;
-       DECLARE_WAITQUEUE(wait, current);
-
-       sharp_send_cmd(map, CMD_READ_STATUS, adr);
-       status = map_read(map, adr);
-
-       timeo = jiffies + HZ;
-
-       while(time_before(jiffies, timeo)){
-               sharp_send_cmd(map, CMD_READ_STATUS, adr);
-               status = map_read(map, adr);
-               if((status.x[0] & SR_READY)==SR_READY){
-                       ret = 0;
-                       goto out;
-               }
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&chip->wq, &wait);
-
-               //spin_unlock_bh(chip->mutex);
-
-               schedule_timeout(1);
-               schedule();
-               remove_wait_queue(&chip->wq, &wait);
-
-               //spin_lock_bh(chip->mutex);
-
-               if (signal_pending(current)){
-                       ret = -EINTR;
-                       goto out;
-               }
-
-       }
-       ret = -ETIME;
-out:
-       return ret;
-}
-
-static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
-       unsigned long adr)
-{
-       int ret;
-       //int timeo;
-       map_word status;
-       //int i;
-
-//printk("sharp_erase_oneblock()\n");
-
-#ifdef AUTOUNLOCK
-       /* This seems like a good place to do an unlock */
-       sharp_unlock_oneblock(map,chip,adr);
-#endif
-
-       sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
-       sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
-
-       chip->state = FL_ERASING;
-
-       ret = sharp_do_wait_for_ready(map,chip,adr);
-       if(ret<0)return ret;
-
-       sharp_send_cmd(map, CMD_READ_STATUS, adr);
-       status = map_read(map, adr);
-
-       if(!(status.x[0] & SR_ERRORS)){
-               sharp_send_cmd(map, CMD_RESET, adr);
-               chip->state = FL_READY;
-               //spin_unlock_bh(chip->mutex);
-               return 0;
-       }
-
-       printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
-       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-
-       //spin_unlock_bh(chip->mutex);
-
-       return -EIO;
-}
-
-#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
-       unsigned long adr)
-{
-       int i;
-       map_word status;
-
-       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr);
-       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr);
-
-       udelay(100);
-
-       status = map_read(map, adr);
-       printk("status=%08lx\n", status.x[0]);
-
-       for(i=0;i<1000;i++){
-               //sharp_send_cmd(map, CMD_READ_STATUS, adr);
-               status = map_read(map, adr);
-               if((status.x[0] & SR_READY) == SR_READY)
-                       break;
-               udelay(100);
-       }
-       if(i==1000){
-               printk("sharp: timed out unlocking block\n");
-       }
-
-       if(!(status.x[0] & SR_ERRORS)){
-               sharp_send_cmd(map, CMD_RESET, adr);
-               chip->state = FL_READY;
-               return;
-       }
-
-       printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
-       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-}
-#endif
-
-static void sharp_sync(struct mtd_info *mtd)
-{
-       //printk("sharp_sync()\n");
-}
-
-static int sharp_suspend(struct mtd_info *mtd)
-{
-       printk("sharp_suspend()\n");
-       return -EINVAL;
-}
-
-static void sharp_resume(struct mtd_info *mtd)
-{
-       printk("sharp_resume()\n");
-
-}
-
-static void sharp_destroy(struct mtd_info *mtd)
-{
-       printk("sharp_destroy()\n");
-
-}
-
-static int __init sharp_probe_init(void)
-{
-       printk("MTD Sharp chip driver <ds@lineo.com>\n");
-
-       register_mtd_chip_driver(&sharp_chipdrv);
-
-       return 0;
-}
-
-static void __exit sharp_probe_exit(void)
-{
-       unregister_mtd_chip_driver(&sharp_chipdrv);
-}
-
-module_init(sharp_probe_init);
-module_exit(sharp_probe_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Schleef <ds@schleef.org>");
-MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
index fc4cc8ba9e29b98a5df19e0d5119dfefd5455882..be4b9948c762e33b577cbd192dd836ff50c75e46 100644 (file)
@@ -373,7 +373,7 @@ static inline void kill_final_newline(char *str)
 
 #ifndef MODULE
 static int block2mtd_init_called = 0;
-static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
+static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
 #endif
 
 
index d990d8141ef5dab4337dd7be35d3dc836f8926f5..b665e4ac2208458bc70d1f8dfe9cd00a3a6a58fd 100644 (file)
@@ -60,7 +60,7 @@ config MTD_PHYSMAP_BANKWIDTH
          (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_OF
-       tristate "Flash device in physical memory map based on OF descirption"
+       tristate "Flash device in physical memory map based on OF description"
        depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
        help
          This provides a 'mapping' driver which allows the NOR Flash and
@@ -358,22 +358,6 @@ config MTD_CFI_FLAGADM
          Mapping for the Flaga digital module. If you don't have one, ignore
          this setting.
 
-config MTD_BEECH
-       tristate "CFI Flash device mapped on IBM 405LP Beech"
-       depends on MTD_CFI && BEECH
-       help
-         This enables access routines for the flash chips on the IBM
-         405LP Beech board. If you have one of these boards and would like
-         to use the flash chips on it, say 'Y'.
-
-config MTD_ARCTIC
-       tristate "CFI Flash device mapped on IBM 405LP Arctic"
-       depends on MTD_CFI && ARCTIC2
-       help
-         This enables access routines for the flash chips on the IBM 405LP
-         Arctic board. If you have one of these boards and would like to
-         use the flash chips on it, say 'Y'.
-
 config MTD_WALNUT
        tristate "Flash device mapped on IBM 405GP Walnut"
        depends on MTD_JEDECPROBE && WALNUT
index de036c5e61394375721a4fe789a824da6cbcf23e..3acbb5d01ca4edc159238390e1f827ebee431524 100644 (file)
@@ -58,8 +58,6 @@ obj-$(CONFIG_MTD_NETtel)      += nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)   += scb2_flash.o
 obj-$(CONFIG_MTD_EBONY)                += ebony.o
 obj-$(CONFIG_MTD_OCOTEA)       += ocotea.o
-obj-$(CONFIG_MTD_BEECH)                += beech-mtd.o
-obj-$(CONFIG_MTD_ARCTIC)       += arctic-mtd.o
 obj-$(CONFIG_MTD_WALNUT)        += walnut.o
 obj-$(CONFIG_MTD_H720X)                += h720x-flash.o
 obj-$(CONFIG_MTD_SBC8240)      += sbc8240.o
diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
deleted file mode 100644 (file)
index 2cc9024..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
- *
- * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
- *                              IBM 405LP Arctic boards.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright (C) 2002, International Business Machines Corporation
- * All Rights Reserved.
- *
- * Bishop Brock
- * IBM Research, Austin Center for Low-Power Computing
- * bcbrock@us.ibm.com
- * March 2002
- *
- * modified for Arctic by,
- * David Gibson
- * IBM OzLabs, Canberra, Australia
- * <arctic@gibson.dropbear.id.au>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-
-/*
- * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
- * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
- * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
- * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
- */
-
-#define FFS1_SIZE      0x01000000 /* 16MiB */
-#define KERNEL_SIZE    0x00500000 /* 5.12MiB */
-#define FFS2_SIZE      0x00a60000 /* 10.624MiB */
-#define FIRMWARE_SIZE  0x000a0000 /* 640KiB */
-
-
-#define NAME           "Arctic Linux Flash"
-#define PADDR          SUBZERO_BOOTFLASH_PADDR
-#define BUSWIDTH       2
-#define SIZE           SUBZERO_BOOTFLASH_SIZE
-#define PARTITIONS     4
-
-/* Flash memories on these boards are memory resources, accessed big-endian. */
-
-{
-  /* do nothing for now */
-}
-
-static struct map_info arctic_mtd_map = {
-       .name           = NAME,
-       .size           = SIZE,
-       .bankwidth      = BUSWIDTH,
-       .phys           = PADDR,
-};
-
-static struct mtd_info *arctic_mtd;
-
-static struct mtd_partition arctic_partitions[PARTITIONS] = {
-       { .name         = "Filesystem",
-         .size         = FFS1_SIZE,
-         .offset       = 0,},
-        { .name                = "Kernel",
-         .size         = KERNEL_SIZE,
-         .offset       = FFS1_SIZE,},
-       { .name         = "Filesystem",
-         .size         = FFS2_SIZE,
-         .offset       = FFS1_SIZE + KERNEL_SIZE,},
-       { .name         = "Firmware",
-         .size         = FIRMWARE_SIZE,
-         .offset       = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
-};
-
-static int __init
-init_arctic_mtd(void)
-{
-       int err;
-
-       printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
-
-       arctic_mtd_map.virt = ioremap(PADDR, SIZE);
-
-       if (!arctic_mtd_map.virt) {
-               printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
-               return -EIO;
-       }
-       simple_map_init(&arctic_mtd_map);
-
-       printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
-       arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
-
-       if (!arctic_mtd) {
-               iounmap(arctic_mtd_map.virt);
-               return -ENXIO;
-       }
-
-       arctic_mtd->owner = THIS_MODULE;
-
-       err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
-       if (err) {
-               printk("%s: add_mtd_partitions failed\n", NAME);
-               iounmap(arctic_mtd_map.virt);
-       }
-
-       return err;
-}
-
-static void __exit
-cleanup_arctic_mtd(void)
-{
-       if (arctic_mtd) {
-               del_mtd_partitions(arctic_mtd);
-               map_destroy(arctic_mtd);
-               iounmap((void *) arctic_mtd_map.virt);
-       }
-}
-
-module_init(init_arctic_mtd);
-module_exit(cleanup_arctic_mtd);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Gibson <arctic@gibson.dropbear.id.au>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards");
diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c
deleted file mode 100644 (file)
index d76d598..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $
- *
- * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
- *                              IBM 405LP Beech boards.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright (C) 2002, International Business Machines Corporation
- * All Rights Reserved.
- *
- * Bishop Brock
- * IBM Research, Austin Center for Low-Power Computing
- * bcbrock@us.ibm.com
- * March 2002
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-
-#define NAME     "Beech Linux Flash"
-#define PADDR    BEECH_BIGFLASH_PADDR
-#define SIZE     BEECH_BIGFLASH_SIZE
-#define BUSWIDTH 1
-
-/* Flash memories on these boards are memory resources, accessed big-endian. */
-
-
-static struct map_info beech_mtd_map = {
-       .name =         NAME,
-       .size =         SIZE,
-       .bankwidth =    BUSWIDTH,
-       .phys =         PADDR
-};
-
-static struct mtd_info *beech_mtd;
-
-static struct mtd_partition beech_partitions[2] = {
-       {
-             .name = "Linux Kernel",
-             .size = BEECH_KERNEL_SIZE,
-             .offset = BEECH_KERNEL_OFFSET
-       }, {
-             .name = "Free Area",
-             .size = BEECH_FREE_AREA_SIZE,
-             .offset = BEECH_FREE_AREA_OFFSET
-       }
-};
-
-static int __init
-init_beech_mtd(void)
-{
-       int err;
-
-       printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
-
-       beech_mtd_map.virt = ioremap(PADDR, SIZE);
-
-       if (!beech_mtd_map.virt) {
-               printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
-               return -EIO;
-       }
-
-       simple_map_init(&beech_mtd_map);
-
-       printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
-       beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
-
-       if (!beech_mtd) {
-               iounmap(beech_mtd_map.virt);
-               return -ENXIO;
-       }
-
-       beech_mtd->owner = THIS_MODULE;
-
-       err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
-       if (err) {
-               printk("%s: add_mtd_partitions failed\n", NAME);
-               iounmap(beech_mtd_map.virt);
-       }
-
-       return err;
-}
-
-static void __exit
-cleanup_beech_mtd(void)
-{
-       if (beech_mtd) {
-               del_mtd_partitions(beech_mtd);
-               map_destroy(beech_mtd);
-               iounmap((void *) beech_mtd_map.virt);
-       }
-}
-
-module_init(init_beech_mtd);
-module_exit(cleanup_beech_mtd);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bishop Brock <bcbrock@us.ibm.com>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards");
index 9f53c655af3a9e18f1d7c1e9d6a07fb4ade7a824..7b96cd02f82b37c08a4ed0faad6c07b189aa11a3 100644 (file)
@@ -358,7 +358,7 @@ int __init nettel_init(void)
        /* Turn other PAR off so the first probe doesn't find it */
        *intel1par = 0;
 
-       /* Probe for the the size of the first Intel flash */
+       /* Probe for the size of the first Intel flash */
        nettel_intel_map.size = maxsize;
        nettel_intel_map.phys = intel0addr;
        nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
index 7efe744ad31e63c20fadef5c0cfc474e476d6658..bbb42c35b69b9df05a108f21b0d837f80ca3d7e6 100644 (file)
@@ -48,7 +48,7 @@ static int parse_flash_partitions(struct device_node *node,
        const  u32  *part;
        const  char *name;
 
-       part = get_property(node, "partitions", &plen);
+       part = of_get_property(node, "partitions", &plen);
        if (part == NULL)
                goto err;
 
@@ -59,7 +59,7 @@ static int parse_flash_partitions(struct device_node *node,
                goto err;
        }
 
-       name = get_property(node, "partition-names", &plen);
+       name = of_get_property(node, "partition-names", &plen);
 
        for (i = 0; i < retval; i++) {
                (*parts)[i].offset = *part++;
@@ -153,7 +153,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
                goto err_out;
        }
 
-       width = get_property(dp, "bank-width", NULL);
+       width = of_get_property(dp, "bank-width", NULL);
        if (width == NULL) {
                dev_err(&dev->dev, "Can't get the flash bank width!\n");
                err = -EINVAL;
@@ -174,7 +174,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
 
        simple_map_init(&info->map);
 
-       of_probe = get_property(dp, "probe-type", NULL);
+       of_probe = of_get_property(dp, "probe-type", NULL);
        if (of_probe == NULL) {
                probe_type = rom_probe_types;
                for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
@@ -186,7 +186,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
        else {
                if (strcmp(of_probe, "ROM"))
                        dev_dbg(&dev->dev, "map_probe: don't know probe type "
-                       "'%s', mapping as rom\n");
+                       "'%s', mapping as rom\n", of_probe);
                info->mtd = do_map_probe("mtd_rom", &info->map);
        }
        if (info->mtd == NULL) {
index 524b83b5ebf5985bb4420a6cdd5f8fc65d69b356..51bc7e2f1f22d61c735afc81b58f2f7ad35b777c 100644 (file)
@@ -216,7 +216,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        int last_devnum = -1;
        struct gendisk *gd;
 
-       if (!!mutex_trylock(&mtd_table_mutex)) {
+       if (mutex_trylock(&mtd_table_mutex)) {
                mutex_unlock(&mtd_table_mutex);
                BUG();
        }
@@ -294,7 +294,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 {
-       if (!!mutex_trylock(&mtd_table_mutex)) {
+       if (mutex_trylock(&mtd_table_mutex)) {
                mutex_unlock(&mtd_table_mutex);
                BUG();
        }
index 1af989023c6644ca89c8e4107c21fcde8137904d..9c6236852942ec7e98441c5a333c1786a0e83a0c 100644 (file)
@@ -347,7 +347,6 @@ int add_mtd_partitions(struct mtd_info *master,
                slave->mtd.subpage_sft = master->subpage_sft;
 
                slave->mtd.name = parts[i].name;
-               slave->mtd.bank_size = master->bank_size;
                slave->mtd.owner = master->owner;
 
                slave->mtd.read = part_read;
index d05873b8c155a8f8c478fc86cd522ca792441451..f1d60b6f048e6f08aa855e19fed1337a292cfe79 100644 (file)
@@ -232,11 +232,13 @@ config MTD_NAND_BASLER_EXCITE
           will be named "excite_nandflash.ko".
 
 config MTD_NAND_CAFE
-       tristate "NAND support for OLPC CAFÉ chip"
-       depends on PCI
-       help
-        Use NAND flash attached to the CAFÉ chip designed for the $100
-        laptop.
+       tristate "NAND support for OLPC CAFÉ chip"
+       depends on PCI
+       select REED_SOLOMON
+       select REED_SOLOMON_DEC16
+       help
+         Use NAND flash attached to the CAFÉ chip designed for the $100
+         laptop.
 
 config MTD_NAND_CS553X
        tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
@@ -270,4 +272,13 @@ config MTD_NAND_NANDSIM
          The simulator may simulate various NAND flash chips for the
          MTD nand layer.
 
+config MTD_NAND_PLATFORM
+       tristate "Support for generic platform NAND driver"
+       depends on MTD_NAND
+       help
+         This implements a generic NAND driver for on-SOC platform
+         devices. You will need to provide platform-specific functions
+         via platform_data.
+
+
 endif # MTD_NAND
index 6872031a3fb25ff45d4e263691133d4698d94c8f..edba1db14bfad6581260b822b60a260063fc542c 100644 (file)
@@ -26,6 +26,6 @@ obj-$(CONFIG_MTD_NAND_NDFC)           += ndfc.o
 obj-$(CONFIG_MTD_NAND_AT91)            += at91_nand.o
 obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
+obj-$(CONFIG_MTD_NAND_PLATFORM)                += plat_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
-cafe_nand-objs := cafe.o cafe_ecc.o
index 14b80cc90a7b789d7af4efe96b549bb105f87e22..512e999177f70cb39c745ac6d454d22e6a4c3bae 100644 (file)
@@ -82,6 +82,10 @@ static void at91_nand_disable(struct at91_nand_host *host)
                at91_set_gpio_value(host->board->enable_pin, 1);
 }
 
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
 /*
  * Probe for the NAND device.
  */
@@ -151,6 +155,12 @@ static int __init at91_nand_probe(struct platform_device *pdev)
 #ifdef CONFIG_MTD_PARTITIONS
        if (host->board->partition_info)
                partitions = host->board->partition_info(mtd->size, &num_partitions);
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+       else {
+               mtd->name = "at91_nand";
+               num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
+       }
+#endif
 
        if ((!partitions) || (num_partitions == 0)) {
                printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
deleted file mode 100644 (file)
index ea5c849..0000000
+++ /dev/null
@@ -1,1381 +0,0 @@
-/* Error correction for CAFÉ NAND controller
- *
- * © 2006 Marvell, Inc.
- * Author: Tom Chiou
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-
-static unsigned short gf4096_mul(unsigned short, unsigned short);
-static unsigned short gf64_mul(unsigned short, unsigned short);
-static unsigned short gf4096_inv(unsigned short);
-static unsigned short err_pos(unsigned short);
-static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
-                               unsigned short, unsigned short, unsigned short,
-                               unsigned short, unsigned short, unsigned short *);
-static void zero_4x5_col3(unsigned short[4][5]);
-static void zero_4x5_col2(unsigned short[4][5]);
-static void zero_4x5_col1(unsigned short[4][5]);
-static void swap_4x5_rows(unsigned short[4][5], int, int, int);
-static void swap_2x3_rows(unsigned short m[2][3]);
-static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
-static void sort_coefs(int *, unsigned short *, int);
-static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
-                              unsigned short, unsigned short, unsigned short,
-                              unsigned short, unsigned short, unsigned short *);
-static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
-                               unsigned short, unsigned short, unsigned short,
-                               unsigned short *);
-static void zero_3x4_col2(unsigned short[3][4]);
-static void zero_3x4_col1(unsigned short[3][4]);
-static void swap_3x4_rows(unsigned short[3][4], int, int, int);
-static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
-static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
-                              unsigned short, unsigned short, unsigned short,
-                              unsigned short *);
-
-static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
-                              unsigned short, unsigned short *);
-static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
-                         unsigned short, unsigned short, unsigned short,
-                         unsigned short *);
-static void solve_2x3(unsigned short[2][3], unsigned short *);
-static int chk_no_err_only(unsigned short *, unsigned short *);
-static int chk_1_err_only(unsigned short *, unsigned short *);
-static int chk_2_err_only(unsigned short *, unsigned short *);
-static int chk_3_err_only(unsigned short *, unsigned short *);
-static int chk_4_err_only(unsigned short *, unsigned short *);
-
-static unsigned short gf64_mul(unsigned short a, unsigned short b)
-{
-       unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
-       unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
-
-       tmp1 = ((a) ^ (a >> 5));
-       tmp2 = ((a >> 4) ^ (a >> 5));
-       tmp3 = ((a >> 3) ^ (a >> 4));
-       tmp4 = ((a >> 2) ^ (a >> 3));
-       tmp5 = ((a >> 1) ^ (a >> 2));
-
-       c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
-                 ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
-
-       c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
-                 (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
-
-       c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
-                 (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
-
-       c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
-                 (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
-
-       c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
-                 ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
-
-       c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
-                 ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
-
-       c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
-
-       return c;
-}
-
-static unsigned short gf4096_mul(unsigned short a, unsigned short b)
-{
-       unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
-
-       ah = (a >> 6) & 0x3f;
-       al = a & 0x3f;
-       bh = (b >> 6) & 0x3f;
-       bl = b & 0x3f;
-       alxah = al ^ ah;
-       blxbh = bl ^ bh;
-
-       ablh = gf64_mul(alxah, blxbh);
-       albl = gf64_mul(al, bl);
-       ahbh = gf64_mul(ah, bh);
-
-       ahbhB = ((ahbh & 0x1) << 5) |
-           ((ahbh & 0x20) >> 1) |
-           ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
-
-       c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
-       return c;
-}
-
-static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
-{
-       find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
-}
-
-static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
-                               unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
-{
-       unsigned short m[3][4];
-       int row_order[3];
-
-       row_order[0] = 0;
-       row_order[1] = 1;
-       row_order[2] = 2;
-       m[0][0] = s2;
-       m[0][1] = s1;
-       m[0][2] = s0;
-       m[0][3] = s3;
-       m[1][0] = s3;
-       m[1][1] = s2;
-       m[1][2] = s1;
-       m[1][3] = s4;
-       m[2][0] = s4;
-       m[2][1] = s3;
-       m[2][2] = s2;
-       m[2][3] = s5;
-
-       if (m[0][2] != 0x0) {
-               zero_3x4_col2(m);
-       } else if (m[1][2] != 0x0) {
-               swap_3x4_rows(m, 0, 1, 4);
-               zero_3x4_col2(m);
-       } else if (m[2][2] != 0x0) {
-               swap_3x4_rows(m, 0, 2, 4);
-               zero_3x4_col2(m);
-       } else {
-               printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
-       }
-
-       if (m[1][1] != 0x0) {
-               zero_3x4_col1(m);
-       } else if (m[2][1] != 0x0) {
-               swap_3x4_rows(m, 1, 2, 4);
-               zero_3x4_col1(m);
-       } else {
-               printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
-       }
-
-       /* solve coefs */
-       solve_3x4(m, coefs, row_order);
-}
-
-static void zero_3x4_col2(unsigned short m[3][4])
-{
-       unsigned short minv1, minv2;
-
-       minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
-       minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
-       m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
-       m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
-       m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
-       m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
-       m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
-       m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
-}
-
-static void zero_3x4_col1(unsigned short m[3][4])
-{
-       unsigned short minv;
-       minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
-       m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
-       m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
-}
-
-static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
-{
-       unsigned short tmp0;
-       int cnt;
-       for (cnt = 0; cnt < col_width; cnt++) {
-               tmp0 = m[i][cnt];
-               m[i][cnt] = m[j][cnt];
-               m[j][cnt] = tmp0;
-       }
-}
-
-static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
-{
-       unsigned short tmp[3];
-       tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
-       tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
-       tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
-       sort_coefs(row_order, tmp, 3);
-       coefs[0] = tmp[0];
-       coefs[1] = tmp[1];
-       coefs[2] = tmp[2];
-}
-
-static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
-                              unsigned short s2, unsigned short r0,
-                              unsigned short r1, unsigned short r2,
-                              unsigned short *pats)
-{
-       find_2x2_soln(r0 ^ r2, r1 ^ r2,
-                     gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
-                     gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
-       pats[2] = s0 ^ pats[0] ^ pats[1];
-}
-
-static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
-                               unsigned short s2, unsigned short s3,
-                               unsigned short s4, unsigned short s5,
-                               unsigned short s6, unsigned short s7,
-                               unsigned short *coefs)
-{
-       unsigned short m[4][5];
-       int row_order[4];
-
-       row_order[0] = 0;
-       row_order[1] = 1;
-       row_order[2] = 2;
-       row_order[3] = 3;
-
-       m[0][0] = s3;
-       m[0][1] = s2;
-       m[0][2] = s1;
-       m[0][3] = s0;
-       m[0][4] = s4;
-       m[1][0] = s4;
-       m[1][1] = s3;
-       m[1][2] = s2;
-       m[1][3] = s1;
-       m[1][4] = s5;
-       m[2][0] = s5;
-       m[2][1] = s4;
-       m[2][2] = s3;
-       m[2][3] = s2;
-       m[2][4] = s6;
-       m[3][0] = s6;
-       m[3][1] = s5;
-       m[3][2] = s4;
-       m[3][3] = s3;
-       m[3][4] = s7;
-
-       if (m[0][3] != 0x0) {
-               zero_4x5_col3(m);
-       } else if (m[1][3] != 0x0) {
-               swap_4x5_rows(m, 0, 1, 5);
-               zero_4x5_col3(m);
-       } else if (m[2][3] != 0x0) {
-               swap_4x5_rows(m, 0, 2, 5);
-               zero_4x5_col3(m);
-       } else if (m[3][3] != 0x0) {
-               swap_4x5_rows(m, 0, 3, 5);
-               zero_4x5_col3(m);
-       } else {
-               printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
-       }
-
-       if (m[1][2] != 0x0) {
-               zero_4x5_col2(m);
-       } else if (m[2][2] != 0x0) {
-               swap_4x5_rows(m, 1, 2, 5);
-               zero_4x5_col2(m);
-       } else if (m[3][2] != 0x0) {
-               swap_4x5_rows(m, 1, 3, 5);
-               zero_4x5_col2(m);
-       } else {
-               printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
-       }
-
-       if (m[2][1] != 0x0) {
-               zero_4x5_col1(m);
-       } else if (m[3][1] != 0x0) {
-               swap_4x5_rows(m, 2, 3, 5);
-               zero_4x5_col1(m);
-       } else {
-               printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
-       }
-
-       solve_4x5(m, coefs, row_order);
-}
-
-static void zero_4x5_col3(unsigned short m[4][5])
-{
-       unsigned short minv1, minv2, minv3;
-
-       minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
-       minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
-       minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
-
-       m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
-       m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
-       m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
-       m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
-       m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
-       m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
-       m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
-       m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
-       m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
-       m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
-       m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
-       m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
-}
-
-static void zero_4x5_col2(unsigned short m[4][5])
-{
-       unsigned short minv2, minv3;
-
-       minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
-       minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
-
-       m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
-       m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
-       m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
-       m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
-       m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
-       m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
-}
-
-static void zero_4x5_col1(unsigned short m[4][5])
-{
-       unsigned short minv;
-
-       minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
-
-       m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
-       m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
-}
-
-static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
-{
-       unsigned short tmp0;
-       int cnt;
-
-       for (cnt = 0; cnt < col_width; cnt++) {
-               tmp0 = m[i][cnt];
-               m[i][cnt] = m[j][cnt];
-               m[j][cnt] = tmp0;
-       }
-}
-
-static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
-{
-       unsigned short tmp[4];
-
-       tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
-       tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
-       tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
-       tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
-                       gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
-       sort_coefs(row_order, tmp, 4);
-       coefs[0] = tmp[0];
-       coefs[1] = tmp[1];
-       coefs[2] = tmp[2];
-       coefs[3] = tmp[3];
-}
-
-static void sort_coefs(int *order, unsigned short *soln, int len)
-{
-       int cnt, start_cnt, least_ord, least_cnt;
-       unsigned short tmp0;
-       for (start_cnt = 0; start_cnt < len; start_cnt++) {
-               for (cnt = start_cnt; cnt < len; cnt++) {
-                       if (cnt == start_cnt) {
-                               least_ord = order[cnt];
-                               least_cnt = start_cnt;
-                       } else {
-                               if (least_ord > order[cnt]) {
-                                       least_ord = order[cnt];
-                                       least_cnt = cnt;
-                               }
-                       }
-               }
-               if (least_cnt != start_cnt) {
-                       tmp0 = order[least_cnt];
-                       order[least_cnt] = order[start_cnt];
-                       order[start_cnt] = tmp0;
-                       tmp0 = soln[least_cnt];
-                       soln[least_cnt] = soln[start_cnt];
-                       soln[start_cnt] = tmp0;
-               }
-       }
-}
-
-static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
-                              unsigned short s2, unsigned short s3,
-                              unsigned short z1, unsigned short z2,
-                              unsigned short z3, unsigned short z4,
-                              unsigned short *pats)
-{
-       unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
-               z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
-       unsigned short tmp0, tmp1, tmp2, tmp3;
-
-       z4_z1 = z4 ^ z1;
-       z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
-       z4_z2 = z4 ^ z2;
-       s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
-       z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
-       z4_z3 = z4 ^ z3;
-       z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
-       s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
-       z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
-       z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
-       z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
-       s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
-
-       //find err pat 0,1
-       find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
-                     gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
-                                                              z3z4_z3z3) ^
-                     gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
-                                                              z3z3z4_z3z3z3) ^
-                     gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
-                     gf4096_mul(z2z4_z2z2,
-                                z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
-                                                            z3z4_z3z3),
-                     gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
-                                                                 z4_z3),
-                     gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
-       tmp0 = pats[0];
-       tmp1 = pats[1];
-       tmp2 = pats[0] ^ pats[1] ^ s0;
-       tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
-
-       //find err pat 2,3
-       find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
-       pats[2] = pats[0];
-       pats[3] = pats[1];
-       pats[0] = tmp0;
-       pats[1] = tmp1;
-}
-
-static void find_2x2_soln(unsigned short c00, unsigned short c01,
-                         unsigned short c10, unsigned short c11,
-                         unsigned short lval0, unsigned short lval1,
-                         unsigned short *soln)
-{
-       unsigned short m[2][3];
-       m[0][0] = c00;
-       m[0][1] = c01;
-       m[0][2] = lval0;
-       m[1][0] = c10;
-       m[1][1] = c11;
-       m[1][2] = lval1;
-
-       if (m[0][1] != 0x0) {
-               /* */
-       } else if (m[1][1] != 0x0) {
-               swap_2x3_rows(m);
-       } else {
-               printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
-       }
-
-       solve_2x3(m, soln);
-}
-
-static void swap_2x3_rows(unsigned short m[2][3])
-{
-       unsigned short tmp0;
-       int cnt;
-
-       for (cnt = 0; cnt < 3; cnt++) {
-               tmp0 = m[0][cnt];
-               m[0][cnt] = m[1][cnt];
-               m[1][cnt] = tmp0;
-       }
-}
-
-static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
-{
-       unsigned short minv;
-
-       minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
-       m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
-       m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
-       coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
-       coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
-}
-
-static unsigned char gf64_inv[64] = {
-        0,  1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
-       61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45,  6,
-       63,  2, 27, 21, 56,  9, 50, 19, 13, 47, 48,  5,  7, 30, 12, 41,
-       42,  4, 38, 18, 10, 29, 17, 60, 36,  8, 59, 58, 55, 16,  3, 32
-};
-
-static unsigned short gf4096_inv(unsigned short din)
-{
-       unsigned short alahxal, ah2B, deno, inv, bl, bh;
-       unsigned short ah, al, ahxal;
-       unsigned short dout;
-
-       ah = (din >> 6) & 0x3f;
-       al = din & 0x3f;
-       ahxal = ah ^ al;
-       ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
-               ((ah >> 1) & 0x10) |
-               ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
-               ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
-       alahxal = gf64_mul(ahxal, al);
-       deno = alahxal ^ ah2B;
-       inv = gf64_inv[deno];
-       bl = gf64_mul(inv, ahxal);
-       bh = gf64_mul(inv, ah);
-       dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
-       return (((bh & 0x3f) << 6) | (bl & 0x3f));
-}
-
-static unsigned short err_pos_lut[4096] = {
-       0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
-       0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
-       0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
-       0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
-       0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
-       0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
-       0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
-       0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
-       0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
-       0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
-       0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
-       0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
-       0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
-       0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
-       0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
-       0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
-       0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
-       0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
-       0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
-       0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
-       0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
-       0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
-       0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
-       0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
-       0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
-       0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
-       0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
-       0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
-       0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
-       0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
-       0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
-       0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
-       0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
-       0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
-       0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
-       0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
-       0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
-       0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
-       0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
-       0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
-       0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
-       0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
-       0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
-       0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
-       0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
-       0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
-       0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
-       0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
-       0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
-       0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
-       0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
-       0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
-       0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
-       0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
-       0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
-       0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
-       0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
-       0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
-       0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
-       0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
-       0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
-       0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
-       0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
-       0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
-       0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
-       0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
-       0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
-       0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
-       0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
-       0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
-       0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
-       0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
-       0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
-       0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
-       0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
-       0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
-       0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
-       0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
-       0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
-       0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
-       0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
-       0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
-       0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
-       0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
-       0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
-       0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
-       0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
-       0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
-       0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
-       0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
-       0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
-       0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
-       0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
-       0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
-       0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
-       0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
-       0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
-       0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
-       0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
-       0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
-       0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
-       0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
-       0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
-       0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
-       0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
-       0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
-       0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
-       0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
-       0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
-       0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
-       0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
-       0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
-       0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
-       0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
-       0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
-       0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
-       0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
-       0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
-       0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
-       0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
-       0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
-       0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
-       0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
-       0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
-       0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
-       0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
-       0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
-       0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
-       0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
-       0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
-       0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
-       0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
-       0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
-       0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
-       0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
-       0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
-       0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
-       0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
-       0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
-       0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
-       0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
-       0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
-       0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
-       0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
-       0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
-       0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
-       0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
-       0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
-       0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
-       0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
-       0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
-       0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
-       0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
-       0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
-       0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
-       0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
-       0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
-       0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
-       0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
-       0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
-       0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
-       0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
-       0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
-       0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
-       0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
-       0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
-       0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
-       0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
-       0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
-       0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
-       0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
-       0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
-       0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
-       0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
-       0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
-       0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
-       0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
-       0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
-       0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
-       0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
-       0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
-       0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
-       0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
-       0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
-       0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
-       0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
-       0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
-       0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
-       0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
-       0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
-       0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
-       0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
-       0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
-       0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
-       0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
-       0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
-       0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
-       0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
-       0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
-       0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
-       0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
-       0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
-       0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
-       0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
-       0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
-       0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
-       0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
-       0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
-       0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
-       0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
-       0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
-       0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
-       0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
-       0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
-       0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
-       0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
-       0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
-       0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
-       0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
-       0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
-       0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
-       0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
-       0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
-       0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
-       0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
-       0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
-       0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
-       0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
-       0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
-       0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
-       0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
-       0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
-       0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
-       0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
-       0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
-       0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
-       0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
-       0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
-       0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
-       0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
-       0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
-       0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
-       0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
-       0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
-       0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
-       0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
-       0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
-       0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
-       0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
-       0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
-       0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
-       0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
-       0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
-       0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
-       0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
-       0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
-       0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
-       0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
-       0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
-       0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
-       0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
-       0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
-       0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
-       0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
-       0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
-       0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
-       0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
-       0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
-       0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
-       0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
-       0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-       0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
-       0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
-       0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
-       0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
-       0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
-       0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
-       0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
-};
-
-static unsigned short err_pos(unsigned short din)
-{
-       BUG_ON(din >= ARRAY_SIZE(err_pos_lut));
-       return err_pos_lut[din];
-}
-static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-       if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
-            chk_syndrome_list[2] | chk_syndrome_list[3] |
-            chk_syndrome_list[4] | chk_syndrome_list[5] |
-            chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
-               return -EINVAL;
-       } else {
-               err_info[0] = 0x0;
-               return 0;
-       }
-}
-static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-       unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
-       tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
-       tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
-       tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
-       tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
-       tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
-       tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
-       tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
-       if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
-               err_info[0] = 0x1;      // encode 1-symbol error as 0x1
-               err_info[1] = err_pos(tmp0);
-               err_info[1] = (unsigned short)(0x55e - err_info[1]);
-               err_info[5] = chk_syndrome_list[0];
-               return 0;
-       } else
-               return -EINVAL;
-}
-static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-       unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
-       unsigned short coefs[4];
-       unsigned short err_pats[4];
-       int found_num_root = 0;
-       unsigned short bit2_root0, bit2_root1;
-       unsigned short bit2_root0_inv, bit2_root1_inv;
-       unsigned short err_loc_eqn, test_root;
-       unsigned short bit2_loc0, bit2_loc1;
-       unsigned short bit2_pat0, bit2_pat1;
-
-       find_2x2_soln(chk_syndrome_list[1],
-                     chk_syndrome_list[0],
-                     chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
-       for (test_root = 0x1; test_root < 0xfff; test_root++) {
-               err_loc_eqn =
-                   gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
-               if (err_loc_eqn == 0x0) {
-                       if (found_num_root == 0) {
-                               bit2_root0 = test_root;
-                               found_num_root = 1;
-                       } else if (found_num_root == 1) {
-                               bit2_root1 = test_root;
-                               found_num_root = 2;
-                               break;
-                       }
-               }
-       }
-       if (found_num_root != 2)
-               return -EINVAL;
-       else {
-               bit2_root0_inv = gf4096_inv(bit2_root0);
-               bit2_root1_inv = gf4096_inv(bit2_root1);
-               find_2bit_err_pats(chk_syndrome_list[0],
-                                  chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
-               bit2_pat0 = err_pats[0];
-               bit2_pat1 = err_pats[1];
-               //for(x+1)
-               tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv));      //rinv0^4
-               tmp1 = gf4096_mul(bit2_root0_inv, tmp0);        //rinv0^5
-               tmp2 = gf4096_mul(bit2_root0_inv, tmp1);        //rinv0^6
-               tmp3 = gf4096_mul(bit2_root0_inv, tmp2);        //rinv0^7
-               tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv));      //rinv1^4
-               tmp5 = gf4096_mul(bit2_root1_inv, tmp4);        //rinv1^5
-               tmp6 = gf4096_mul(bit2_root1_inv, tmp5);        //rinv1^6
-               tmp7 = gf4096_mul(bit2_root1_inv, tmp6);        //rinv1^7
-               //check if only 2-bit error
-               if ((chk_syndrome_list[4] ==
-                    (gf4096_mul(bit2_pat0, tmp0) ^
-                     gf4096_mul(bit2_pat1,
-                                tmp4))) & (chk_syndrome_list[5] ==
-                                           (gf4096_mul(bit2_pat0, tmp1) ^
-                                            gf4096_mul(bit2_pat1,
-                                                       tmp5))) &
-                   (chk_syndrome_list[6] ==
-                    (gf4096_mul(bit2_pat0, tmp2) ^
-                     gf4096_mul(bit2_pat1,
-                                tmp6))) & (chk_syndrome_list[7] ==
-                                           (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
-                       if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
-                               return -EINVAL;
-                       } else {
-                               bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
-                               bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
-                               err_info[0] = 0x2;      // encode 2-symbol error as 0x2
-                               err_info[1] = bit2_loc0;
-                               err_info[2] = bit2_loc1;
-                               err_info[5] = bit2_pat0;
-                               err_info[6] = bit2_pat1;
-                               return 0;
-                       }
-               } else
-                       return -EINVAL;
-       }
-}
-static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-       unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
-       unsigned short coefs[4];
-       unsigned short err_pats[4];
-       int found_num_root = 0;
-       unsigned short bit3_root0, bit3_root1, bit3_root2;
-       unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
-       unsigned short err_loc_eqn, test_root;
-
-       find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
-                           chk_syndrome_list[2], chk_syndrome_list[3],
-                           chk_syndrome_list[4], chk_syndrome_list[5], coefs);
-
-       for (test_root = 0x1; test_root < 0xfff; test_root++) {
-               err_loc_eqn = gf4096_mul(coefs[2],
-                                        gf4096_mul(gf4096_mul(test_root, test_root),
-                                                   test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
-                       ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
-
-               if (err_loc_eqn == 0x0) {
-                       if (found_num_root == 0) {
-                               bit3_root0 = test_root;
-                               found_num_root = 1;
-                       } else if (found_num_root == 1) {
-                               bit3_root1 = test_root;
-                               found_num_root = 2;
-                       } else if (found_num_root == 2) {
-                               bit3_root2 = test_root;
-                               found_num_root = 3;
-                               break;
-                       }
-               }
-       }
-       if (found_num_root != 3)
-               return -EINVAL;
-       else {
-               bit3_root0_inv = gf4096_inv(bit3_root0);
-               bit3_root1_inv = gf4096_inv(bit3_root1);
-               bit3_root2_inv = gf4096_inv(bit3_root2);
-
-               find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
-                                  chk_syndrome_list[2], bit3_root0_inv,
-                                  bit3_root1_inv, bit3_root2_inv, err_pats);
-
-               //check if only 3-bit error
-               tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
-               tmp0 = gf4096_mul(tmp0, tmp0);
-               tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
-               tmp0 = gf4096_mul(tmp0, bit3_root0_inv);        //rinv0^6
-               tmp1 = gf4096_mul(tmp0, bit3_root0_inv);        //rinv0^7
-               tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
-               tmp2 = gf4096_mul(tmp2, tmp2);
-               tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
-               tmp2 = gf4096_mul(tmp2, bit3_root1_inv);        //rinv1^6
-               tmp3 = gf4096_mul(tmp2, bit3_root1_inv);        //rinv1^7
-               tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
-               tmp4 = gf4096_mul(tmp4, tmp4);
-               tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
-               tmp4 = gf4096_mul(tmp4, bit3_root2_inv);        //rinv2^6
-               tmp5 = gf4096_mul(tmp4, bit3_root2_inv);        //rinv2^7
-
-               //check if only 3 errors
-               if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
-                                             gf4096_mul(err_pats[1], tmp2) ^
-                                             gf4096_mul(err_pats[2], tmp4))) &
-                   (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
-                                             gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
-                       if ((err_pos(bit3_root0_inv) == 0xfff) |
-                           (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
-                               return -EINVAL;
-                       } else {
-                               err_info[0] = 0x3;
-                               err_info[1] = (0x55e - err_pos(bit3_root0_inv));
-                               err_info[2] = (0x55e - err_pos(bit3_root1_inv));
-                               err_info[3] = (0x55e - err_pos(bit3_root2_inv));
-                               err_info[5] = err_pats[0];
-                               err_info[6] = err_pats[1];
-                               err_info[7] = err_pats[2];
-                               return 0;
-                       }
-               } else
-                       return -EINVAL;
-       }
-}
-static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-       unsigned short coefs[4];
-       unsigned short err_pats[4];
-       int found_num_root = 0;
-       unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
-       unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
-       unsigned short err_loc_eqn, test_root;
-
-       find_4bit_err_coefs(chk_syndrome_list[0],
-                           chk_syndrome_list[1],
-                           chk_syndrome_list[2],
-                           chk_syndrome_list[3],
-                           chk_syndrome_list[4],
-                           chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
-
-       for (test_root = 0x1; test_root < 0xfff; test_root++) {
-               err_loc_eqn =
-                   gf4096_mul(coefs[3],
-                              gf4096_mul(gf4096_mul
-                                         (gf4096_mul(test_root, test_root),
-                                          test_root),
-                                         test_root)) ^ gf4096_mul(coefs[2],
-                                                                  gf4096_mul
-                                                                  (gf4096_mul(test_root, test_root), test_root))
-                   ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
-                   ^ 0x1;
-               if (err_loc_eqn == 0x0) {
-                       if (found_num_root == 0) {
-                               bit4_root0 = test_root;
-                               found_num_root = 1;
-                       } else if (found_num_root == 1) {
-                               bit4_root1 = test_root;
-                               found_num_root = 2;
-                       } else if (found_num_root == 2) {
-                               bit4_root2 = test_root;
-                               found_num_root = 3;
-                       } else {
-                               found_num_root = 4;
-                               bit4_root3 = test_root;
-                               break;
-                       }
-               }
-       }
-       if (found_num_root != 4) {
-               return -EINVAL;
-       } else {
-               bit4_root0_inv = gf4096_inv(bit4_root0);
-               bit4_root1_inv = gf4096_inv(bit4_root1);
-               bit4_root2_inv = gf4096_inv(bit4_root2);
-               bit4_root3_inv = gf4096_inv(bit4_root3);
-               find_4bit_err_pats(chk_syndrome_list[0],
-                                  chk_syndrome_list[1],
-                                  chk_syndrome_list[2],
-                                  chk_syndrome_list[3],
-                                  bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
-               err_info[0] = 0x4;
-               err_info[1] = (0x55e - err_pos(bit4_root0_inv));
-               err_info[2] = (0x55e - err_pos(bit4_root1_inv));
-               err_info[3] = (0x55e - err_pos(bit4_root2_inv));
-               err_info[4] = (0x55e - err_pos(bit4_root3_inv));
-               err_info[5] = err_pats[0];
-               err_info[6] = err_pats[1];
-               err_info[7] = err_pats[2];
-               err_info[8] = err_pats[3];
-               return 0;
-       }
-}
-
-void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
-                         unsigned short val)
-{
-       if (unlikely(sym > 1366)) {
-               printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
-       } else if (sym == 0) {
-               buf[0] ^= val;
-       } else if (sym & 1) {
-               buf[1+(3*(sym-1))/2] ^= (val >> 4);
-               buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
-       } else {
-               buf[2+(3*(sym-2))/2] ^= (val >> 8);
-               buf[3+(3*(sym-2))/2] ^= (val & 0xff);
-       }
-}
-
-static int debugecc = 0;
-module_param(debugecc, int, 0644);
-
-int cafe_correct_ecc(unsigned char *buf,
-                    unsigned short *chk_syndrome_list)
-{
-       unsigned short err_info[9];
-       int i;
-
-       if (debugecc) {
-               printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n",
-                      chk_syndrome_list[0], chk_syndrome_list[1],
-                      chk_syndrome_list[2], chk_syndrome_list[3],
-                      chk_syndrome_list[4], chk_syndrome_list[5],
-                      chk_syndrome_list[6], chk_syndrome_list[7]);
-               for (i=0; i < 2048; i+=16) {
-                       printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                              i,
-                              buf[i], buf[i+1], buf[i+2], buf[i+3],
-                              buf[i+4], buf[i+5], buf[i+6], buf[i+7],
-                              buf[i+8], buf[i+9], buf[i+10], buf[i+11],
-                              buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
-               }
-               for ( ; i < 2112; i+=16) {
-                       printk(KERN_WARNING "O   %02x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                              i - 2048,
-                              buf[i], buf[i+1], buf[i+2], buf[i+3],
-                              buf[i+4], buf[i+5], buf[i+6], buf[i+7],
-                              buf[i+8], buf[i+9], buf[i+10], buf[i+11],
-                              buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
-               }
-       }
-
-
-
-       if (chk_no_err_only(chk_syndrome_list, err_info) &&
-           chk_1_err_only(chk_syndrome_list, err_info) &&
-           chk_2_err_only(chk_syndrome_list, err_info) &&
-           chk_3_err_only(chk_syndrome_list, err_info) &&
-           chk_4_err_only(chk_syndrome_list, err_info)) {
-               return -EIO;
-       }
-
-       for (i=0; i < err_info[0]; i++) {
-               if (debugecc)
-                       printk(KERN_WARNING "Correct symbol %d with 0x%03x\n",
-                              err_info[1+i], err_info[5+i]);
-
-               correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
-       }
-
-       return err_info[0];
-}
-
similarity index 88%
rename from drivers/mtd/nand/cafe.c
rename to drivers/mtd/nand/cafe_nand.c
index c328a7514510d836e843b6657e4bf1f71340389b..cff969d05d4a1824cb18fda1808f89a9f9700000 100644 (file)
@@ -11,6 +11,7 @@
 #undef DEBUG
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/rslib.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #define CAFE_GLOBAL_IRQ_MASK   0x300c
 #define CAFE_NAND_RESET                0x3034
 
-int cafe_correct_ecc(unsigned char *buf,
-                    unsigned short *chk_syndrome_list);
+/* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */
+#define CTRL1_CHIPSELECT       (1<<19)
 
 struct cafe_priv {
        struct nand_chip nand;
        struct pci_dev *pdev;
        void __iomem *mmio;
+       struct rs_control *rs;
        uint32_t ctl1;
        uint32_t ctl2;
        int datalen;
@@ -195,8 +197,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
        cafe->data_pos = cafe->datalen = 0;
 
-       /* Set command valid bit */
-       ctl1 = 0x80000000 | command;
+       /* Set command valid bit, mask in the chip select bit  */
+       ctl1 = 0x80000000 | command | (cafe->ctl1 & CTRL1_CHIPSELECT);
 
        /* Set RD or WR bits as appropriate */
        if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
@@ -309,8 +311,16 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
 {
-       //struct cafe_priv *cafe = mtd->priv;
-       //      cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+       struct cafe_priv *cafe = mtd->priv;
+
+       cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+
+       /* Mask the appropriate bit into the stored value of ctl1
+          which will be used by cafe_nand_cmdfunc() */
+       if (chipnr)
+               cafe->ctl1 |= CTRL1_CHIPSELECT;
+       else
+               cafe->ctl1 &= ~CTRL1_CHIPSELECT;
 }
 
 static int cafe_nand_interrupt(int irq, void *id)
@@ -374,28 +384,66 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
        if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
-               unsigned short syn[8];
-               int i;
+               unsigned short syn[8], pat[4];
+               int pos[4];
+               u8 *oob = chip->oob_poi;
+               int i, n;
 
                for (i=0; i<8; i+=2) {
                        uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
-                       syn[i] = tmp & 0xfff;
-                       syn[i+1] = (tmp >> 16) & 0xfff;
+                       syn[i] = cafe->rs->index_of[tmp & 0xfff];
+                       syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff];
+               }
+
+               n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0,
+                               pat);
+
+               for (i = 0; i < n; i++) {
+                       int p = pos[i];
+
+                       /* The 12-bit symbols are mapped to bytes here */
+
+                       if (p > 1374) {
+                               /* out of range */
+                               n = -1374;
+                       } else if (p == 0) {
+                               /* high four bits do not correspond to data */
+                               if (pat[i] > 0xff)
+                                       n = -2048;
+                               else
+                                       buf[0] ^= pat[i];
+                       } else if (p == 1365) {
+                               buf[2047] ^= pat[i] >> 4;
+                               oob[0] ^= pat[i] << 4;
+                       } else if (p > 1365) {
+                               if ((p & 1) == 1) {
+                                       oob[3*p/2 - 2048] ^= pat[i] >> 4;
+                                       oob[3*p/2 - 2047] ^= pat[i] << 4;
+                               } else {
+                                       oob[3*p/2 - 2049] ^= pat[i] >> 8;
+                                       oob[3*p/2 - 2048] ^= pat[i];
+                               }
+                       } else if ((p & 1) == 1) {
+                               buf[3*p/2] ^= pat[i] >> 4;
+                               buf[3*p/2 + 1] ^= pat[i] << 4;
+                       } else {
+                               buf[3*p/2 - 1] ^= pat[i] >> 8;
+                               buf[3*p/2] ^= pat[i];
+                       }
                }
 
-               if ((i = cafe_correct_ecc(buf, syn)) < 0) {
+               if (n < 0) {
                        dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
                                cafe_readl(cafe, NAND_ADDR2) * 2048);
-                       for (i=0; i< 0x5c; i+=4)
+                       for (i = 0; i < 0x5c; i += 4)
                                printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
                        mtd->ecc_stats.failed++;
                } else {
-                       dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
-                       mtd->ecc_stats.corrected += i;
+                       dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
+                       mtd->ecc_stats.corrected += n;
                }
        }
 
-
        return 0;
 }
 
@@ -416,7 +464,7 @@ static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
 
 static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
        .offs = 14,
        .len = 4,
        .veroffs = 18,
@@ -426,7 +474,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
 
 static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
        .offs = 14,
        .len = 4,
        .veroffs = 18,
@@ -442,7 +490,7 @@ static struct nand_ecclayout cafe_oobinfo_512 = {
 
 static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
        .offs = 14,
        .len = 1,
        .veroffs = 15,
@@ -452,7 +500,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
 
 static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
        .offs = 14,
        .len = 1,
        .veroffs = 15,
@@ -525,6 +573,48 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
        return 0;
 }
 
+/* F_2[X]/(X**6+X+1)  */
+static unsigned short __devinit gf64_mul(u8 a, u8 b)
+{
+       u8 c;
+       unsigned int i;
+
+       c = 0;
+       for (i = 0; i < 6; i++) {
+               if (a & 1)
+                       c ^= b;
+               a >>= 1;
+               b <<= 1;
+               if ((b & 0x40) != 0)
+                       b ^= 0x43;
+       }
+
+       return c;
+}
+
+/* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X]  */
+static u16 __devinit gf4096_mul(u16 a, u16 b)
+{
+       u8 ah, al, bh, bl, ch, cl;
+
+       ah = a >> 6;
+       al = a & 0x3f;
+       bh = b >> 6;
+       bl = b & 0x3f;
+
+       ch = gf64_mul(ah ^ al, bh ^ bl) ^ gf64_mul(al, bl);
+       cl = gf64_mul(gf64_mul(ah, bh), 0x21) ^ gf64_mul(al, bl);
+
+       return (ch << 6) ^ cl;
+}
+
+static int __devinit cafe_mul(int x)
+{
+       if (x == 0)
+               return 1;
+       return gf4096_mul(x, 0xe01);
+}
+
 static int __devinit cafe_nand_probe(struct pci_dev *pdev,
                                     const struct pci_device_id *ent)
 {
@@ -564,6 +654,12 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        }
        cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
 
+       cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
+       if (!cafe->rs) {
+               err = -ENOMEM;
+               goto out_ior;
+       }
+
        cafe->nand.cmdfunc = cafe_nand_cmdfunc;
        cafe->nand.dev_ready = cafe_device_ready;
        cafe->nand.read_byte = cafe_read_byte;
@@ -646,7 +742,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
                cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
 
        /* Scan to find existence of the device */
-       if (nand_scan_ident(mtd, 1)) {
+       if (nand_scan_ident(mtd, 2)) {
                err = -ENXIO;
                goto out_irq;
        }
@@ -713,6 +809,7 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
        cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
        free_irq(pdev->irq, mtd);
        nand_release(mtd);
+       free_rs(cafe->rs);
        pci_iounmap(pdev, cafe->mmio);
        dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
        kfree(mtd);
index 04de315e4937c0e650025983b4364ad647c69dac..7e68203fe1ba1c46c779d55a5ae2c9151c5659bf 100644 (file)
@@ -303,28 +303,27 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
        struct nand_chip *chip = mtd->priv;
        u16 bad;
 
+       page = (int)(ofs >> chip->page_shift) & chip->pagemask;
+
        if (getchip) {
-               page = (int)(ofs >> chip->page_shift);
                chipnr = (int)(ofs >> chip->chip_shift);
 
                nand_get_device(chip, mtd, FL_READING);
 
                /* Select the NAND device */
                chip->select_chip(mtd, chipnr);
-       } else
-               page = (int)(ofs >> chip->page_shift);
+       }
 
        if (chip->options & NAND_BUSWIDTH_16) {
                chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
-                             page & chip->pagemask);
+                             page);
                bad = cpu_to_le16(chip->read_word(mtd));
                if (chip->badblockpos & 0x1)
                        bad >>= 8;
                if ((bad & 0xFF) != 0xff)
                        res = 1;
        } else {
-               chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
-                             page & chip->pagemask);
+               chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page);
                if (chip->read_byte(mtd) != 0xff)
                        res = 1;
        }
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
new file mode 100644 (file)
index 0000000..cd725fc
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Generic NAND driver
+ *
+ * Author: Vitaly Wool <vitalywool@gmail.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/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct plat_nand_data {
+       struct nand_chip        chip;
+       struct mtd_info         mtd;
+       void __iomem            *io_base;
+#ifdef CONFIG_MTD_PARTITIONS
+       int                     nr_parts;
+       struct mtd_partition    *parts;
+#endif
+};
+
+/*
+ * Probe for the NAND device.
+ */
+static int __init plat_nand_probe(struct platform_device *pdev)
+{
+       struct platform_nand_data *pdata = pdev->dev.platform_data;
+       struct plat_nand_data *data;
+       int res = 0;
+
+       /* Allocate memory for the device structure (and zero it) */
+       data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+               return -ENOMEM;
+       }
+
+       data->io_base = ioremap(pdev->resource[0].start,
+                               pdev->resource[0].end - pdev->resource[0].start + 1);
+       if (data->io_base == NULL) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               kfree(data);
+               return -EIO;
+       }
+
+       data->chip.priv = &data;
+       data->mtd.priv = &data->chip;
+       data->mtd.owner = THIS_MODULE;
+
+       data->chip.IO_ADDR_R = data->io_base;
+       data->chip.IO_ADDR_W = data->io_base;
+       data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
+       data->chip.dev_ready = pdata->ctrl.dev_ready;
+       data->chip.select_chip = pdata->ctrl.select_chip;
+       data->chip.chip_delay = pdata->chip.chip_delay;
+       data->chip.options |= pdata->chip.options;
+
+       data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
+       data->chip.ecc.layout = pdata->chip.ecclayout;
+       data->chip.ecc.mode = NAND_ECC_SOFT;
+
+       platform_set_drvdata(pdev, data);
+
+       /* Scan to find existance of the device */
+       if (nand_scan(&data->mtd, 1)) {
+               res = -ENXIO;
+               goto out;
+       }
+
+#ifdef CONFIG_MTD_PARTITIONS
+       if (pdata->chip.part_probe_types) {
+               res = parse_mtd_partitions(&data->mtd,
+                                       pdata->chip.part_probe_types,
+                                       &data->parts, 0);
+               if (res > 0) {
+                       add_mtd_partitions(&data->mtd, data->parts, res);
+                       return 0;
+               }
+       }
+       if (pdata->chip.partitions) {
+               data->parts = pdata->chip.partitions;
+               res = add_mtd_partitions(&data->mtd, data->parts,
+                       pdata->chip.nr_partitions);
+       } else
+#endif
+       res = add_mtd_device(&data->mtd);
+
+       if (!res)
+               return res;
+
+       nand_release(&data->mtd);
+out:
+       platform_set_drvdata(pdev, NULL);
+       iounmap(data->io_base);
+       kfree(data);
+       return res;
+}
+
+/*
+ * Remove a NAND device.
+ */
+static int __devexit plat_nand_remove(struct platform_device *pdev)
+{
+       struct plat_nand_data *data = platform_get_drvdata(pdev);
+       struct platform_nand_data *pdata = pdev->dev.platform_data;
+
+       nand_release(&data->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+       if (data->parts && data->parts != pdata->chip.partitions)
+               kfree(data->parts);
+#endif
+       iounmap(data->io_base);
+       kfree(data);
+
+       return 0;
+}
+
+static struct platform_driver plat_nand_driver = {
+       .probe          = plat_nand_probe,
+       .remove         = plat_nand_remove,
+       .driver         = {
+               .name   = "gen_nand",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init plat_nand_init(void)
+{
+       return platform_driver_register(&plat_nand_driver);
+}
+
+static void __exit plat_nand_exit(void)
+{
+       platform_driver_unregister(&plat_nand_driver);
+}
+
+module_init(plat_nand_init);
+module_exit(plat_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vitaly Wool");
+MODULE_DESCRIPTION("Simple generic NAND driver");
index 000794c6caf543682e686d23787f238ddf6d141c..0537fac8de74fd703a6c50d9116213626b010f75 100644 (file)
@@ -2192,7 +2192,7 @@ static int onenand_check_maf(int manuf)
  * @param mtd          MTD device structure
  *
  * OneNAND detection method:
- *   Compare the the values from command with ones from register
+ *   Compare the values from command with ones from register
  */
 static int onenand_probe(struct mtd_info *mtd)
 {
index 9588da3a30e7ccd75b32ff8536d864ee964cb4c7..127f60841b10db37878c081896fcab17a57351cd 100644 (file)
@@ -95,8 +95,7 @@ static int max_interrupt_work = 10;
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
-static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
+static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 
 #if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
 #define EL3_SUSPEND
@@ -360,7 +359,7 @@ static int __init el3_common_init(struct net_device *dev)
        printk(", IRQ %d.\n", dev->irq);
 
        if (el3_debug > 0)
-               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+               printk(KERN_INFO "%s", version);
        return 0;
 
 }
index 80924f76dee8e8673cd11b7ae93628114746f415..f26ca331615e596e01a3e48d1357fa58494dec20 100644 (file)
@@ -103,7 +103,7 @@ static int vortex_debug = 1;
 
 
 static char version[] __devinitdata =
-DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n";
+DRV_NAME ": Donald Becker and others.\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver ");
index 279ec625cec45ac3d5678d9b2b7009d397b4bd4a..b86ccd2ecd5b49f8f304bdec90a875ee192df67b 100644 (file)
@@ -1104,7 +1104,7 @@ config ETH16I
 
 config NE2000
        tristate "NE2000/NE1000 support"
-       depends on NET_ISA || (Q40 && m) || M32R
+       depends on NET_ISA || (Q40 && m) || M32R || TOSHIBA_RBTX4927 || TOSHIBA_RBTX4938
        select CRC32
        ---help---
          If you have a network (Ethernet) card of this type, say Y and read
@@ -2488,6 +2488,7 @@ config NETXEN_NIC
 config PASEMI_MAC
        tristate "PA Semi 1/10Gbit MAC"
        depends on PPC64 && PCI
+       select PHYLIB
        help
          This driver supports the on-chip 1/10Gbit Ethernet controller on
          PA Semi's PWRficient line of chips.
index 152fa7a042b8c16cc736dc4197d028cbc2ff85fa..ef2cc80256a36bc0692ba7fe2857e06fc1045eaf 100644 (file)
@@ -225,6 +225,16 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
                if (!(phy & ((1 << 2) | 1)))
                        goto done;
        }
+       else if (lp->phy_type == MII_T78Q21x3_ID) {                     /* ack interrupt in Teridian PHY */
+               read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
+               if (!(phy & ((1 << 2) | 1)))
+                       goto done;
+       }
+       else if (lp->phy_type == MII_DP83848_ID) {
+               read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy);      /* ack interrupt in DP83848 PHY */
+               if (!(phy & (1 << 7)))
+                       goto done;
+       }
 
        update_linkspeed(dev, 0);
 
@@ -280,6 +290,19 @@ static void enable_phyirq(struct net_device *dev)
                dsintr = (1 << 10) | ( 1 << 8);
                write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
        }
+       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
+               read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+               dsintr = dsintr | 0x500;                /* set bits 8, 10 */
+               write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+       }
+       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
+               read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+               dsintr = dsintr | 0x3c;                 /* set bits 2..5 */
+               write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
+               read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+               dsintr = dsintr | 0x3;                  /* set bits 0,1 */
+               write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
+       }
 
        disable_mdi();
        spin_unlock_irq(&lp->lock);
@@ -323,6 +346,19 @@ static void disable_phyirq(struct net_device *dev)
                dsintr = ~((1 << 10) | (1 << 8));
                write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
        }
+       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
+               read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+               dsintr = dsintr & ~0x500;                       /* clear bits 8, 10 */
+               write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+       }
+       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
+               read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+               dsintr = dsintr & ~0x3;                         /* clear bits 0, 1 */
+               write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
+               read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+               dsintr = dsintr & ~0x3c;                        /* clear bits 2..5 */
+               write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
+       }
 
        disable_mdi();
        spin_unlock_irq(&lp->lock);
@@ -535,8 +571,8 @@ static void at91ether_sethashtable(struct net_device *dev)
                mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
        }
 
-       at91_emac_write(AT91_EMAC_HSH, mc_filter[0]);
-       at91_emac_write(AT91_EMAC_HSL, mc_filter[1]);
+       at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
+       at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
 }
 
 /*
@@ -1062,10 +1098,16 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
                printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
        else if (phy_type == MII_DP83847_ID)
                printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
+       else if (phy_type == MII_DP83848_ID)
+               printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
        else if (phy_type == MII_AC101L_ID)
                printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
        else if (phy_type == MII_KS8721_ID)
                printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
+       else if (phy_type == MII_T78Q21x3_ID)
+               printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
+       else if (phy_type == MII_LAN83C185_ID)
+               printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
 
        return 0;
 }
@@ -1103,8 +1145,11 @@ static int __init at91ether_probe(struct platform_device *pdev)
                        case MII_RTL8201_ID:            /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
                        case MII_BCM5221_ID:            /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
                        case MII_DP83847_ID:            /* National Semiconductor DP83847:  */
+                       case MII_DP83848_ID:            /* National Semiconductor DP83848:  */
                        case MII_AC101L_ID:             /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
                        case MII_KS8721_ID:             /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
+                       case MII_T78Q21x3_ID:           /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
+                       case MII_LAN83C185_ID:          /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
                                detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
                                break;
                }
index b6b665de2ea0c28ac56e4ba30a23044fe0b29b36..a38fd2d053a6171480972ca5f587bc7aa1538b54 100644 (file)
 
 
 /* Davicom 9161 PHY */
-#define MII_DM9161_ID  0x0181b880
-#define MII_DM9161A_ID 0x0181b8a0
-
-/* Davicom specific registers */
-#define MII_DSCR_REG   16
-#define MII_DSCSR_REG  17
-#define MII_DSINTR_REG 21
+#define MII_DM9161_ID          0x0181b880
+#define MII_DM9161A_ID         0x0181b8a0
+#define MII_DSCR_REG           16
+#define MII_DSCSR_REG          17
+#define MII_DSINTR_REG         21
 
 /* Intel LXT971A PHY */
-#define MII_LXT971A_ID 0x001378E0
-
-/* Intel specific registers */
-#define MII_ISINTE_REG 18
-#define MII_ISINTS_REG 19
-#define MII_LEDCTRL_REG        20
+#define MII_LXT971A_ID         0x001378E0
+#define MII_ISINTE_REG         18
+#define MII_ISINTS_REG         19
+#define MII_LEDCTRL_REG                20
 
 /* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID 0x00008200
+#define MII_RTL8201_ID         0x00008200
 
 /* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID 0x004061e0
-
-/* Broadcom specific registers */
-#define MII_BCMINTR_REG        26
+#define MII_BCM5221_ID         0x004061e0
+#define MII_BCMINTR_REG                26
 
 /* National Semiconductor DP83847 */
-#define MII_DP83847_ID 0x20005c30
+#define MII_DP83847_ID         0x20005c30
+
+/* National Semiconductor DP83848 */
+#define MII_DP83848_ID         0x20005c90
+#define MII_DPPHYSTS_REG       16
+#define MII_DPMICR_REG         17
+#define MII_DPMISR_REG         18
 
 /* Altima AC101L PHY */
-#define MII_AC101L_ID  0x00225520
+#define MII_AC101L_ID          0x00225520
 
 /* Micrel KS8721 PHY */
-#define MII_KS8721_ID  0x00221610
+#define MII_KS8721_ID          0x00221610
+
+/* Teridian 78Q2123/78Q2133 */
+#define MII_T78Q21x3_ID                0x000e7230
+#define MII_T78Q21INT_REG      17
+
+/* SMSC LAN83C185 */
+#define MII_LAN83C185_ID       0x0007C0A0
 
 /* ........................................................................ */
 
index c11c27798e5c151b606e1f538548b815d3e01c9d..1f616c5c14739437d0e8efffa856c6df7824825c 100644 (file)
@@ -156,8 +156,7 @@ static int atl1_set_settings(struct net_device *netdev,
        u16 old_media_type = hw->media_type;
 
        if (netif_running(adapter->netdev)) {
-               printk(KERN_DEBUG "%s: ethtool shutting down adapter\n",
-                       atl1_driver_name);
+               dev_dbg(&adapter->pdev->dev, "ethtool shutting down adapter\n");
                atl1_down(adapter);
        }
 
@@ -166,9 +165,8 @@ static int atl1_set_settings(struct net_device *netdev,
        else {
                if (ecmd->speed == SPEED_1000) {
                        if (ecmd->duplex != DUPLEX_FULL) {
-                               printk(KERN_WARNING
-                                      "%s: can't force to 1000M half duplex\n",
-                                       atl1_driver_name);
+                               dev_warn(&adapter->pdev->dev,
+                                       "can't force to 1000M half duplex\n");
                                ret_val = -EINVAL;
                                goto exit_sset;
                        }
@@ -206,9 +204,8 @@ static int atl1_set_settings(struct net_device *netdev,
        }
        if (atl1_phy_setup_autoneg_adv(hw)) {
                ret_val = -EINVAL;
-               printk(KERN_WARNING
-                       "%s: invalid ethtool speed/duplex setting\n",
-                       atl1_driver_name);
+               dev_warn(&adapter->pdev->dev,
+                       "invalid ethtool speed/duplex setting\n");
                goto exit_sset;
        }
        if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
@@ -239,12 +236,10 @@ exit_sset:
                hw->media_type = old_media_type;
 
        if (netif_running(adapter->netdev)) {
-               printk(KERN_DEBUG "%s: ethtool starting adapter\n",
-                       atl1_driver_name);
+               dev_dbg(&adapter->pdev->dev, "ethtool starting adapter\n");
                atl1_up(adapter);
        } else if (!ret_val) {
-               printk(KERN_DEBUG "%s: ethtool resetting adapter\n",
-                       atl1_driver_name);
+               dev_dbg(&adapter->pdev->dev, "ethtool resetting adapter\n");
                atl1_reset(adapter);
        }
        return ret_val;
index 69482e0d849b60673d58d07443708b6a42f4ab79..ef886bdeac13d5ed689c61bc6da41e8209051704 100644 (file)
@@ -2,20 +2,20 @@
  * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
  * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
  * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- * 
+ *
  * Derived from Intel e1000 driver
  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 59
  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 s32 atl1_reset_hw(struct atl1_hw *hw)
 {
+       struct pci_dev *pdev = hw->back->pdev;
        u32 icr;
        int i;
 
-       /* 
+       /*
         * Clear Interrupt mask to stop board from generating
-        * interrupts & Clear any pending interrupt events 
+        * interrupts & Clear any pending interrupt events
         */
        /*
         * iowrite32(0, hw->hw_addr + REG_IMR);
@@ -74,7 +75,7 @@ s32 atl1_reset_hw(struct atl1_hw *hw)
        }
 
        if (icr) {
-               printk (KERN_DEBUG "icr = %x\n", icr); 
+               dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
                return icr;
        }
 
@@ -136,8 +137,8 @@ s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
        int i;
 
        val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-               MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
-               MDIO_CLK_SEL_SHIFT;
+               MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+               MDIO_CLK_SEL_SHIFT;
        iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
        ioread32(hw->hw_addr + REG_MDIO_CTRL);
 
@@ -204,7 +205,7 @@ static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
 
 /*
  * get_permanent_address
- * return 0 if get valid mac address, 
+ * return 0 if get valid mac address,
  */
 static int atl1_get_permanent_address(struct atl1_hw *hw)
 {
@@ -301,7 +302,7 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
 }
 
 /*
- * Reads the adapter's MAC address from the EEPROM 
+ * Reads the adapter's MAC address from the EEPROM
  * hw - Struct containing variables accessed by shared code
  */
 s32 atl1_read_mac_addr(struct atl1_hw *hw)
@@ -437,6 +438,7 @@ s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
  */
 static s32 atl1_phy_reset(struct atl1_hw *hw)
 {
+       struct pci_dev *pdev = hw->back->pdev;
        s32 ret_val;
        u16 phy_data;
 
@@ -468,8 +470,7 @@ static s32 atl1_phy_reset(struct atl1_hw *hw)
                u32 val;
                int i;
                /* pcie serdes link may be down! */
-               printk(KERN_DEBUG "%s: autoneg caused pcie phy link down\n", 
-                       atl1_driver_name);
+               dev_dbg(&pdev->dev, "pcie phy link down\n");
 
                for (i = 0; i < 25; i++) {
                        msleep(1);
@@ -479,9 +480,7 @@ static s32 atl1_phy_reset(struct atl1_hw *hw)
                }
 
                if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
-                       printk(KERN_WARNING 
-                               "%s: pcie link down at least for 25ms\n", 
-                               atl1_driver_name);
+                       dev_warn(&pdev->dev, "pcie link down at least 25ms\n");
                        return ret_val;
                }
        }
@@ -571,6 +570,7 @@ s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
  */
 static s32 atl1_setup_link(struct atl1_hw *hw)
 {
+       struct pci_dev *pdev = hw->back->pdev;
        s32 ret_val;
 
        /*
@@ -581,15 +581,13 @@ static s32 atl1_setup_link(struct atl1_hw *hw)
         */
        ret_val = atl1_phy_setup_autoneg_adv(hw);
        if (ret_val) {
-               printk(KERN_DEBUG "%s: error setting up autonegotiation\n", 
-                       atl1_driver_name);
+               dev_dbg(&pdev->dev, "error setting up autonegotiation\n");
                return ret_val;
        }
        /* SW.Reset , En-Auto-Neg if needed */
        ret_val = atl1_phy_reset(hw);
        if (ret_val) {
-               printk(KERN_DEBUG "%s: error resetting the phy\n", 
-                       atl1_driver_name);
+               dev_dbg(&pdev->dev, "error resetting phy\n");
                return ret_val;
        }
        hw->phy_configured = true;
@@ -631,7 +629,7 @@ static void atl1_init_flash_opcode(struct atl1_hw *hw)
  * Performs basic configuration of the adapter.
  * hw - Struct containing variables accessed by shared code
  * Assumes that the controller has previously been reset and is in a
- * post-reset uninitialized state. Initializes multicast table, 
+ * post-reset uninitialized state. Initializes multicast table,
  * and  Calls routines to setup link
  * Leaves the transmit and receive units disabled and uninitialized.
  */
@@ -669,6 +667,7 @@ s32 atl1_init_hw(struct atl1_hw *hw)
  */
 s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
 {
+       struct pci_dev *pdev = hw->back->pdev;
        s32 ret_val;
        u16 phy_data;
 
@@ -691,8 +690,7 @@ s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
                *speed = SPEED_10;
                break;
        default:
-               printk(KERN_DEBUG "%s: error getting speed\n", 
-                       atl1_driver_name);
+               dev_dbg(&pdev->dev, "error getting speed\n");
                return ATL1_ERR_PHY_SPEED;
                break;
        }
index 4b1d4d153ecfe909e64eca72d90be43d69be0440..d28f88bbdd5fcd43634104f6d228c0ab874ed83e 100644 (file)
@@ -188,8 +188,7 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
        size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
        tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
        if (unlikely(!tpd_ring->buffer_info)) {
-               printk(KERN_WARNING "%s: kzalloc failed , size = D%d\n",
-                       atl1_driver_name, size);
+               dev_err(&pdev->dev, "kzalloc failed , size = D%d\n", size);
                goto err_nomem;
        }
        rfd_ring->buffer_info =
@@ -207,9 +206,7 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
        ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
                                                &ring_header->dma);
        if (unlikely(!ring_header->desc)) {
-               printk(KERN_WARNING
-                       "%s: pci_alloc_consistent failed, size = D%d\n",
-                       atl1_driver_name, size);
+               dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
                goto err_nomem;
        }
 
@@ -373,8 +370,7 @@ static void atl1_rx_checksum(struct atl1_adapter *adapter,
                if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
                                        ERR_FLAG_CODE | ERR_FLAG_OV)) {
                        adapter->hw_csum_err++;
-                       printk(KERN_DEBUG "%s: rx checksum error\n",
-                               atl1_driver_name);
+                       dev_dbg(&adapter->pdev->dev, "rx checksum error\n");
                        return;
                }
        }
@@ -393,8 +389,9 @@ static void atl1_rx_checksum(struct atl1_adapter *adapter,
        }
 
        /* IPv4, but hardware thinks its checksum is wrong */
-       printk(KERN_DEBUG "%s: hw csum wrong pkt_flag:%x, err_flag:%x\n",
-               atl1_driver_name, rrd->pkt_flg, rrd->err_flg);
+       dev_dbg(&adapter->pdev->dev,
+               "hw csum wrong, pkt_flag:%x, err_flag:%x\n",
+               rrd->pkt_flg, rrd->err_flg);
        skb->ip_summed = CHECKSUM_COMPLETE;
        skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
        adapter->hw_csum_err++;
@@ -507,14 +504,13 @@ chk_rrd:
                        /* rrd seems to be bad */
                        if (unlikely(i-- > 0)) {
                                /* rrd may not be DMAed completely */
-                               printk(KERN_DEBUG
-                                       "%s: RRD may not be DMAed completely\n",
-                                       atl1_driver_name);
+                               dev_dbg(&adapter->pdev->dev,
+                                       "incomplete RRD DMA transfer\n");
                                udelay(1);
                                goto chk_rrd;
                        }
                        /* bad rrd */
-                       printk(KERN_DEBUG "%s: bad RRD\n", atl1_driver_name);
+                       dev_dbg(&adapter->pdev->dev, "bad RRD\n");
                        /* see if update RFD index */
                        if (rrd->num_buf > 1) {
                                u16 num_buf;
@@ -685,8 +681,8 @@ static void atl1_check_for_link(struct atl1_adapter *adapter)
        /* notify upper layer link down ASAP */
        if (!(phy_data & BMSR_LSTATUS)) {       /* Link Down */
                if (netif_carrier_ok(netdev)) { /* old link state: Up */
-                       printk(KERN_INFO "%s: %s link is down\n",
-                              atl1_driver_name, netdev->name);
+                       dev_info(&adapter->pdev->dev, "%s link is down\n",
+                               netdev->name);
                        adapter->link_speed = SPEED_0;
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
@@ -731,8 +727,8 @@ static irqreturn_t atl1_intr(int irq, void *data)
 
                /* check if PCIE PHY Link down */
                if (status & ISR_PHY_LINKDOWN) {
-                       printk(KERN_DEBUG "%s: pcie phy link down %x\n",
-                               atl1_driver_name, status);
+                       dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n",
+                               status);
                        if (netif_running(adapter->netdev)) {   /* reset MAC */
                                iowrite32(0, adapter->hw.hw_addr + REG_IMR);
                                schedule_work(&adapter->pcie_dma_to_rst_task);
@@ -742,9 +738,9 @@ static irqreturn_t atl1_intr(int irq, void *data)
 
                /* check if DMA read/write error ? */
                if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-                       printk(KERN_DEBUG
-                               "%s: pcie DMA r/w error (status = 0x%x)\n",
-                               atl1_driver_name, status);
+                       dev_dbg(&adapter->pdev->dev,
+                               "pcie DMA r/w error (status = 0x%x)\n",
+                               status);
                        iowrite32(0, adapter->hw.hw_addr + REG_IMR);
                        schedule_work(&adapter->pcie_dma_to_rst_task);
                        return IRQ_HANDLED;
@@ -762,14 +758,13 @@ static irqreturn_t atl1_intr(int irq, void *data)
 
                /* rx exception */
                if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+                       ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+                       ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+                       if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
                                ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-                               ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-                       if (status &
-                           (ISR_RXF_OV | ISR_RFD_UNRUN | ISR_RRD_OV |
-                            ISR_HOST_RFD_UNRUN | ISR_HOST_RRD_OV))
-                               printk(KERN_INFO
-                                       "%s: rx exception: status = 0x%x\n",
-                                       atl1_driver_name, status);
+                               ISR_HOST_RRD_OV))
+                               dev_dbg(&adapter->pdev->dev,
+                                       "rx exception, ISR = 0x%x\n", status);
                        atl1_intr_rx(adapter);
                }
 
@@ -874,8 +869,7 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
        atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
        if (!(phy_data & BMSR_LSTATUS)) {       /* link down */
                if (netif_carrier_ok(netdev)) { /* old link state: Up */
-                       printk(KERN_INFO "%s: link is down\n",
-                               atl1_driver_name);
+                       dev_info(&adapter->pdev->dev, "link is down\n");
                        adapter->link_speed = SPEED_0;
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
@@ -918,11 +912,11 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
                        adapter->link_speed = speed;
                        adapter->link_duplex = duplex;
                        atl1_setup_mac_ctrl(adapter);
-                       printk(KERN_INFO "%s: %s link is up %d Mbps %s\n",
-                              atl1_driver_name, netdev->name,
-                              adapter->link_speed,
-                              adapter->link_duplex ==
-                              FULL_DUPLEX ? "full duplex" : "half duplex");
+                       dev_info(&adapter->pdev->dev,
+                               "%s link is up %d Mbps %s\n",
+                               netdev->name, adapter->link_speed,
+                               adapter->link_duplex == FULL_DUPLEX ?
+                               "full duplex" : "half duplex");
                }
                if (!netif_carrier_ok(netdev)) {        /* Link down -> Up */
                        netif_carrier_on(netdev);
@@ -1330,8 +1324,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
                cso = skb_transport_offset(skb);
                css = cso + skb->csum_offset;
                if (unlikely(cso & 0x1)) {
-                       printk(KERN_DEBUG "%s: payload offset != even number\n",
-                               atl1_driver_name);
+                       dev_dbg(&adapter->pdev->dev,
+                               "payload offset not an even number\n");
                        return -1;
                }
                csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
@@ -1579,7 +1573,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if (!spin_trylock(&adapter->lock)) {
                /* Can't get lock - tell upper layer to requeue */
                local_irq_restore(flags);
-               printk(KERN_DEBUG "%s: TX locked\n", atl1_driver_name);
+               dev_dbg(&adapter->pdev->dev, "tx locked\n");
                return NETDEV_TX_LOCKED;
        }
 
@@ -1587,7 +1581,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                /* not enough descriptors */
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&adapter->lock, flags);
-               printk(KERN_DEBUG "%s: TX busy\n", atl1_driver_name);
+               dev_dbg(&adapter->pdev->dev, "tx busy\n");
                return NETDEV_TX_BUSY;
        }
 
@@ -1841,8 +1835,7 @@ static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
 
        if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
            (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-               printk(KERN_WARNING "%s: invalid MTU setting\n",
-                       atl1_driver_name);
+               dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
                return -EINVAL;
        }
 
@@ -2136,9 +2129,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
        if (err) {
                err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
                if (err) {
-                       printk(KERN_DEBUG
-                               "%s: no usable DMA configuration, aborting\n",
-                               atl1_driver_name);
+                       dev_err(&pdev->dev, "no usable DMA configuration\n");
                        goto err_dma;
                }
                pci_using_64 = false;
@@ -2175,7 +2166,9 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
                goto err_pci_iomap;
        }
        /* get device revision number */
-       adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + (REG_MASTER_CTRL + 2));
+       adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
+                                       (REG_MASTER_CTRL + 2));
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
        /* set default ring resource counts */
        adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
@@ -2466,8 +2459,6 @@ static void __exit atl1_exit_module(void)
  */
 static int __init atl1_init_module(void)
 {
-       printk(KERN_INFO "%s - version %s\n", atl1_driver_string, DRIVER_VERSION);
-       printk(KERN_INFO "%s\n", atl1_copyright);
        return pci_register_driver(&atl1_driver);
 }
 
index bcd0bd8917226a3e5f13f9735b81cc41954e58ea..4246bb9bd50eb9cad5ab4419f08da20d065defac 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/types.h>
 #include <linux/moduleparam.h>
+#include <linux/pci.h>
 #include "atl1.h"
 
 /*
@@ -93,7 +94,7 @@ struct atl1_option {
        } arg;
 };
 
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, struct pci_dev *pdev)
 {
        if (*value == OPTION_UNSET) {
                *value = opt->def;
@@ -104,19 +105,17 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
        case enable_option:
                switch (*value) {
                case OPTION_ENABLED:
-                       printk(KERN_INFO "%s: %s Enabled\n", atl1_driver_name,
-                               opt->name);
+                       dev_info(&pdev->dev, "%s enabled\n", opt->name);
                        return 0;
                case OPTION_DISABLED:
-                       printk(KERN_INFO "%s: %s Disabled\n", atl1_driver_name,
-                               opt->name);
+                       dev_info(&pdev->dev, "%s disabled\n", opt->name);
                        return 0;
                }
                break;
        case range_option:
                if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-                       printk(KERN_INFO "%s: %s set to %i\n",
-                               atl1_driver_name, opt->name, *value);
+                       dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+                               *value);
                        return 0;
                }
                break;
@@ -128,8 +127,8 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
                                ent = &opt->arg.l.p[i];
                                if (*value == ent->i) {
                                        if (ent->str[0] != '\0')
-                                               printk(KERN_INFO "%s: %s\n",
-                                                      atl1_driver_name, ent->str);
+                                               dev_info(&pdev->dev, "%s\n",
+                                                       ent->str);
                                        return 0;
                                }
                        }
@@ -140,8 +139,8 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
                break;
        }
 
-       printk(KERN_INFO "%s: invalid %s specified (%i) %s\n",
-              atl1_driver_name, opt->name, *value, opt->err);
+       dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+               opt->name, *value, opt->err);
        *value = opt->def;
        return -1;
 }
@@ -157,12 +156,11 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
  */
 void __devinit atl1_check_options(struct atl1_adapter *adapter)
 {
+       struct pci_dev *pdev = adapter->pdev;
        int bd = adapter->bd_number;
        if (bd >= ATL1_MAX_NIC) {
-               printk(KERN_NOTICE "%s: warning: no configuration for board #%i\n",
-                       atl1_driver_name, bd);
-               printk(KERN_NOTICE "%s: using defaults for all values\n",
-                       atl1_driver_name);
+               dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+               dev_notice(&pdev->dev, "using defaults for all values\n");
        }
        {                       /* Interrupt Moderate Timer */
                struct atl1_option opt = {
@@ -177,7 +175,7 @@ void __devinit atl1_check_options(struct atl1_adapter *adapter)
                int val;
                if (num_int_mod_timer > bd) {
                        val = int_mod_timer[bd];
-                       atl1_validate_option(&val, &opt);
+                       atl1_validate_option(&val, &opt, pdev);
                        adapter->imt = (u16) val;
                } else
                        adapter->imt = (u16) (opt.def);
@@ -197,7 +195,7 @@ void __devinit atl1_check_options(struct atl1_adapter *adapter)
                int val;
                if (num_flash_vendor > bd) {
                        val = flash_vendor[bd];
-                       atl1_validate_option(&val, &opt);
+                       atl1_validate_option(&val, &opt, pdev);
                        adapter->hw.flash_vendor = (u8) val;
                } else
                        adapter->hw.flash_vendor = (u8) (opt.def);
index 18aba838c1ff231dc44c27d80e41647f32d9e86a..82d78ff8399bbeea1046b1efa241e3bf2fd181bd 100644 (file)
 
 */
 
-static const char versionA[] =
+static const char version[] =
 "atp.c:v1.09=ac 2002/10/01 Donald Becker <becker@scyld.com>\n";
-static const char versionB[] =
-"  http://www.scyld.com/network/atp.html\n";
 
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
@@ -324,7 +322,7 @@ static int __init atp_probe1(long ioaddr)
 
 #ifndef MODULE
        if (net_debug)
-               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+               printk(KERN_INFO "%s", version);
 #endif
 
        printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, SAPROM "
@@ -926,7 +924,7 @@ static void set_rx_mode_8012(struct net_device *dev)
 
 static int __init atp_init_module(void) {
        if (debug)                                      /* Emit version even if no cards detected. */
-               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+               printk(KERN_INFO "%s", version);
        return atp_init();
 }
 
index 4612725965df3164f9fd1aaacd15c4eb3b54ff23..9b8d7d9dbe86cc99908842d54beb3930dad5f748 100644 (file)
@@ -1260,9 +1260,10 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i
                printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
                return -ENODEV;
        }
-       prop_addr = get_property(macio_get_of_node(mdev), "mac-address", NULL);
+       prop_addr = of_get_property(macio_get_of_node(mdev),
+                       "mac-address", NULL);
        if (prop_addr == NULL) {
-               prop_addr = get_property(macio_get_of_node(mdev),
+               prop_addr = of_get_property(macio_get_of_node(mdev),
                                "local-mac-address", NULL);
                if (prop_addr == NULL) {
                        printk(KERN_ERR "BMAC: Can't get mac-address\n");
index 724bce51f936b52450764463b7faf1b707487483..223517dcbcfd48ba48c75710d99b3eeb22ceaa46 100644 (file)
@@ -3461,7 +3461,7 @@ void bond_unregister_arp(struct bonding *bond)
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
- * Hash for the the output device based upon layer 3 and layer 4 data. If
+ * Hash for the output device based upon layer 3 and layer 4 data. If
  * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
  * altogether not IP, mimic bond_xmit_hash_policy_l2()
  */
index 8cc1174e7f64361847def8e89132ee0ade90f863..264fa0e2e0750401ff200a063f46e68a2f45378c 100644 (file)
@@ -77,9 +77,6 @@
 
 #define DM9000_PHY             0x40    /* PHY address 0x01 */
 
-#define TRUE                   1
-#define FALSE                  0
-
 #define CARDNAME "dm9000"
 #define PFX CARDNAME ": "
 
@@ -601,7 +598,7 @@ dm9000_probe(struct platform_device *pdev)
        printk("%s: not found (%d).\n", CARDNAME, ret);
 
        dm9000_release_board(pdev, db);
-       kfree(ndev);
+       free_netdev(ndev);
 
        return ret;
 }
@@ -896,7 +893,7 @@ dm9000_rx(struct net_device *dev)
        struct dm9000_rxhdr rxhdr;
        struct sk_buff *skb;
        u8 rxbyte, *rdptr;
-       int GoodPacket;
+       bool GoodPacket;
        int RxLen;
 
        /* Check packet ready or not */
@@ -918,7 +915,7 @@ dm9000_rx(struct net_device *dev)
                        return;
 
                /* A packet ready now  & Get status/length */
-               GoodPacket = TRUE;
+               GoodPacket = true;
                writeb(DM9000_MRCMD, db->io_addr);
 
                (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
@@ -927,7 +924,7 @@ dm9000_rx(struct net_device *dev)
 
                /* Packet Status check */
                if (RxLen < 0x40) {
-                       GoodPacket = FALSE;
+                       GoodPacket = false;
                        PRINTK1("Bad Packet received (runt)\n");
                }
 
@@ -936,7 +933,7 @@ dm9000_rx(struct net_device *dev)
                }
 
                if (rxhdr.RxStatus & 0xbf00) {
-                       GoodPacket = FALSE;
+                       GoodPacket = false;
                        if (rxhdr.RxStatus & 0x100) {
                                PRINTK1("fifo error\n");
                                db->stats.rx_fifo_errors++;
@@ -1193,7 +1190,7 @@ dm9000_drv_remove(struct platform_device *pdev)
 
        unregister_netdev(ndev);
        dm9000_release_board(pdev, (board_info_t *) ndev->priv);
-       kfree(ndev);            /* free device structure */
+       free_netdev(ndev);              /* free device structure */
 
        PRINTK1("clean_module() exit\n");
 
index 3a03a74c0609b89172941ccb9e6a9586005bbf31..637ae8f6879199444716e0c8025ec56a3eaacdc0 100644 (file)
@@ -1214,7 +1214,7 @@ e1000_remove(struct pci_dev *pdev)
        int i;
 #endif
 
-       flush_scheduled_work();
+       cancel_work_sync(&adapter->reset_task);
 
        e1000_release_manageability(adapter);
 
index 39654e1e2bed09450bb67206729c17761d5b8798..47680237f783f04b05a5c233012b6c48d4d0d491 100644 (file)
@@ -1126,7 +1126,7 @@ static void eepro_tx_timeout (struct net_device *dev)
        printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
                "network cable problem");
        /* This is not a duplicate. One message for the console,
-          one for the the log file  */
+          one for the log file  */
        printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
                "network cable problem");
        eepro_complete_selreset(ioaddr);
index 6c267c38df97a7080b2094ce08b31da4cdaaadc4..9800341956a2e36a1277e9f9830547abdbc737ba 100644 (file)
@@ -28,7 +28,7 @@
 */
 
 static const char * const version =
-"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n"
+"eepro100.c:v1.09j-t 9/29/99 Donald Becker\n"
 "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
 
 /* A few user-configurable values that apply to all boards.
index c7a5614e66c01b6d928521cb609296d97c923662..f6e0cb1ada1ff6a0b14fa07b0e574f18316bf0dc 100644 (file)
@@ -1803,10 +1803,10 @@ static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
        u32 tmp;
 
        if ((skb->protocol == htons(ETH_P_IP)) &&
-           (skb->nh.iph->protocol == IPPROTO_TCP)) {
-               tcp = (struct tcphdr*)(skb->nh.raw + (skb->nh.iph->ihl * 4));
+           (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
+               tcp = (struct tcphdr*)(skb_network_header(skb) + (ip_hdr(skb)->ihl * 4));
                tmp = (tcp->source + (tcp->dest << 16)) % 31;
-               tmp += skb->nh.iph->daddr % 31;
+               tmp += ip_hdr(skb)->daddr % 31;
                return tmp % num_qps;
        }
        else
@@ -2603,14 +2603,13 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
 {
        struct device_node *lhea_dn;
        struct device_node *eth_dn = NULL;
-
-       u32 *dn_log_port_id;
+       const u32 *dn_log_port_id;
        int i = 0;
 
        lhea_dn = adapter->ebus_dev->ofdev.node;
        while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
-               dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no",
+               dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
                                                    NULL);
                if (!dn_log_port_id) {
                        ehea_error("bad device node: eth_dn name=%s",
@@ -2645,12 +2644,12 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
 {
        struct device_node *lhea_dn;
        struct device_node *eth_dn = NULL;
-       u32 *dn_log_port_id;
+       const u32 *dn_log_port_id;
 
        lhea_dn = adapter->ebus_dev->ofdev.node;
        while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
-               dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no",
+               dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
                                                    NULL);
                if (dn_log_port_id)
                        if (*dn_log_port_id == logical_port_id)
@@ -2774,7 +2773,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
                                        const struct of_device_id *id)
 {
        struct ehea_adapter *adapter;
-       u64 *adapter_handle;
+       const u64 *adapter_handle;
        int ret;
 
        if (!dev || !dev->ofdev.node) {
@@ -2791,7 +2790,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
 
        adapter->ebus_dev = dev;
 
-       adapter_handle = (u64*)get_property(dev->ofdev.node, "ibm,hea-handle",
+       adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
                                            NULL);
        if (adapter_handle)
                adapter->handle = *adapter_handle;
index 4e3f14c9c7174d1667bed0393e6289974f9af3b1..5e517946f46a6c1deaee52eb25664467cd233528 100644 (file)
@@ -93,8 +93,6 @@ static int rx_copybreak;
 static char version[] __devinitdata =
 DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
 static char version2[] __devinitdata =
-"  http://www.scyld.com/network/epic100.html\n";
-static char version3[] __devinitdata =
 "  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -323,8 +321,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 #ifndef MODULE
        static int printed_version;
        if (!printed_version++)
-               printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
-                       version, version2, version3);
+               printk (KERN_INFO "%s" KERN_INFO "%s",
+                       version, version2);
 #endif
 
        card_idx++;
@@ -1596,8 +1594,8 @@ static int __init epic_init (void)
 {
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
-       printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
-               version, version2, version3);
+       printk (KERN_INFO "%s" KERN_INFO "%s",
+               version, version2);
 #endif
 
        return pci_register_driver(&epic_driver);
index 6e90619b3b41d483cef4e12a51c9e1188cf29395..36d2c7d4f4d089ab3e22ab559ef5a00a336a2e16 100644 (file)
@@ -140,7 +140,7 @@ config BAYCOM_SER_HDX
          modems that connect to a serial interface. The driver supports the
          ser12 design in half-duplex mode. This is the old driver.  It is
          still provided in case your serial interface chip does not work with
-         the full-duplex driver. This driver is depreciated.  To configure
+         the full-duplex driver. This driver is deprecated.  To configure
          the driver, use the sethdlc utility available in the standard ax25
          utilities package. For information on the modems, see
          <http://www.baycom.de/> and
index 2ab173d9a0e424001efcd5a0f77640381fde02ef..1e67720f1066f5952bd67225aaa2269c96ca23c0 100644 (file)
 /* RxOver  overflow in Recv FIFO                                */
 /* SipRcv  received serial gap  (or other condition you set)    */
 /* Interrupts are enabled by writing a one to the IER register  */
-/* Interrupts are cleared by writting a one to the ISR register */
+/* Interrupts are cleared by writing a one to the ISR register */
 /*                                                              */
 /* 6. The remaining registers: 0x6 and 0x3 appear to be         */
 /*    reserved parts of 16 or 32 bit registersthe remainder     */
index 17b0c3ab6201a27d10af5da3254c876af52025ee..9d6c8f391b2d594338bf457f3119363160d7cf07 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 
 #include <net/irda/irda.h>
index d7e32d9554fc555bb01ca8ae58921a4290e7fd3a..25d5b8a96bdcbdbd54c2afc0694d51c4fc52280a 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/kmod.h>
 #include <linux/mutex.h>
 
index 198bf3bfa70fc234b3ba4b4d0f182dac0280572c..9043bf4aa49ec9e5a477eff5347b49790f2160fa 100644 (file)
@@ -79,11 +79,17 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
 MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
 MODULE_LICENSE("GPL");
 
-static int ircc_dma = 255;
+static int smsc_nopnp;
+module_param_named(nopnp, smsc_nopnp, bool, 0);
+MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
+
+#define DMA_INVAL 255
+static int ircc_dma = DMA_INVAL;
 module_param(ircc_dma, int, 0);
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 
-static int ircc_irq = 255;
+#define IRQ_INVAL 255
+static int ircc_irq = IRQ_INVAL;
 module_param(ircc_irq, int, 0);
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
 
@@ -360,7 +366,6 @@ static inline void register_bank(int iobase, int bank)
                iobase + IRCC_MASTER);
 }
 
-#ifdef CONFIG_PNP
 /* PNP hotplug support */
 static const struct pnp_device_id smsc_ircc_pnp_table[] = {
        { .id = "SMCf010", .driver_data = 0 },
@@ -368,7 +373,35 @@ static const struct pnp_device_id smsc_ircc_pnp_table[] = {
        { }
 };
 MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
-#endif
+
+static int pnp_driver_registered;
+
+static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
+                                     const struct pnp_device_id *dev_id)
+{
+       unsigned int firbase, sirbase;
+       u8 dma, irq;
+
+       if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+             pnp_dma_valid(dev, 0) && pnp_irq_valid(dev, 0)))
+               return -EINVAL;
+
+       sirbase = pnp_port_start(dev, 0);
+       firbase = pnp_port_start(dev, 1);
+       dma = pnp_dma(dev, 0);
+       irq = pnp_irq(dev, 0);
+
+       if (smsc_ircc_open(firbase, sirbase, dma, irq))
+               return -ENODEV;
+
+       return 0;
+}
+
+static struct pnp_driver smsc_ircc_pnp_driver = {
+       .name           = "smsc-ircc2",
+       .id_table       = smsc_ircc_pnp_table,
+       .probe          = smsc_ircc_pnp_probe,
+};
 
 
 /*******************************************************************************
@@ -379,6 +412,35 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
  *
  *******************************************************************************/
 
+static int __init smsc_ircc_legacy_probe(void)
+{
+       int ret = 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))
+                       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;
+               }
+
+               if (smsc_ircc_look_for_chips() > 0)
+                       ret = 0;
+       }
+       return ret;
+}
+
 /*
  * Function smsc_ircc_init ()
  *
@@ -406,31 +468,20 @@ static int __init smsc_ircc_init(void)
 
        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))
-                       ret = -ENODEV;
+       if (smsc_nopnp || !pnp_platform_devices ||
+           ircc_cfg || ircc_fir || ircc_sir ||
+           ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) {
+               ret = smsc_ircc_legacy_probe();
        } 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;
-               }
-
-               if (smsc_ircc_look_for_chips() > 0)
-                       ret = 0;
+               if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0)
+                       pnp_driver_registered = 1;
        }
 
-       if (ret)
+       if (ret) {
+               if (pnp_driver_registered)
+                       pnp_unregister_driver(&smsc_ircc_pnp_driver);
                platform_driver_unregister(&smsc_ircc_driver);
+       }
 
        return ret;
 }
@@ -646,7 +697,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
        self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE;
        self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED;
 
-       if (irq < 255) {
+       if (irq != IRQ_INVAL) {
                if (irq != chip_irq)
                        IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
                                     driver_name, chip_irq, irq);
@@ -654,7 +705,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
        } else
                self->io.irq = chip_irq;
 
-       if (dma < 255) {
+       if (dma != DMA_INVAL) {
                if (dma != chip_dma)
                        IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
                                     driver_name, chip_dma, dma);
@@ -1840,6 +1891,9 @@ static void __exit smsc_ircc_cleanup(void)
                        smsc_ircc_close(dev_self[i]);
        }
 
+       if (pnp_driver_registered)
+               pnp_unregister_driver(&smsc_ircc_pnp_driver);
+
        platform_driver_unregister(&smsc_ircc_driver);
 }
 
@@ -2836,9 +2890,9 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
                                        tmpconf.fir_io = ircc_fir;
                                if (ircc_sir != 0)
                                        tmpconf.sir_io = ircc_sir;
-                               if (ircc_dma != 0xff)
+                               if (ircc_dma != DMA_INVAL)
                                        tmpconf.fir_dma = ircc_dma;
-                               if (ircc_irq != 0xff)
+                               if (ircc_irq != IRQ_INVAL)
                                        tmpconf.fir_irq = ircc_irq;
 
                                IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
index c4be973867a6904713ce108baee9516580551acd..bf78ef1120adf2f9696b29f38450d77832778fde 100644 (file)
@@ -44,7 +44,6 @@ MODULE_LICENSE("GPL");
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
index f15aebde7b9026bea724f90785e08847889c84f0..52c99d01d5681f33c9c51242e887c52240debe5b 100644 (file)
@@ -315,7 +315,7 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
  * hw - Struct containing variables accessed by shared code
  *
  * Reads the first 64 16 bit words of the EEPROM and sums the values read.
- * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
  * valid.
  *
  * Returns:
index b3bd62394958da1c727207a48e2380a2b0642912..52b9332810c52eb7465fdb30de5450758f10fd36 100644 (file)
@@ -110,9 +110,9 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
                return -ENODEV;
        }
 
-       addr = get_property(mace, "mac-address", NULL);
+       addr = of_get_property(mace, "mac-address", NULL);
        if (addr == NULL) {
-               addr = get_property(mace, "local-mac-address", NULL);
+               addr = of_get_property(mace, "local-mac-address", NULL);
                if (addr == NULL) {
                        printk(KERN_ERR "Can't get mac-address for MACE %s\n",
                               mace->full_name);
index 84960dae2a2235a07ad82dec7fb534f62377b385..ea3b8fc86d1ef239cef9b6557f1468ad0cdf4a95 100644 (file)
@@ -126,7 +126,7 @@ typedef struct rx_packet {
                                       /*   Note: when loopback is set this bit becomes collision control.  Setting this bit will */
                                       /*         cause a collision to be reported. */
 
-                                      /* Bits 5 and 6 are used to determine the the Destination address filter mode */
+                                      /* Bits 5 and 6 are used to determine the Destination address filter mode */
 #define METH_ACCEPT_MY 0                       /* 00: Accept PHY address only */
 #define METH_ACCEPT_MCAST 0x20 /* 01: Accept physical, broadcast, and multicast filter matches only */
 #define METH_ACCEPT_AMCAST 0x40        /* 10: Accept physical, broadcast, and all multicast packets */
index 16e3c4315e8228496ed62fa2bfca3728635bc215..5d14be7405a37e29c6a75ee73d9409f25f0d9aa3 100644 (file)
@@ -290,6 +290,8 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
 
 #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
 
+static void myri10ge_set_multicast_list(struct net_device *dev);
+
 static inline void put_be32(__be32 val, __be32 __iomem * p)
 {
        __raw_writel((__force __u32) val, (__force void __iomem *)p);
@@ -353,6 +355,8 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                        return 0;
                } else if (result == MXGEFW_CMD_UNKNOWN) {
                        return -ENOSYS;
+               } else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {
+                       return -E2BIG;
                } else {
                        dev_err(&mgp->pdev->dev,
                                "command %d failed, result = %d\n",
@@ -712,14 +716,78 @@ myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic)
                       mgp->dev->name);
 }
 
-static int myri10ge_reset(struct myri10ge_priv *mgp)
+static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type)
 {
        struct myri10ge_cmd cmd;
        int status;
-       size_t bytes;
        u32 len;
        struct page *dmatest_page;
        dma_addr_t dmatest_bus;
+       char *test = " ";
+
+       dmatest_page = alloc_page(GFP_KERNEL);
+       if (!dmatest_page)
+               return -ENOMEM;
+       dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
+                                  DMA_BIDIRECTIONAL);
+
+       /* Run a small DMA test.
+        * The magic multipliers to the length tell the firmware
+        * to do DMA read, write, or read+write tests.  The
+        * results are returned in cmd.data0.  The upper 16
+        * bits or the return is the number of transfers completed.
+        * The lower 16 bits is the time in 0.5us ticks that the
+        * transfers took to complete.
+        */
+
+       len = mgp->tx.boundary;
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
+       cmd.data2 = len * 0x10000;
+       status = myri10ge_send_cmd(mgp, test_type, &cmd, 0);
+       if (status != 0) {
+               test = "read";
+               goto abort;
+       }
+       mgp->read_dma = ((cmd.data0 >> 16) * len * 2) / (cmd.data0 & 0xffff);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
+       cmd.data2 = len * 0x1;
+       status = myri10ge_send_cmd(mgp, test_type, &cmd, 0);
+       if (status != 0) {
+               test = "write";
+               goto abort;
+       }
+       mgp->write_dma = ((cmd.data0 >> 16) * len * 2) / (cmd.data0 & 0xffff);
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
+       cmd.data2 = len * 0x10001;
+       status = myri10ge_send_cmd(mgp, test_type, &cmd, 0);
+       if (status != 0) {
+               test = "read/write";
+               goto abort;
+       }
+       mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
+           (cmd.data0 & 0xffff);
+
+abort:
+       pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
+       put_page(dmatest_page);
+
+       if (status != 0 && test_type != MXGEFW_CMD_UNALIGNED_TEST)
+               dev_warn(&mgp->pdev->dev, "DMA %s benchmark failed: %d\n",
+                        test, status);
+
+       return status;
+}
+
+static int myri10ge_reset(struct myri10ge_priv *mgp)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+       size_t bytes;
 
        /* try to send a reset command to the card to see if it
         * is alive */
@@ -729,11 +797,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
                dev_err(&mgp->pdev->dev, "failed reset\n");
                return -ENXIO;
        }
-       dmatest_page = alloc_page(GFP_KERNEL);
-       if (!dmatest_page)
-               return -ENOMEM;
-       dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
-                                  DMA_BIDIRECTIONAL);
+
+       (void)myri10ge_dma_test(mgp, MXGEFW_DMA_TEST);
 
        /* Now exchange information about interrupts  */
 
@@ -761,52 +826,6 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        }
        put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
 
-       /* Run a small DMA test.
-        * The magic multipliers to the length tell the firmware
-        * to do DMA read, write, or read+write tests.  The
-        * results are returned in cmd.data0.  The upper 16
-        * bits or the return is the number of transfers completed.
-        * The lower 16 bits is the time in 0.5us ticks that the
-        * transfers took to complete.
-        */
-
-       len = mgp->tx.boundary;
-
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
-       cmd.data2 = len * 0x10000;
-       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
-       if (status == 0)
-               mgp->read_dma = ((cmd.data0 >> 16) * len * 2) /
-                   (cmd.data0 & 0xffff);
-       else
-               dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
-                        status);
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
-       cmd.data2 = len * 0x1;
-       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
-       if (status == 0)
-               mgp->write_dma = ((cmd.data0 >> 16) * len * 2) /
-                   (cmd.data0 & 0xffff);
-       else
-               dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
-                        status);
-
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
-       cmd.data2 = len * 0x10001;
-       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
-       if (status == 0)
-               mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
-                   (cmd.data0 & 0xffff);
-       else
-               dev_warn(&mgp->pdev->dev,
-                        "DMA read/write benchmark failed: %d\n", status);
-
-       pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
-       put_page(dmatest_page);
-
        memset(mgp->rx_done.entry, 0, bytes);
 
        /* reset mcp/driver shared state back to 0 */
@@ -820,10 +839,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        mgp->rx_done.cnt = 0;
        mgp->link_changes = 0;
        status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
-       myri10ge_change_promisc(mgp, 0, 0);
        myri10ge_change_pause(mgp, mgp->pause);
-       if (mgp->adopted_rx_filter_bug)
-               (void)myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1);
+       myri10ge_set_multicast_list(mgp->dev);
        return status;
 }
 
@@ -1355,7 +1372,9 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
        "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
        "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
        "link_changes", "link_up", "dropped_link_overflow",
-       "dropped_link_error_or_filtered", "dropped_multicast_filtered",
+       "dropped_link_error_or_filtered",
+       "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32",
+       "dropped_unicast_filtered", "dropped_multicast_filtered",
        "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
        "dropped_no_big_buffer"
 };
@@ -1412,6 +1431,11 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
        data[i++] =
            (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_pause);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_bad_phy);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_bad_crc32);
+       data[i++] =
+           (unsigned int)ntohl(mgp->fw_stats->dropped_unicast_filtered);
        data[i++] =
            (unsigned int)ntohl(mgp->fw_stats->dropped_multicast_filtered);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
@@ -2276,7 +2300,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
        myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1);
 
        /* This firmware is known to not support multicast */
-       if (!mgp->fw_multicast_support || mgp->adopted_rx_filter_bug)
+       if (!mgp->fw_multicast_support)
                return;
 
        /* Disable multicast filtering */
@@ -2288,7 +2312,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
                goto abort;
        }
 
-       if (dev->flags & IFF_ALLMULTI) {
+       if ((dev->flags & IFF_ALLMULTI) || mgp->adopted_rx_filter_bug) {
                /* request to disable multicast filtering, so quit here */
                return;
        }
@@ -2461,8 +2485,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
        err_cap |= PCI_ERR_CAP_ECRC_GENE;
        pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap);
        dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge));
-       mgp->tx.boundary = 4096;
-       mgp->fw_name = myri10ge_fw_aligned;
 }
 
 /*
@@ -2484,22 +2506,70 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
  * firmware image, and set tx.boundary to 4KB.
  */
 
-#define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7
-#define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa
-#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510
-#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b
-#define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779
-#define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a
-#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140
-#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142
-
-static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
+static void myri10ge_firmware_probe(struct myri10ge_priv *mgp)
 {
-       struct pci_dev *bridge = mgp->pdev->bus->self;
+       struct pci_dev *pdev = mgp->pdev;
+       struct device *dev = &pdev->dev;
+       int cap, status;
+       u16 val;
+
+       mgp->tx.boundary = 4096;
+       /*
+        * Verify the max read request size was set to 4KB
+        * before trying the test with 4KB.
+        */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (cap < 64) {
+               dev_err(dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
+               goto abort;
+       }
+       status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
+       if (status != 0) {
+               dev_err(dev, "Couldn't read max read req size: %d\n", status);
+               goto abort;
+       }
+       if ((val & (5 << 12)) != (5 << 12)) {
+               dev_warn(dev, "Max Read Request size != 4096 (0x%x)\n", val);
+               mgp->tx.boundary = 2048;
+       }
+       /*
+        * load the optimized firmware (which assumes aligned PCIe
+        * completions) in order to see if it works on this host.
+        */
+       mgp->fw_name = myri10ge_fw_aligned;
+       status = myri10ge_load_firmware(mgp);
+       if (status != 0) {
+               goto abort;
+       }
+
+       /*
+        * Enable ECRC if possible
+        */
+       myri10ge_enable_ecrc(mgp);
+
+       /*
+        * Run a DMA test which watches for unaligned completions and
+        * aborts on the first one seen.
+        */
 
+       status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST);
+       if (status == 0)
+               return;         /* keep the aligned firmware */
+
+       if (status != -E2BIG)
+               dev_warn(dev, "DMA test failed: %d\n", status);
+       if (status == -ENOSYS)
+               dev_warn(dev, "Falling back to ethp! "
+                        "Please install up to date fw\n");
+abort:
+       /* fall back to using the unaligned firmware */
        mgp->tx.boundary = 2048;
        mgp->fw_name = myri10ge_fw_unaligned;
 
+}
+
+static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
+{
        if (myri10ge_force_firmware == 0) {
                int link_width, exp_cap;
                u16 lnk;
@@ -2508,8 +2578,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
                pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
                link_width = (lnk >> 4) & 0x3f;
 
-               myri10ge_enable_ecrc(mgp);
-
                /* Check to see if Link is less than 8 or if the
                 * upstream bridge is known to provide aligned
                 * completions */
@@ -2518,46 +2586,8 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
                                 link_width);
                        mgp->tx.boundary = 4096;
                        mgp->fw_name = myri10ge_fw_aligned;
-               } else if (bridge &&
-                          /* ServerWorks HT2000/HT1000 */
-                          ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
-                            && bridge->device ==
-                            PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE)
-                           /* ServerWorks HT2100 */
-                           || (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
-                               && bridge->device >=
-                               PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST
-                               && bridge->device <=
-                               PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST)
-                           /* All Intel E3000/E3010 PCIE ports */
-                           || (bridge->vendor == PCI_VENDOR_ID_INTEL
-                               && (bridge->device ==
-                                   PCI_DEVICE_ID_INTEL_E3000_PCIE
-                                   || bridge->device ==
-                                   PCI_DEVICE_ID_INTEL_E3010_PCIE))
-                           /* All Intel 6310/6311/6321ESB PCIE ports */
-                           || (bridge->vendor == PCI_VENDOR_ID_INTEL
-                               && bridge->device >=
-                               PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1
-                               && bridge->device <=
-                               PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4)
-                           /* All Intel E5000 PCIE ports */
-                           || (bridge->vendor == PCI_VENDOR_ID_INTEL
-                               && bridge->device >=
-                               PCI_DEVICE_ID_INTEL_E5000_PCIE23
-                               && bridge->device <=
-                               PCI_DEVICE_ID_INTEL_E5000_PCIE47))) {
-                       dev_info(&mgp->pdev->dev,
-                                "Assuming aligned completions (0x%x:0x%x)\n",
-                                bridge->vendor, bridge->device);
-                       mgp->tx.boundary = 4096;
-                       mgp->fw_name = myri10ge_fw_aligned;
-               } else if (bridge &&
-                          bridge->vendor == PCI_VENDOR_ID_SGI &&
-                          bridge->device == 0x4002 /* TIOCE pcie-port */ ) {
-                       /* this pcie bridge does not support 4K rdma request */
-                       mgp->tx.boundary = 2048;
-                       mgp->fw_name = myri10ge_fw_aligned;
+               } else {
+                       myri10ge_firmware_probe(mgp);
                }
        } else {
                if (myri10ge_force_firmware == 1) {
@@ -2825,7 +2855,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                status = -ENODEV;
                goto abort_with_netdev;
        }
-       myri10ge_select_firmware(mgp);
 
        /* Find the vendor-specific cap so we can check
         * the reboot register later on */
@@ -2919,6 +2948,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto abort_with_ioremap;
        memset(mgp->rx_done.entry, 0, bytes);
 
+       myri10ge_select_firmware(mgp);
+
        status = myri10ge_load_firmware(mgp);
        if (status != 0) {
                dev_err(&pdev->dev, "failed to load firmware\n");
index 29463b301a84f5a1eb9614bb01fab4bd021d2d57..a1d2a22296a985f88eb56877bbfd835425d6c623 100644 (file)
@@ -200,6 +200,13 @@ enum myri10ge_mcp_cmd_type {
        /* data0, data1 = bus addr,
         * data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
         * adding new stuff to mcp_irq_data without changing the ABI */
+
+       MXGEFW_CMD_UNALIGNED_TEST,
+       /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned
+        * chipset */
+
+       MXGEFW_CMD_UNALIGNED_STATUS
+           /* return data = boolean, true if the chipset is known to be unaligned */
 };
 
 enum myri10ge_mcp_cmd_status {
@@ -212,18 +219,27 @@ enum myri10ge_mcp_cmd_status {
        MXGEFW_CMD_ERROR_HASH_ERROR,
        MXGEFW_CMD_ERROR_BAD_PORT,
        MXGEFW_CMD_ERROR_RESOURCES,
-       MXGEFW_CMD_ERROR_MULTICAST
+       MXGEFW_CMD_ERROR_MULTICAST,
+       MXGEFW_CMD_ERROR_UNALIGNED
 };
 
 #define MXGEFW_OLD_IRQ_DATA_LEN 40
 
 struct mcp_irq_data {
        /* add new counters at the beginning */
-       __be32 future_use[5];
+       __be32 future_use[1];
+       __be32 dropped_pause;
+       __be32 dropped_unicast_filtered;
+       __be32 dropped_bad_crc32;
+       __be32 dropped_bad_phy;
        __be32 dropped_multicast_filtered;
        /* 40 Bytes */
        __be32 send_done_count;
 
+#define MXGEFW_LINK_DOWN 0
+#define MXGEFW_LINK_UP 1
+#define MXGEFW_LINK_MYRINET 2
+#define MXGEFW_LINK_UNKNOWN 3
        __be32 link_up;
        __be32 dropped_link_overflow;
        __be32 dropped_link_error_or_filtered;
index a8d7ff2c96ac8381c7a79f737956d992cfda0f1a..4cf0d3fcb519d741559d9e016178f455a75884c3 100644 (file)
@@ -81,6 +81,8 @@ static const int multicast_filter_limit = 100;
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
+static int dspcfg_workaround = 1;
+
 /* Used to pass the media type, etc.
    Both 'options[]' and 'full_duplex[]' should exist for driver
    interoperability.
@@ -129,7 +131,6 @@ static const char version[] __devinitdata =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
   KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"
-  KERN_INFO "  http://www.scyld.com/network/natsemi.html\n"
   KERN_INFO "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -139,12 +140,14 @@ MODULE_LICENSE("GPL");
 module_param(mtu, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
+module_param(dspcfg_workaround, int, 1);
 module_param_array(options, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
 MODULE_PARM_DESC(debug, "DP8381x default debug level");
 MODULE_PARM_DESC(rx_copybreak,
        "DP8381x copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(dspcfg_workaround, "DP8381x: control DspCfg workaround");
 MODULE_PARM_DESC(options,
        "DP8381x: Bits 0-3: media type, bit 17: full duplex");
 MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)");
@@ -590,6 +593,7 @@ struct netdev_private {
        u32 srr;
        /* expected DSPCFG value */
        u16 dspcfg;
+       int dspcfg_workaround;
        /* parms saved in ethtool format */
        u16     speed;          /* The forced speed, 10Mb, 100Mb, gigabit */
        u8      duplex;         /* Duplex, half or full */
@@ -656,6 +660,56 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf);
 static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
 static const struct ethtool_ops ethtool_ops;
 
+#define NATSEMI_ATTR(_name) \
+static ssize_t natsemi_show_##_name(struct device *dev, \
+         struct device_attribute *attr, char *buf); \
+        static ssize_t natsemi_set_##_name(struct device *dev, \
+               struct device_attribute *attr, \
+               const char *buf, size_t count); \
+        static DEVICE_ATTR(_name, 0644, natsemi_show_##_name, natsemi_set_##_name)
+
+#define NATSEMI_CREATE_FILE(_dev, _name) \
+         device_create_file(&_dev->dev, &dev_attr_##_name)
+#define NATSEMI_REMOVE_FILE(_dev, _name) \
+         device_create_file(&_dev->dev, &dev_attr_##_name)
+
+NATSEMI_ATTR(dspcfg_workaround);
+
+static ssize_t natsemi_show_dspcfg_workaround(struct device *dev,
+                                             struct device_attribute *attr, 
+                                             char *buf)
+{
+       struct netdev_private *np = netdev_priv(to_net_dev(dev));
+
+       return sprintf(buf, "%s\n", np->dspcfg_workaround ? "on" : "off");
+}
+
+static ssize_t natsemi_set_dspcfg_workaround(struct device *dev,
+                                            struct device_attribute *attr,
+                                            const char *buf, size_t count)
+{
+       struct netdev_private *np = netdev_priv(to_net_dev(dev));
+       int new_setting;
+       u32 flags;
+
+        /* Find out the new setting */
+        if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
+                new_setting = 1;
+        else if (!strncmp("off", buf, count - 1)
+                 || !strncmp("0", buf, count - 1))
+               new_setting = 0;
+       else
+                 return count; 
+
+       spin_lock_irqsave(&np->lock, flags);
+
+       np->dspcfg_workaround = new_setting;
+
+       spin_unlock_irqrestore(&np->lock, flags);
+
+       return count;
+}
+
 static inline void __iomem *ns_ioaddr(struct net_device *dev)
 {
        return (void __iomem *) dev->base_addr;
@@ -820,6 +874,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
                np->ignore_phy = 1;
        else
                np->ignore_phy = 0;
+       np->dspcfg_workaround = dspcfg_workaround;
 
        /* Initial port:
         * - If configured to ignore the PHY set up for external.
@@ -899,6 +954,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        if (i)
                goto err_register_netdev;
 
+       if (NATSEMI_CREATE_FILE(pdev, dspcfg_workaround))
+               goto err_create_file;
+
        if (netif_msg_drv(np)) {
                printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ",
                        dev->name, natsemi_pci_info[chip_idx].name, iostart,
@@ -915,6 +973,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        }
        return 0;
 
+ err_create_file:
+       unregister_netdev(dev);
+
  err_register_netdev:
        iounmap(ioaddr);
 
@@ -1727,7 +1788,8 @@ static void init_registers(struct net_device *dev)
  *    It seems that a reference set for this chip went out with incorrect info,
  *    and there exist boards that aren't quite right.  An unexpected voltage
  *    drop can cause the PHY to get itself in a weird state (basically reset).
- *    NOTE: this only seems to affect revC chips.
+ *    NOTE: this only seems to affect revC chips.  The user can disable
+ *    this check via dspcfg_workaround sysfs option.
  * 3) check of death of the RX path due to OOM
  */
 static void netdev_timer(unsigned long data)
@@ -1753,10 +1815,10 @@ static void netdev_timer(unsigned long data)
                writew(1, ioaddr+PGSEL);
                dspcfg = readw(ioaddr+DSPCFG);
                writew(0, ioaddr+PGSEL);
-               if (dspcfg != np->dspcfg) {
+               if (np->dspcfg_workaround && dspcfg != np->dspcfg) {
                        if (!netif_queue_stopped(dev)) {
                                spin_unlock_irq(&np->lock);
-                               if (netif_msg_hw(np))
+                               if (netif_msg_drv(np))
                                        printk(KERN_NOTICE "%s: possible phy reset: "
                                                "re-initializing\n", dev->name);
                                disable_irq(dev->irq);
@@ -3157,6 +3219,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        void __iomem * ioaddr = ns_ioaddr(dev);
 
+       NATSEMI_REMOVE_FILE(pdev, dspcfg_workaround);
        unregister_netdev (dev);
        pci_release_regions (pdev);
        iounmap(ioaddr);
index a5c4199e2754cff0abc74303afd443e684386bce..c9f74bf5f4917634ff9d563bba0a0b2fc4d4df69 100644 (file)
@@ -51,14 +51,11 @@ static const char version2[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/jiffies.h>
+#include <linux/platform_device.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-#include <asm/tx4938/rbtx4938.h>
-#endif
-
 #include "8390.h"
 
 #define DRV_NAME "ne"
@@ -77,8 +74,13 @@ static const char version2[] =
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE   0x40 */
 
+#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
+/* Do we need a portlist for the ISA auto-probe ? */
+#define NEEDS_PORTLIST
+#endif
+
 /* A zero-terminated list of I/O addresses to be probed at boot. */
-#ifndef MODULE
+#ifdef NEEDS_PORTLIST
 static unsigned int netcard_portlist[] __initdata = {
        0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
 };
@@ -146,7 +148,7 @@ bad_clone_list[] __initdata = {
 #  define DCR_VAL 0x49
 #endif
 
-static int ne_probe1(struct net_device *dev, int ioaddr);
+static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
 static int ne_probe_isapnp(struct net_device *dev);
 
 static int ne_open(struct net_device *dev);
@@ -184,8 +186,8 @@ static void ne_block_output(struct net_device *dev, const int count,
 
 static int __init do_ne_probe(struct net_device *dev)
 {
-       unsigned int base_addr = dev->base_addr;
-#ifndef MODULE
+       unsigned long base_addr = dev->base_addr;
+#ifdef NEEDS_PORTLIST
        int orig_irq = dev->irq;
 #endif
 
@@ -201,7 +203,7 @@ static int __init do_ne_probe(struct net_device *dev)
        if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
                return 0;
 
-#ifndef MODULE
+#ifdef NEEDS_PORTLIST
        /* Last resort. The semi-risky ISA auto-probe. */
        for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
                int ioaddr = netcard_portlist[base_addr];
@@ -226,10 +228,6 @@ struct net_device * __init ne_probe(int unit)
        sprintf(dev->name, "eth%d", unit);
        netdev_boot_setup_check(dev);
 
-#ifdef CONFIG_TOSHIBA_RBTX4938
-       dev->base_addr = RBTX4938_RTL_8019_BASE;
-       dev->irq = RBTX4938_RTL_8019_IRQ;
-#endif
        err = do_ne_probe(dev);
        if (err)
                goto out;
@@ -285,7 +283,7 @@ static int __init ne_probe_isapnp(struct net_device *dev)
        return -ENODEV;
 }
 
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
+static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
 {
        int i;
        unsigned char SA_prom[32];
@@ -324,7 +322,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        if (ei_debug  &&  version_printed++ == 0)
                printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 
-       printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
+       printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
 
        /* A user with a poor card that fails to ack the reset, or that
           does not have a valid 0x57,0x57 signature can still use this
@@ -516,8 +514,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        }
 #endif
 
-       printk("\n%s: %s found at %#x, using IRQ %d.\n",
-               dev->name, name, ioaddr, dev->irq);
+       printk("\n");
 
        ei_status.name = name;
        ei_status.tx_start_page = start_page;
@@ -547,6 +544,8 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        ret = register_netdev(dev);
        if (ret)
                goto out_irq;
+       printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
+              dev->name, name, ioaddr, dev->irq);
        return 0;
 
 out_irq:
@@ -807,6 +806,87 @@ retry:
        return;
 }
 
+static int __init ne_drv_probe(struct platform_device *pdev)
+{
+       struct net_device *dev;
+       struct resource *res;
+       int err, irq;
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!res || irq < 0)
+               return -ENODEV;
+
+       dev = alloc_ei_netdev();
+       if (!dev)
+               return -ENOMEM;
+       dev->irq = irq;
+       dev->base_addr = res->start;
+       err = do_ne_probe(dev);
+       if (err) {
+               free_netdev(dev);
+               return err;
+       }
+       platform_set_drvdata(pdev, dev);
+       return 0;
+}
+
+static int __exit ne_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       unregister_netdev(dev);
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, NE_IO_EXTENT);
+       free_netdev(dev);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev))
+               netif_device_detach(dev);
+       return 0;
+}
+
+static int ne_drv_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               ne_reset_8390(dev);
+               NS8390_init(dev, 1);
+               netif_device_attach(dev);
+       }
+       return 0;
+}
+#else
+#define ne_drv_suspend NULL
+#define ne_drv_resume NULL
+#endif
+
+static struct platform_driver ne_driver = {
+       .remove         = __exit_p(ne_drv_remove),
+       .suspend        = ne_drv_suspend,
+       .resume         = ne_drv_resume,
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init ne_init(void)
+{
+       return platform_driver_probe(&ne_driver, ne_drv_probe);
+}
+
+static void __exit ne_exit(void)
+{
+       platform_driver_unregister(&ne_driver);
+}
 
 #ifdef MODULE
 #define MAX_NE_CARDS   4       /* Max number of NE cards per module */
@@ -832,6 +912,7 @@ ISA device autoprobes on a running machine are not recommended anyway. */
 int __init init_module(void)
 {
        int this_dev, found = 0;
+       int plat_found = !ne_init();
 
        for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
                struct net_device *dev = alloc_ei_netdev();
@@ -845,7 +926,7 @@ int __init init_module(void)
                        continue;
                }
                free_netdev(dev);
-               if (found)
+               if (found || plat_found)
                        break;
                if (io[this_dev] != 0)
                        printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
@@ -853,7 +934,7 @@ int __init init_module(void)
                        printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
                return -ENXIO;
        }
-       if (found)
+       if (found || plat_found)
                return 0;
        return -ENODEV;
 }
@@ -871,6 +952,7 @@ void __exit cleanup_module(void)
 {
        int this_dev;
 
+       ne_exit();
        for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
                struct net_device *dev = dev_ne[this_dev];
                if (dev) {
@@ -880,4 +962,7 @@ void __exit cleanup_module(void)
                }
        }
 }
+#else /* MODULE */
+module_init(ne_init);
+module_exit(ne_exit);
 #endif /* MODULE */
index 589785d1e762d1b280f9c267435b9535f93c3318..995c0a5d40662ec1c7c1238faeb9bc74384c29be 100644 (file)
@@ -63,8 +63,7 @@ static int options[MAX_UNITS];
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n"
-KERN_INFO "  http://www.scyld.com/network/ne2k-pci.html\n";
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n";
 
 #if defined(__powerpc__)
 #define inl_le(addr)  le32_to_cpu(inl(addr))
index 6a32338623f18bdeacca68b2ffc9e771cf03bfeb..3439f8c649f93e5281aed53ceb2a8b9067ff38c3 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/workqueue.h>
 #include <linux/init.h>
 #include <linux/ip.h>  /* for iph */
index 76fe9dd8e841581cd70dcbd09746bd7a84705ea0..bc7f3dee6e5b0934ba859d44f5e1882a71a14cd9 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/tcp.h>
 #include <net/checksum.h>
 
+#include <asm/irq.h>
+
 #include "pasemi_mac.h"
 
 
 #define RX_RING_SIZE 512
 #define TX_RING_SIZE 512
 
+#define DEFAULT_MSG_ENABLE       \
+       (NETIF_MSG_DRV          | \
+        NETIF_MSG_PROBE        | \
+        NETIF_MSG_LINK         | \
+        NETIF_MSG_TIMER        | \
+        NETIF_MSG_IFDOWN       | \
+        NETIF_MSG_IFUP         | \
+        NETIF_MSG_RX_ERR       | \
+        NETIF_MSG_TX_ERR)
+
 #define TX_DESC(mac, num)      ((mac)->tx->desc[(num) & (TX_RING_SIZE-1)])
 #define TX_DESC_INFO(mac, num) ((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)])
 #define RX_DESC(mac, num)      ((mac)->rx->desc[(num) & (RX_RING_SIZE-1)])
 
 #define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
 
-/* XXXOJN these should come out of the device tree some day */
-#define PAS_DMA_CAP_BASE   0xe00d0040
-#define PAS_DMA_CAP_SIZE   0x100
-#define PAS_DMA_COM_BASE   0xe00d0100
-#define PAS_DMA_COM_SIZE   0x100
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
+
+static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
 
 static struct pasdma_status *dma_status;
 
@@ -80,7 +94,12 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
                return -ENOENT;
        }
 
-       maddr = get_property(dn, "mac-address", NULL);
+       maddr = of_get_property(dn, "local-mac-address", NULL);
+
+       /* Fall back to mac-address for older firmware */
+       if (maddr == NULL)
+               maddr = of_get_property(dn, "mac-address", NULL);
+
        if (maddr == NULL) {
                dev_warn(&pdev->dev,
                         "no mac address in device tree, not configuring\n");
@@ -277,8 +296,8 @@ static void pasemi_mac_free_rx_resources(struct net_device *dev)
        for (i = 0; i < RX_RING_SIZE; i++) {
                info = &RX_DESC_INFO(mac, i);
                dp = &RX_DESC(mac, i);
-               if (info->dma) {
-                       if (info->skb) {
+               if (info->skb) {
+                       if (info->dma) {
                                pci_unmap_single(mac->dma_pdev,
                                                 info->dma,
                                                 info->skb->len,
@@ -309,82 +328,120 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev)
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int i;
        int start = mac->rx->next_to_fill;
-       unsigned int count;
+       unsigned int limit, count;
 
-       count = (mac->rx->next_to_clean + RX_RING_SIZE -
+       limit = (mac->rx->next_to_clean + RX_RING_SIZE -
                 mac->rx->next_to_fill) & (RX_RING_SIZE - 1);
 
        /* Check to see if we're doing first-time setup */
        if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0))
-               count = RX_RING_SIZE;
+               limit = RX_RING_SIZE;
 
-       if (count <= 0)
+       if (limit <= 0)
                return;
 
-       for (i = start; i < start + count; i++) {
+       i = start;
+       for (count = limit; count; count--) {
                struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
                u64 *buff = &RX_BUFF(mac, i);
                struct sk_buff *skb;
                dma_addr_t dma;
 
-               skb = dev_alloc_skb(BUF_SIZE);
+               /* skb might still be in there for recycle on short receives */
+               if (info->skb)
+                       skb = info->skb;
+               else
+                       skb = dev_alloc_skb(BUF_SIZE);
 
-               if (!skb) {
-                       count = i - start;
+               if (unlikely(!skb))
                        break;
-               }
 
                dma = pci_map_single(mac->dma_pdev, skb->data, skb->len,
                                     PCI_DMA_FROMDEVICE);
 
-               if (dma_mapping_error(dma)) {
+               if (unlikely(dma_mapping_error(dma))) {
                        dev_kfree_skb_irq(info->skb);
-                       count = i - start;
                        break;
                }
 
                info->skb = skb;
                info->dma = dma;
                *buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
+               i++;
        }
 
        wmb();
 
        pci_write_config_dword(mac->dma_pdev,
                               PAS_DMA_RXCHAN_INCR(mac->dma_rxch),
-                              count);
+                              limit - count);
        pci_write_config_dword(mac->dma_pdev,
                               PAS_DMA_RXINT_INCR(mac->dma_if),
-                              count);
+                              limit - count);
 
-       mac->rx->next_to_fill += count;
+       mac->rx->next_to_fill += limit - count;
 }
 
+static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
+{
+       unsigned int reg, stat;
+       /* Re-enable packet count interrupts: finally
+        * ack the packet count interrupt we got in rx_intr.
+        */
+
+       pci_read_config_dword(mac->iob_pdev,
+                             PAS_IOB_DMA_RXCH_STAT(mac->dma_rxch),
+                             &stat);
+
+       reg = PAS_IOB_DMA_RXCH_RESET_PCNT(stat & PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
+               | PAS_IOB_DMA_RXCH_RESET_PINTC;
+
+       pci_write_config_dword(mac->iob_pdev,
+                              PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch),
+                              reg);
+}
+
+static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
+{
+       unsigned int reg, stat;
+
+       /* Re-enable packet count interrupts */
+       pci_read_config_dword(mac->iob_pdev,
+                             PAS_IOB_DMA_TXCH_STAT(mac->dma_txch), &stat);
+
+       reg = PAS_IOB_DMA_TXCH_RESET_PCNT(stat & PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
+               | PAS_IOB_DMA_TXCH_RESET_PINTC;
+
+       pci_write_config_dword(mac->iob_pdev,
+                              PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
+}
+
+
 static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 {
-       unsigned int i;
-       int start, count;
+       unsigned int n;
+       int count;
+       struct pas_dma_xct_descr *dp;
+       struct pasemi_mac_buffer *info;
+       struct sk_buff *skb;
+       unsigned int i, len;
+       u64 macrx;
+       dma_addr_t dma;
 
        spin_lock(&mac->rx->lock);
 
-       start = mac->rx->next_to_clean;
-       count = 0;
+       n = mac->rx->next_to_clean;
 
-       for (i = start; i < (start + RX_RING_SIZE) && count < limit; i++) {
-               struct pas_dma_xct_descr *dp;
-               struct pasemi_mac_buffer *info;
-               struct sk_buff *skb;
-               unsigned int j, len;
-               dma_addr_t dma;
+       for (count = limit; count; count--) {
 
                rmb();
 
-               dp = &RX_DESC(mac, i);
+               dp = &RX_DESC(mac, n);
+               macrx = dp->macrx;
 
-               if (!(dp->macrx & XCT_MACRX_O))
+               if (!(macrx & XCT_MACRX_O))
                        break;
 
-               count++;
 
                info = NULL;
 
@@ -396,29 +453,42 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
                 */
 
                dma = (dp->ptr & XCT_PTR_ADDR_M);
-               for (j = start; j < (start + RX_RING_SIZE); j++) {
-                       info = &RX_DESC_INFO(mac, j);
+               for (i = n; i < (n + RX_RING_SIZE); i++) {
+                       info = &RX_DESC_INFO(mac, i);
                        if (info->dma == dma)
                                break;
                }
 
-               BUG_ON(!info);
-               BUG_ON(info->dma != dma);
+               skb = info->skb;
+               info->dma = 0;
 
-               pci_unmap_single(mac->dma_pdev, info->dma, info->skb->len,
+               pci_unmap_single(mac->dma_pdev, dma, skb->len,
                                 PCI_DMA_FROMDEVICE);
 
-               skb = info->skb;
-
-               len = (dp->macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
+               len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
+
+               if (len < 256) {
+                       struct sk_buff *new_skb =
+                           netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
+                       if (new_skb) {
+                               skb_reserve(new_skb, NET_IP_ALIGN);
+                               memcpy(new_skb->data - NET_IP_ALIGN,
+                                       skb->data - NET_IP_ALIGN,
+                                       len + NET_IP_ALIGN);
+                               /* save the skb in buffer_info as good */
+                               skb = new_skb;
+                       }
+                       /* else just continue with the old one */
+               } else
+                       info->skb = NULL;
 
                skb_put(skb, len);
 
                skb->protocol = eth_type_trans(skb, mac->netdev);
 
-               if ((dp->macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) {
+               if ((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) {
                        skb->ip_summed = CHECKSUM_COMPLETE;
-                       skb->csum = (dp->macrx & XCT_MACRX_CSUM_M) >>
+                       skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
                                           XCT_MACRX_CSUM_S;
                } else
                        skb->ip_summed = CHECKSUM_NONE;
@@ -428,13 +498,13 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 
                netif_receive_skb(skb);
 
-               info->dma = 0;
-               info->skb = NULL;
                dp->ptr = 0;
                dp->macrx = 0;
+
+               n++;
        }
 
-       mac->rx->next_to_clean += count;
+       mac->rx->next_to_clean += limit - count;
        pasemi_mac_replenish_rx_ring(mac->netdev);
 
        spin_unlock(&mac->rx->lock);
@@ -476,6 +546,8 @@ static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
        mac->tx->next_to_clean += count;
        spin_unlock_irqrestore(&mac->tx->lock, flags);
 
+       netif_wake_queue(mac->netdev);
+
        return count;
 }
 
@@ -486,18 +558,28 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int reg;
 
-       if (!(*mac->rx_status & PAS_STATUS_INT))
+       if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
                return IRQ_NONE;
 
-       netif_rx_schedule(dev);
-       pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
-                              PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0));
+       if (*mac->rx_status & PAS_STATUS_ERROR)
+               printk("rx_status reported error\n");
+
+       /* Don't reset packet count so it won't fire again but clear
+        * all others.
+        */
+
+       pci_read_config_dword(mac->dma_pdev, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), &reg);
 
-       reg = PAS_IOB_DMA_RXCH_RESET_PINTC | PAS_IOB_DMA_RXCH_RESET_SINTC |
-             PAS_IOB_DMA_RXCH_RESET_DINTC;
+       reg = 0;
+       if (*mac->rx_status & PAS_STATUS_SOFT)
+               reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
+       if (*mac->rx_status & PAS_STATUS_ERROR)
+               reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
        if (*mac->rx_status & PAS_STATUS_TIMER)
                reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
 
+       netif_rx_schedule(dev);
+
        pci_write_config_dword(mac->iob_pdev,
                               PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
 
@@ -510,31 +592,137 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
        struct net_device *dev = data;
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int reg;
-       int was_full;
 
-       was_full = mac->tx->next_to_clean - mac->tx->next_to_use == TX_RING_SIZE;
-
-       if (!(*mac->tx_status & PAS_STATUS_INT))
+       if (!(*mac->tx_status & PAS_STATUS_CAUSE_M))
                return IRQ_NONE;
 
        pasemi_mac_clean_tx(mac);
 
-       reg = PAS_IOB_DMA_TXCH_RESET_PINTC | PAS_IOB_DMA_TXCH_RESET_SINTC;
-       if (*mac->tx_status & PAS_STATUS_TIMER)
-               reg |= PAS_IOB_DMA_TXCH_RESET_TINTC;
+       reg = PAS_IOB_DMA_TXCH_RESET_PINTC;
+
+       if (*mac->tx_status & PAS_STATUS_SOFT)
+               reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
+       if (*mac->tx_status & PAS_STATUS_ERROR)
+               reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
 
        pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
                               reg);
 
-       if (was_full)
-               netif_wake_queue(dev);
-
        return IRQ_HANDLED;
 }
 
+static void pasemi_adjust_link(struct net_device *dev)
+{
+       struct pasemi_mac *mac = netdev_priv(dev);
+       int msg;
+       unsigned int flags;
+       unsigned int new_flags;
+
+       if (!mac->phydev->link) {
+               /* If no link, MAC speed settings don't matter. Just report
+                * link down and return.
+                */
+               if (mac->link && netif_msg_link(mac))
+                       printk(KERN_INFO "%s: Link is down.\n", dev->name);
+
+               netif_carrier_off(dev);
+               mac->link = 0;
+
+               return;
+       } else
+               netif_carrier_on(dev);
+
+       pci_read_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, &flags);
+       new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
+                             PAS_MAC_CFG_PCFG_TSR_M);
+
+       if (!mac->phydev->duplex)
+               new_flags |= PAS_MAC_CFG_PCFG_HD;
+
+       switch (mac->phydev->speed) {
+       case 1000:
+               new_flags |= PAS_MAC_CFG_PCFG_SPD_1G |
+                            PAS_MAC_CFG_PCFG_TSR_1G;
+               break;
+       case 100:
+               new_flags |= PAS_MAC_CFG_PCFG_SPD_100M |
+                            PAS_MAC_CFG_PCFG_TSR_100M;
+               break;
+       case 10:
+               new_flags |= PAS_MAC_CFG_PCFG_SPD_10M |
+                            PAS_MAC_CFG_PCFG_TSR_10M;
+               break;
+       default:
+               printk("Unsupported speed %d\n", mac->phydev->speed);
+       }
+
+       /* Print on link or speed/duplex change */
+       msg = mac->link != mac->phydev->link || flags != new_flags;
+
+       mac->duplex = mac->phydev->duplex;
+       mac->speed = mac->phydev->speed;
+       mac->link = mac->phydev->link;
+
+       if (new_flags != flags)
+               pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, new_flags);
+
+       if (msg && netif_msg_link(mac))
+               printk(KERN_INFO "%s: Link is up at %d Mbps, %s duplex.\n",
+                      dev->name, mac->speed, mac->duplex ? "full" : "half");
+}
+
+static int pasemi_mac_phy_init(struct net_device *dev)
+{
+       struct pasemi_mac *mac = netdev_priv(dev);
+       struct device_node *dn, *phy_dn;
+       struct phy_device *phydev;
+       unsigned int phy_id;
+       const phandle *ph;
+       const unsigned int *prop;
+       struct resource r;
+       int ret;
+
+       dn = pci_device_to_OF_node(mac->pdev);
+       ph = of_get_property(dn, "phy-handle", NULL);
+       if (!ph)
+               return -ENODEV;
+       phy_dn = of_find_node_by_phandle(*ph);
+
+       prop = of_get_property(phy_dn, "reg", NULL);
+       ret = of_address_to_resource(phy_dn->parent, 0, &r);
+       if (ret)
+               goto err;
+
+       phy_id = *prop;
+       snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
+
+       of_node_put(phy_dn);
+
+       mac->link = 0;
+       mac->speed = 0;
+       mac->duplex = -1;
+
+       phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII);
+
+       if (IS_ERR(phydev)) {
+               printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
+               return PTR_ERR(phydev);
+       }
+
+       mac->phydev = phydev;
+
+       return 0;
+
+err:
+       of_node_put(phy_dn);
+       return -ENODEV;
+}
+
+
 static int pasemi_mac_open(struct net_device *dev)
 {
        struct pasemi_mac *mac = netdev_priv(dev);
+       int base_irq;
        unsigned int flags;
        int ret;
 
@@ -558,10 +746,18 @@ static int pasemi_mac_open(struct net_device *dev)
        flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
 
        pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
-                              PAS_IOB_DMA_RXCH_CFG_CNTTH(30));
+                              PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
 
+       pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
+                              PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
+
+       /* Clear out any residual packet count state from firmware */
+       pasemi_mac_restart_rx_intr(mac);
+       pasemi_mac_restart_tx_intr(mac);
+
+       /* 0xffffff is max value, about 16ms */
        pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
-                              PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000));
+                              PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
 
        pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags);
 
@@ -595,31 +791,50 @@ static int pasemi_mac_open(struct net_device *dev)
 
        pasemi_mac_replenish_rx_ring(dev);
 
+       ret = pasemi_mac_phy_init(dev);
+       /* Some configs don't have PHYs (XAUI etc), so don't complain about
+        * failed init due to -ENODEV.
+        */
+       if (ret && ret != -ENODEV)
+               dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret);
+
        netif_start_queue(dev);
        netif_poll_enable(dev);
 
-       ret = request_irq(mac->dma_pdev->irq + mac->dma_txch,
-                         &pasemi_mac_tx_intr, IRQF_DISABLED,
+       /* Interrupts are a bit different for our DMA controller: While
+        * it's got one a regular PCI device header, the interrupt there
+        * is really the base of the range it's using. Each tx and rx
+        * channel has it's own interrupt source.
+        */
+
+       base_irq = virq_to_hw(mac->dma_pdev->irq);
+
+       mac->tx_irq = irq_create_mapping(NULL, base_irq + mac->dma_txch);
+       mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_txch);
+
+       ret = request_irq(mac->tx_irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
                          mac->tx->irq_name, dev);
        if (ret) {
                dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
-                      mac->dma_pdev->irq + mac->dma_txch, ret);
+                       base_irq + mac->dma_txch, ret);
                goto out_tx_int;
        }
 
-       ret = request_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch,
-                         &pasemi_mac_rx_intr, IRQF_DISABLED,
+       ret = request_irq(mac->rx_irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
                          mac->rx->irq_name, dev);
        if (ret) {
                dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
-                      mac->dma_pdev->irq + 20 + mac->dma_rxch, ret);
+                       base_irq + 20 + mac->dma_rxch, ret);
                goto out_rx_int;
        }
 
+       if (mac->phydev)
+               phy_start(mac->phydev);
+
        return 0;
 
 out_rx_int:
-       free_irq(mac->dma_pdev->irq + mac->dma_txch, dev);
+       free_irq(mac->tx_irq, dev);
 out_tx_int:
        netif_poll_disable(dev);
        netif_stop_queue(dev);
@@ -639,6 +854,11 @@ static int pasemi_mac_close(struct net_device *dev)
        unsigned int stat;
        int retries;
 
+       if (mac->phydev) {
+               phy_stop(mac->phydev);
+               phy_disconnect(mac->phydev);
+       }
+
        netif_stop_queue(dev);
 
        /* Clean out any pending buffers */
@@ -660,40 +880,37 @@ static int pasemi_mac_close(struct net_device *dev)
                pci_read_config_dword(mac->dma_pdev,
                                      PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
                                      &stat);
-               if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+               if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
                        break;
                cond_resched();
        }
 
-       if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
+       if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
                dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
-       }
 
        for (retries = 0; retries < MAX_RETRIES; retries++) {
                pci_read_config_dword(mac->dma_pdev,
                                      PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
                                      &stat);
-               if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+               if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
                        break;
                cond_resched();
        }
 
-       if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
+       if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
                dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
-       }
 
        for (retries = 0; retries < MAX_RETRIES; retries++) {
                pci_read_config_dword(mac->dma_pdev,
                                      PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
                                      &stat);
-               if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
+               if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
                        break;
                cond_resched();
        }
 
-       if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT)) {
+       if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
                dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
-       }
 
        /* Then, disable the channel. This must be done separately from
         * stopping, since you can't disable when active.
@@ -706,8 +923,8 @@ static int pasemi_mac_close(struct net_device *dev)
        pci_write_config_dword(mac->dma_pdev,
                               PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
 
-       free_irq(mac->dma_pdev->irq + mac->dma_txch, dev);
-       free_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch, dev);
+       free_irq(mac->tx_irq, dev);
+       free_irq(mac->rx_irq, dev);
 
        /* Free resources */
        pasemi_mac_free_rx_resources(dev);
@@ -802,6 +1019,7 @@ static struct net_device_stats *pasemi_mac_get_stats(struct net_device *dev)
        return &mac->stats;
 }
 
+
 static void pasemi_mac_set_rx_mode(struct net_device *dev)
 {
        struct pasemi_mac *mac = netdev_priv(dev);
@@ -826,18 +1044,17 @@ static int pasemi_mac_poll(struct net_device *dev, int *budget)
 
        pkts = pasemi_mac_clean_rx(mac, limit);
 
+       dev->quota -= pkts;
+       *budget -= pkts;
+
        if (pkts < limit) {
                /* all done, no more packets present */
                netif_rx_complete(dev);
 
-               /* re-enable receive interrupts */
-               pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
-                                      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000));
+               pasemi_mac_restart_rx_intr(mac);
                return 0;
        } else {
                /* used up our quantum, so reschedule */
-               dev->quota -= pkts;
-               *budget -= pkts;
                return 1;
        }
 }
@@ -937,6 +1154,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mac->rx_status = &dma_status->rx_sta[mac->dma_rxch];
        mac->tx_status = &dma_status->tx_sta[mac->dma_txch];
 
+       mac->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
+
+       /* Enable most messages by default */
+       mac->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
+
        err = register_netdev(dev);
 
        if (err) {
@@ -1011,9 +1233,5 @@ int pasemi_mac_init_module(void)
        return pci_register_driver(&pasemi_mac_driver);
 }
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
-MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
-
 module_init(pasemi_mac_init_module);
 module_exit(pasemi_mac_cleanup_module);
index c3e37e46a18ad9881c98950c2eb8bb73c53ea210..8bc0cea8b145517b9f527b24d71ca9267ebc00c0 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
+#include <linux/phy.h>
 
 struct pasemi_mac_txring {
        spinlock_t       lock;
@@ -54,6 +55,7 @@ struct pasemi_mac {
        struct pci_dev *pdev;
        struct pci_dev *dma_pdev;
        struct pci_dev *iob_pdev;
+       struct phy_device *phydev;
        struct net_device_stats stats;
 
        /* Pointer to the cacheable per-channel status registers */
@@ -73,6 +75,14 @@ struct pasemi_mac {
 
        struct pasemi_mac_txring *tx;
        struct pasemi_mac_rxring *rx;
+       unsigned long   tx_irq;
+       unsigned long   rx_irq;
+       int     link;
+       int     speed;
+       int     duplex;
+
+       unsigned int    msg_enable;
+       char    phy_id[BUS_ID_SIZE];
 };
 
 /* Software status descriptor (desc_info) */
@@ -193,11 +203,15 @@ enum {
 #define PAS_DMA_RXINT_RCMDSTA(i)       (0x200+(i)*_PAS_DMA_RXINT_STRIDE)
 #define    PAS_DMA_RXINT_RCMDSTA_EN    0x00000001
 #define    PAS_DMA_RXINT_RCMDSTA_ST    0x00000002
-#define    PAS_DMA_RXINT_RCMDSTA_OO    0x00000100
-#define    PAS_DMA_RXINT_RCMDSTA_BP    0x00000200
-#define    PAS_DMA_RXINT_RCMDSTA_DR    0x00000400
+#define    PAS_DMA_RXINT_RCMDSTA_MBT   0x00000008
+#define    PAS_DMA_RXINT_RCMDSTA_MDR   0x00000010
+#define    PAS_DMA_RXINT_RCMDSTA_MOO   0x00000020
+#define    PAS_DMA_RXINT_RCMDSTA_MBP   0x00000040
 #define    PAS_DMA_RXINT_RCMDSTA_BT    0x00000800
-#define    PAS_DMA_RXINT_RCMDSTA_TB    0x00001000
+#define    PAS_DMA_RXINT_RCMDSTA_DR    0x00001000
+#define    PAS_DMA_RXINT_RCMDSTA_OO    0x00002000
+#define    PAS_DMA_RXINT_RCMDSTA_BP    0x00004000
+#define    PAS_DMA_RXINT_RCMDSTA_TB    0x00008000
 #define    PAS_DMA_RXINT_RCMDSTA_ACT   0x00010000
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_M       0xfffe0000
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_S       17
@@ -297,6 +311,7 @@ enum {
 #define    PAS_STATUS_DCNT_S           16
 #define    PAS_STATUS_BPCNT_M          0x0000ffff00000000ull
 #define    PAS_STATUS_BPCNT_S          32
+#define    PAS_STATUS_CAUSE_M          0xf000000000000000ull
 #define    PAS_STATUS_TIMER            0x1000000000000000ull
 #define    PAS_STATUS_ERROR            0x2000000000000000ull
 #define    PAS_STATUS_SOFT             0x4000000000000000ull
index 809ec440b8eb03896bf833d5b1a3cfb8f51adc06..258d6f396186bcd0ca015993d49c0bb634e92633 100644 (file)
@@ -1420,7 +1420,7 @@ set_addresses(struct net_device *dev)
     kio_addr_t ioaddr = dev->base_addr;
     local_info_t *lp = netdev_priv(dev);
     struct dev_mc_list *dmi = dev->mc_list;
-    char *addr;
+    unsigned char *addr;
     int i,j,k,n;
 
     SelectPage(k=0x50);
@@ -1429,6 +1429,9 @@ set_addresses(struct net_device *dev)
            if (++n > 9)
                break;
            i = 0;
+           if (n > 1 && n <= dev->mc_count && dmi) {
+                dmi = dmi->next;
+           }
        }
        if (j > 15) {
            j = 8;
@@ -1436,10 +1439,9 @@ set_addresses(struct net_device *dev)
            SelectPage(k);
        }
 
-       if (n && n <= dev->mc_count && dmi) {
+       if (n && n <= dev->mc_count && dmi)
            addr = dmi->dmi_addr;
-           dmi = dmi->next;
-       } else
+       else
            addr = dev->dev_addr;
 
        if (lp->mohawk)
@@ -1465,10 +1467,10 @@ set_multicast_list(struct net_device *dev)
     if (dev->flags & IFF_PROMISC) { /* snoop */
        PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */
     } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) {
-       PutByte(XIRCREG42_SWC1, 0x06); /* set MPE */
+       PutByte(XIRCREG42_SWC1, 0x02); /* set MPE */
     } else if (dev->mc_count) {
        /* the chip can filter 9 addresses perfectly */
-       PutByte(XIRCREG42_SWC1, 0x00);
+       PutByte(XIRCREG42_SWC1, 0x01);
        SelectPage(0x40);
        PutByte(XIRCREG40_CMD0, Offline);
        set_addresses(dev);
index eed433d6056a2ddae3bad391e09ebec087892475..f71dab347667cd3fc33b408aaa55c0fdf7e4e570 100644 (file)
@@ -662,10 +662,10 @@ int phy_stop_interrupts(struct phy_device *phydev)
                phy_error(phydev);
 
        /*
-        * Finish any pending work; we might have been scheduled
-        * to be called from keventd ourselves, though.
+        * Finish any pending work; we might have been scheduled to be called
+        * from keventd ourselves, but cancel_work_sync() handles that.
         */
-       run_scheduled_work(&phydev->phy_queue);
+       cancel_work_sync(&phydev->phy_queue);
 
        free_irq(phydev->irq, phydev);
 
index 6d596ca50cfd1e469407ece20905ffa3d24f2fe1..541168713f1ff671beb7945ee36b223a27a95a77 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/rwsem.h>
 #include <linux/stddef.h>
 #include <linux/device.h>
index 21afe108d3cb3908efd888650104a09a0b3b4d46..b07da1054add14a8d26af46ce418b6a2c7f24866 100644 (file)
@@ -135,10 +135,13 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
 static u32 wol_supported(const struct skge_hw *hw)
 {
-       if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev != 0)
-               return WAKE_MAGIC | WAKE_PHY;
-       else
+       if (hw->chip_id == CHIP_ID_GENESIS)
                return 0;
+
+       if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)
+               return 0;
+
+       return WAKE_MAGIC | WAKE_PHY;
 }
 
 static u32 pci_wake_enabled(struct pci_dev *dev)
index 238c2ca34da63cbd239fd6f9a92eb4ce347d95d5..a307310f13f5e7c6ef05fea1126fdbb3928cdabf 100644 (file)
@@ -124,10 +124,7 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
-#ifdef broken
-       /* This device causes data corruption problems that are not resolved */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
-#endif
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
@@ -3581,10 +3578,21 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out;
        }
 
+       /* Some Gigabyte motherboards have 88e8056 but cause problems
+        * There is some unresolved hardware related problem that causes
+        * descriptor errors and receive data corruption.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_MARVELL &&
+           pdev->device == 0x4364 && pdev->subsystem_vendor == 0x1458) {
+               dev_err(&pdev->dev,
+                       "88E8056 on Gigabyte motherboards not supported\n");
+               goto err_out_disable;
+       }
+
        err = pci_request_regions(pdev, DRV_NAME);
        if (err) {
                dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-               goto err_out;
+               goto err_out_disable;
        }
 
        pci_set_master(pdev);
@@ -3721,6 +3729,7 @@ err_out_free_hw:
        kfree(hw);
 err_out_free_regions:
        pci_release_regions(pdev);
+err_out_disable:
        pci_disable_device(pdev);
 err_out:
        return err;
index 7053026d6c765aa0fecfcecaaf995e7409b9d2ee..111f23d05764b1544ee06f6f0e9d95a3bafee31f 100644 (file)
@@ -279,6 +279,40 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
 
+#elif   defined(CONFIG_SUPERH)
+
+#if defined(CONFIG_SH_7780_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      0
+#define SMC_IO_SHIFT           0
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          (inw((a) + ((r)&~1)) >> (8*(r%2)))&0xff
+#define SMC_inw(a, r)          inw((a) + (r))
+#define SMC_outb(v, a, r)      outw(((inw((a)+((r)&~1))*(0xff<<8*(r%2)))) | ((v)<<(8*(r&2)))), (a) + ((r)&~1))
+
+#define SMC_outw(v, a, r)      outw(v, (a) + (r))
+#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
+
+#else /* BOARDS */
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+
+#define SMC_inb(a, r)          inb((a) + (r))
+#define SMC_inw(a, r)          inw((a) + (r))
+#define SMC_outb(v, a, r)      outb(v, (a) + (r))
+#define SMC_outw(v, a, r)      outw(v, (a) + (r))
+#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
+
+#endif  /* BOARDS */
+
+#define set_irq_type(irq, type) do {} while (0)
+
 #elif   defined(CONFIG_M32R)
 
 #define SMC_CAN_USE_8BIT       0
index 230da14b1b682f44c87fab30b52c2ad0033b5c51..c15e97253ede41611153c4fdbd12b3376165f631 100644 (file)
@@ -1830,7 +1830,7 @@ try_host_fw:
        if (!dn)
                goto out_err;
 
-       fw_prop = get_property(dn, "firmware", &fw_size);
+       fw_prop = of_get_property(dn, "firmware", &fw_size);
        if (!fw_prop)
                goto out_err;
 
@@ -2236,7 +2236,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
        if (!dn)
                return -EIO;
 
-       mac = get_property(dn, "local-mac-address", NULL);
+       mac = of_get_property(dn, "local-mac-address", NULL);
        if (!mac)
                return -EIO;
        memcpy(addr.sa_data, mac, ETH_ALEN);
index f51ba31970aa34766482f629b147831cc4542efa..e1f912d04043e82c3de70201ed87d0ceb7b097f2 100644 (file)
@@ -110,8 +110,7 @@ static char *media[MAX_UNITS];
 
 /* These identify the driver base version and may not be removed. */
 static char version[] =
-KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
-KERN_INFO "  http://www.scyld.com/network/sundance.html\n";
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
index 5da73212ac9189980286f519278535aab9a41775..4328038550344733f910f50f2f8e87e31a7fbf11 100644 (file)
@@ -2903,7 +2903,7 @@ static int __devinit gem_get_device_address(struct gem *gp)
        struct net_device *dev = gp->dev;
        const unsigned char *addr;
 
-       addr = get_property(gp->of_node, "local-mac-address", NULL);
+       addr = of_get_property(gp->of_node, "local-mac-address", NULL);
        if (addr == NULL) {
 #ifdef CONFIG_SPARC
                addr = idprom->id_ethaddr;
index 56a110ca5e6ffce292ff9287ffb6703202879e21..61843fd5752517344f03e78c758f87cd795c4f0b 100644 (file)
@@ -451,7 +451,7 @@ static int bcm5421_init(struct mii_phy* phy)
        if (phy->platform_data) {
                struct device_node *np = of_get_parent(phy->platform_data);
                int can_low_power = 1;
-               if (np == NULL || get_property(np, "no-autolowpower", NULL))
+               if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
                        can_low_power = 0;
                if (can_low_power) {
                        /* Enable automatic low-power */
index f1e2dfc795a2bdce9036259f76c207e5d6c06af0..463d600ed83d88a1f656430ac980537ddc6d8846 100644 (file)
@@ -540,7 +540,6 @@ static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev,
        skb = dev_alloc_skb(RX_BUF_SIZE);
        if (!skb)
                return NULL;
-       skb->dev = dev;
        *dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE,
                                     PCI_DMA_FROMDEVICE);
        if (pci_dma_mapping_error(*dma_handle)) {
index e5e901ecd80815e16bc8212b80ec047f85421a54..923b9c725cc3f4e5cd75434914dbb4ce466c151f 100644 (file)
@@ -3716,10 +3716,8 @@ static void tg3_reset_task(struct work_struct *work)
        unsigned int restart_timer;
 
        tg3_full_lock(tp, 0);
-       tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK;
 
        if (!netif_running(tp->dev)) {
-               tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
                tg3_full_unlock(tp);
                return;
        }
@@ -3750,8 +3748,6 @@ static void tg3_reset_task(struct work_struct *work)
                mod_timer(&tp->timer, jiffies + 1);
 
 out:
-       tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
-
        tg3_full_unlock(tp);
 }
 
@@ -7390,12 +7386,7 @@ static int tg3_close(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       /* Calling flush_scheduled_work() may deadlock because
-        * linkwatch_event() may be on the workqueue and it will try to get
-        * the rtnl_lock which we are holding.
-        */
-       while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK)
-               msleep(1);
+       cancel_work_sync(&tp->reset_task);
 
        netif_stop_queue(dev);
 
index 4d334cf5a243b905a4e65a9a3f3cf9fc66be42bf..bd9f4f428e5b8895d5cc8c281302e00e0c6bdfba 100644 (file)
@@ -2228,7 +2228,7 @@ struct tg3 {
 #define TG3_FLAG_JUMBO_RING_ENABLE     0x00800000
 #define TG3_FLAG_10_100_ONLY           0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG         0x02000000
-#define TG3_FLAG_IN_RESET_TASK         0x04000000
+
 #define TG3_FLAG_40BIT_DMA_BUG         0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS      0x10000000
 #define TG3_FLAG_SUPPORT_MSI           0x20000000
index 0bfc2c9c1c083223820102cad66f1e747c3b3e05..1aabc91f6458e3d5c3a2b880127002a05d45ee01 100644 (file)
@@ -82,6 +82,7 @@ struct tsi108_prv_data {
        unsigned int phy;               /* Index of PHY for this interface */
        unsigned int irq_num;
        unsigned int id;
+       unsigned int phy_type;
 
        struct timer_list timer;/* Timer that triggers the check phy function */
        unsigned int rxtail;    /* Next entry in rxring to read */
@@ -1256,11 +1257,11 @@ static void tsi108_init_phy(struct net_device *dev)
        if (i == 0)
                printk(KERN_ERR "%s function time out \n", __FUNCTION__);
 
-#if (TSI108_PHY_TYPE == PHY_BCM54XX)   /* Broadcom BCM54xx PHY */
-       tsi108_write_mii(data, 0x09, 0x0300);
-       tsi108_write_mii(data, 0x10, 0x1020);
-       tsi108_write_mii(data, 0x1c, 0x8c00);
-#endif
+       if (data->phy_type == TSI108_PHY_BCM54XX) {
+               tsi108_write_mii(data, 0x09, 0x0300);
+               tsi108_write_mii(data, 0x10, 0x1020);
+               tsi108_write_mii(data, 0x1c, 0x8c00);
+       }
 
        tsi108_write_mii(data,
                         MII_BMCR,
@@ -1587,6 +1588,7 @@ tsi108_init_one(struct platform_device *pdev)
        data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if);
 
        data->phy = einfo->phy;
+       data->phy_type = einfo->phy_type;
        data->irq_num = einfo->irq_num;
        data->id = pdev->id;
        dev->open = tsi108_open;
index 77a769df228ab9c40388b6071ee3a77fe0a533b1..5a77ae6c5f36d07200c7527b61a62ba51b7daff3 100644 (file)
 #define TSI_READ_PHY(offset) \
        in_be32((data->phyregs + (offset)))
 
-/*
- * PHY Configuration Options
- *
- * NOTE: Enable set of definitions corresponding to your board type
- */
-#define PHY_MV88E      1       /* Marvel 88Exxxx PHY */
-#define PHY_BCM54XX    2       /* Broardcom BCM54xx PHY */
-#define TSI108_PHY_TYPE        PHY_MV88E
-
 /*
  * TSI108 GIGE port registers
  */
index 9b08afbd1f65e245648c4e7f3fc84531e9b7069e..ea896777bcafecc84fce5896b8256892541ea8f1 100644 (file)
@@ -269,7 +269,7 @@ done:
             This would turn on IM for devices that is not contributing
             to backlog congestion with unnecessary latency.
 
-             We monitor the the device RX-ring and have:
+             We monitor the device RX-ring and have:
 
              HW Interrupt Mitigation either ON or OFF.
 
index fa440706fb4aa28f2d7b285439aa2f10a0853f36..38f3b99716b8bb8c4357d9291d00fe181f29aeec 100644 (file)
@@ -1021,7 +1021,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                np->tx_ring[entry].length |= DescEndRing;
 
        /* Now acquire the irq spinlock.
-        * The difficult race is the the ordering between
+        * The difficult race is the ordering between
         * increasing np->cur_tx and setting DescOwned:
         * - if np->cur_tx is increased first the interrupt
         *   handler could consider the packet as transmitted
index 985a1810ca5945a282cae4a384db1245a21a2705..2470b1ee33c03b2243f9ed40aa4b0071a321d949 100644 (file)
@@ -1043,7 +1043,7 @@ static int enable_promisc(struct xircom_private *card)
 
 
 /*
-link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.
+link_status() checks the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.
 
 Must be called in locked state with interrupts disabled
 */
index f2dd7763cd0b6661b23dfae1aaa74562f0a29153..f72573594121340f217336024e9a1aff192c30db 100644 (file)
@@ -639,7 +639,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
 
        typhoon_inc_cmd_index(&ring->lastWrite, num_cmd);
 
-       /* "I feel a presence... another warrior is on the the mesa."
+       /* "I feel a presence... another warrior is on the mesa."
         */
        wmb();
        iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
index 16b9acdabbe8205af3d98f3c2b93ca25f0a133b6..d7aff8189377dacb7d0ee68d15e933fe266eee6c 100644 (file)
@@ -3787,7 +3787,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 
        ugeth_vdbg("%s: IN", __FUNCTION__);
 
-       prop = get_property(np, "device-id", NULL);
+       prop = of_get_property(np, "device-id", NULL);
        ucc_num = *prop - 1;
        if ((ucc_num < 0) || (ucc_num > 7))
                return -ENODEV;
@@ -3795,9 +3795,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        ug_info = &ugeth_info[ucc_num];
        ug_info->uf_info.ucc_num = ucc_num;
 
-       prop = get_property(np, "rx-clock", NULL);
+       prop = of_get_property(np, "rx-clock", NULL);
        ug_info->uf_info.rx_clock = *prop;
-       prop = get_property(np, "tx-clock", NULL);
+       prop = of_get_property(np, "tx-clock", NULL);
        ug_info->uf_info.tx_clock = *prop;
        err = of_address_to_resource(np, 0, &res);
        if (err)
@@ -3806,23 +3806,23 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        ug_info->uf_info.regs = res.start;
        ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
 
-       ph = get_property(np, "phy-handle", NULL);
+       ph = of_get_property(np, "phy-handle", NULL);
        phy = of_find_node_by_phandle(*ph);
 
        if (phy == NULL)
                return -ENODEV;
 
        /* set the PHY address */
-       prop = get_property(phy, "reg", NULL);
+       prop = of_get_property(phy, "reg", NULL);
        if (prop == NULL)
                return -1;
        ug_info->phy_address = *prop;
 
        /* get the phy interface type, or default to MII */
-       prop = get_property(np, "interface-type", NULL);
+       prop = of_get_property(np, "interface-type", NULL);
        if (!prop) {
                /* handle interface property present in old trees */
-               prop = get_property(phy, "interface", NULL);
+               prop = of_get_property(phy, "interface", NULL);
                if (prop != NULL)
                        phy_interface = enet_to_phy_interface[*prop];
                else
@@ -3832,10 +3832,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        }
 
        /* get speed, or derive from interface */
-       prop = get_property(np, "max-speed", NULL);
+       prop = of_get_property(np, "max-speed", NULL);
        if (!prop) {
                /* handle interface property present in old trees */
-               prop = get_property(phy, "interface", NULL);
+               prop = of_get_property(phy, "interface", NULL);
                if (prop != NULL)
                        max_speed = enet_to_speed[*prop];
        } else {
index 73b5a538e8f4ec6375ddd41a7ac0aa08da867727..27a1ef3b7b0609c21b6d46164b286970f47412de 100644 (file)
@@ -172,7 +172,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
        while ((child = of_get_next_child(np, child)) != NULL) {
                int irq = irq_of_parse_and_map(child, 0);
                if (irq != NO_IRQ) {
-                       const u32 *id = get_property(child, "reg", NULL);
+                       const u32 *id = of_get_property(child, "reg", NULL);
                        new_bus->irq[*id] = irq;
                }
        }
@@ -203,7 +203,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
                if ((res.start >= tempres.start) &&
                    (res.end <= tempres.end)) {
                        /* set this UCC to be the MII master */
-                       const u32 *id = get_property(tempnp, "device-id", NULL);
+                       const u32 *id = of_get_property(tempnp, "device-id", NULL);
                        if (id == NULL)
                                goto bus_register_fail;
 
index 23464735fa88968746a4e84af9dfd94317420dd4..9ef49ce148b26edc9690f30f816e51440a831914 100644 (file)
@@ -90,7 +90,6 @@
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 
 #undef COSA_SLOW_IO    /* for testing purposes only */
index 0184614517f9425fc1481a2f0906f323afd92b33..e273347dc6068b5dcad2653a46f02b07f17f3aef 100644 (file)
@@ -267,7 +267,7 @@ config IPW2200_DEBUG
 
 config LIBERTAS_USB
        tristate "Marvell Libertas 8388 802.11a/b/g cards"
-       depends on NET_RADIO && USB
+       depends on USB && WLAN_80211
        select FW_LOADER
        ---help---
          A driver for Marvell Libertas 8388 USB devices.
index f21bbafcb7288d3b79ba058c9276ec3a092de2d4..2d3a180dada035492f1c3d058e6ca63e3d7d0b69 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
index 38fac3bbcd823b0e568fef8729961dac95fd2c3d..7d5b8c2cc614ef3970ce34c9279cad6700758bfc 100644 (file)
@@ -149,7 +149,7 @@ static int airport_hard_reset(struct orinoco_private *priv)
        /* Vitally important.  If we don't do this it seems we get an
         * interrupt somewhere during the power cycle, since
         * hw_unavailable is already set it doesn't get ACKed, we get
-        * into an interrupt loop and the the PMU decides to turn us
+        * into an interrupt loop and the PMU decides to turn us
         * off. */
        disable_irq(dev->irq);
 
index cb08bc5db2bd52b3b14b11fd6e3408d27c72b963..cdea7f71b9eba7e6d01fc7637da1cd1854bd5182 100644 (file)
@@ -1,7 +1,6 @@
 /* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
 
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/ethtool.h>
 #include <net/ieee80211_crypt.h>
 
index 841b3c136ad951d47ed6ca0aeb53b8d605550061..283be4a70524b650920b02e86506d5ffab1940d7 100644 (file)
@@ -3054,7 +3054,7 @@ static const iw_handler prism54_handler[] = {
        (iw_handler) prism54_set_wap,   /* SIOCSIWAP */
        (iw_handler) prism54_get_wap,   /* SIOCGIWAP */
        (iw_handler) NULL,      /* -- hole -- */
-       (iw_handler) NULL,      /* SIOCGIWAPLIST depreciated */
+       (iw_handler) NULL,      /* SIOCGIWAPLIST deprecated */
        (iw_handler) prism54_set_scan,  /* SIOCSIWSCAN */
        (iw_handler) prism54_get_scan,  /* SIOCGIWSCAN */
        (iw_handler) prism54_set_essid, /* SIOCSIWESSID */
index a037b11dac9da840645624cb5e28d165ecc76bcb..084795355b74a312cac2bdf29c10b6a01088e528 100644 (file)
@@ -115,7 +115,7 @@ isl_upload_firmware(islpci_private *priv)
                            ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
                        u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
 
-                       /* set the cards base address for writting the data */
+                       /* set the card's base address for writing the data */
                        isl38xx_w32_flush(device_base, reg,
                                          ISL38XX_DIR_MEM_BASE_REG);
                        wmb();  /* be paranoid */
index 67b867f837ca49e0aaca4b96aadeeacdb996b8ba..5740d4d4267c657b762d90db692c9a2ff45f19ab 100644 (file)
@@ -176,7 +176,7 @@ psa_write(struct net_device *       dev,
   volatile u_char __iomem *verify = lp->mem + PSA_ADDR +
     (psaoff(0, psa_comp_number) << 1);
 
-  /* Authorize writting to PSA */
+  /* Authorize writing to PSA */
   hacr_write(base, HACR_PWR_STAT | HACR_ROM_WEN);
 
   while(n-- > 0)
@@ -1676,7 +1676,7 @@ wv_set_frequency(u_long           base,   /* i/o port of the card */
       fee_write(base, 0x60,
                dac, 2);
 
-      /* We now should verify here that the EEprom writting was ok */
+      /* We now should verify here that the EEprom writing was ok */
 
       /* ReRead the first area */
       fee_read(base, 0x00,
index 4d1c4905c7494d04b33a4239234dcc19395a166e..4b9de0093a7b2314bf6439512b21f47fe8d6668a 100644 (file)
  * the Wavelan itself (NCR -> AT&T -> Lucent).
  *
  * All started with Anders Klemets <klemets@paul.rutgers.edu>,
- * writting a Wavelan ISA driver for the MACH microkernel. Girish
+ * writing a Wavelan ISA driver for the MACH microkernel. Girish
  * Welling <welling@paul.rutgers.edu> had also worked on it.
  * Keith Moore modify this for the Pcmcia hardware.
  * 
index 3f4a7cf9efeaaa785e802c50347b055bca61b4b1..f2a90a7fa2d6ff9fb826224342ecec58ad3b6ced 100644 (file)
@@ -109,7 +109,6 @@ static int gx_fix;
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
 KERN_INFO DRV_NAME ".c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n"
-KERN_INFO "  http://www.scyld.com/network/yellowfin.html\n"
 KERN_INFO "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
index 21c4c299b3d6c823ae92b6f8af86741a86207484..5b86ee5c1eeb7437d4886aef39735fe6e7aab5b2 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 
 #include <asm/byteorder.h>
 #include <asm/pdc.h>
index 316c06f4423c381ba05792840750b683d4ba4add..8b7d84eca05da34dab6918e31697c4ef1fbf6a76 100644 (file)
@@ -201,7 +201,7 @@ static int parport_config(struct pcmcia_device *link)
 
     p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
                              link->irq.AssignedIRQ, PARPORT_DMA_NONE,
-                             NULL);
+                             &link->dev);
     if (p == NULL) {
        printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
               "0x%3x, irq %u failed\n", link->io.BasePort1,
index e5b0a544de40f4565ff9558eeb961ef4097351a0..77726fc4976641c13ab9a05cc5e3861699d4afb2 100644 (file)
@@ -356,6 +356,7 @@ static int __init parport_mfc3_init(void)
                                if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, IRQF_SHARED, p->name, &pp_mfc3_ops))
                                        goto out_irq;
                }
+               p->dev = &z->dev;
 
                this_port[pias++] = p;
                printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
index 3de2623afa13b39815690686c6141a4cfa40a74b..02c0d52c9f76cb147524a8153381bca86dbe499d 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/pnp.h>
+#include <linux/platform_device.h>
 #include <linux/sysctl.h>
 
 #include <asm/io.h>
@@ -620,6 +621,7 @@ static size_t parport_pc_fifo_write_block_dma (struct parport *port,
        unsigned long dmaflag;
        size_t left = length;
        const struct parport_pc_private *priv = port->physport->private_data;
+       struct device *dev = port->physport->dev;
        dma_addr_t dma_addr, dma_handle;
        size_t maxlen = 0x10000; /* max 64k per DMA transfer */
        unsigned long start = (unsigned long) buf;
@@ -631,8 +633,8 @@ dump_parport_state ("enter fifo_write_block_dma", port);
                if ((start ^ end) & ~0xffffUL)
                        maxlen = 0x10000 - (start & 0xffff);
 
-               dma_addr = dma_handle = pci_map_single(priv->dev, (void *)buf, length,
-                                                      PCI_DMA_TODEVICE);
+               dma_addr = dma_handle = dma_map_single(dev, (void *)buf, length,
+                                                      DMA_TO_DEVICE);
         } else {
                /* above 16 MB we use a bounce buffer as ISA-DMA is not possible */
                maxlen   = PAGE_SIZE;          /* sizeof(priv->dma_buf) */
@@ -728,9 +730,9 @@ dump_parport_state ("enter fifo_write_block_dma", port);
 
        /* Turn off DMA mode */
        frob_econtrol (port, 1<<3, 0);
-       
+
        if (dma_handle)
-               pci_unmap_single(priv->dev, dma_handle, length, PCI_DMA_TODEVICE);
+               dma_unmap_single(dev, dma_handle, length, DMA_TO_DEVICE);
 
 dump_parport_state ("leave fifo_write_block_dma", port);
        return length - left;
@@ -2146,7 +2148,7 @@ static DEFINE_SPINLOCK(ports_lock);
 struct parport *parport_pc_probe_port (unsigned long int base,
                                       unsigned long int base_hi,
                                       int irq, int dma,
-                                      struct pci_dev *dev)
+                                      struct device *dev)
 {
        struct parport_pc_private *priv;
        struct parport_operations *ops;
@@ -2155,6 +2157,17 @@ struct parport *parport_pc_probe_port (unsigned long int base,
        struct resource *base_res;
        struct resource *ECR_res = NULL;
        struct resource *EPP_res = NULL;
+       struct platform_device *pdev = NULL;
+
+       if (!dev) {
+               /* We need a physical device to attach to, but none was
+                * provided. Create our own. */
+               pdev = platform_device_register_simple("parport_pc",
+                                                      base, NULL, 0);
+               if (IS_ERR(pdev))
+                       return NULL;
+               dev = &pdev->dev;
+       }
 
        ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL);
        if (!ops)
@@ -2180,9 +2193,10 @@ struct parport *parport_pc_probe_port (unsigned long int base,
        priv->fifo_depth = 0;
        priv->dma_buf = NULL;
        priv->dma_handle = 0;
-       priv->dev = dev;
        INIT_LIST_HEAD(&priv->list);
        priv->port = p;
+
+       p->dev = dev;
        p->base_hi = base_hi;
        p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
        p->private_data = priv;
@@ -2305,9 +2319,10 @@ struct parport *parport_pc_probe_port (unsigned long int base,
                                p->dma = PARPORT_DMA_NONE;
                        } else {
                                priv->dma_buf =
-                                 pci_alloc_consistent(priv->dev,
+                                 dma_alloc_coherent(dev,
                                                       PAGE_SIZE,
-                                                      &priv->dma_handle);
+                                                      &priv->dma_handle,
+                                                      GFP_KERNEL);
                                if (! priv->dma_buf) {
                                        printk (KERN_WARNING "%s: "
                                                "cannot get buffer for DMA, "
@@ -2356,6 +2371,8 @@ out3:
 out2:
        kfree (ops);
 out1:
+       if (pdev)
+               platform_device_unregister(pdev);
        return NULL;
 }
 
@@ -2383,7 +2400,7 @@ void parport_pc_unregister_port (struct parport *p)
                release_region(p->base_hi, 3);
 #if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA)
        if (priv->dma_buf)
-               pci_free_consistent(priv->dev, PAGE_SIZE,
+               dma_free_coherent(p->physport->dev, PAGE_SIZE,
                                    priv->dma_buf,
                                    priv->dma_handle);
 #endif
@@ -2489,7 +2506,7 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
         */
        release_resource(base_res);
        if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi,
-                                  irq, PARPORT_DMA_NONE, NULL)) {
+                                  irq, PARPORT_DMA_NONE, &pdev->dev)) {
                printk (KERN_INFO
                        "parport_pc: ITE 8872 parallel port: io=0x%X",
                        ite8872_lpt);
@@ -2672,7 +2689,7 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
        }
 
        /* finally, do the probe with values obtained */
-       if (parport_pc_probe_port (port1, port2, irq, dma, NULL)) {
+       if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev)) {
                printk (KERN_INFO
                        "parport_pc: VIA parallel port: io=0x%X", port1);
                if (irq != PARPORT_IRQ_NONE)
@@ -2970,7 +2987,7 @@ static int parport_pc_pci_probe (struct pci_dev *dev,
                        parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi);
                data->ports[count] =
                        parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-                                              PARPORT_DMA_NONE, dev);
+                                              PARPORT_DMA_NONE, &dev->dev);
                if (data->ports[count])
                        count++;
        }
@@ -3077,8 +3094,8 @@ static int parport_pc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id
        } else
                dma = PARPORT_DMA_NONE;
 
-       printk(KERN_INFO "parport: PnPBIOS parport detected.\n");
-       if (!(pdata = parport_pc_probe_port (io_lo, io_hi, irq, dma, NULL)))
+       dev_info(&dev->dev, "reported by %s\n", dev->protocol->name);
+       if (!(pdata = parport_pc_probe_port (io_lo, io_hi, irq, dma, &dev->dev)))
                return -ENODEV;
 
        pnp_set_drvdata(dev,pdata);
@@ -3103,6 +3120,21 @@ static struct pnp_driver parport_pc_pnp_driver = {
 };
 
 
+static int __devinit parport_pc_platform_probe(struct platform_device *pdev)
+{
+       /* Always succeed, the actual probing is done in
+        * parport_pc_probe_port(). */
+       return 0;
+}
+
+static struct platform_driver parport_pc_platform_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "parport_pc",
+       },
+       .probe          = parport_pc_platform_probe,
+};
+
 /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
 static int __devinit __attribute__((unused))
 parport_pc_find_isa_ports (int autoirq, int autodma)
@@ -3378,9 +3410,15 @@ __setup("parport_init_mode=",parport_init_mode_setup);
 
 static int __init parport_pc_init(void)
 {
+       int err;
+
        if (parse_parport_params())
                return -EINVAL;
 
+       err = platform_driver_register(&parport_pc_platform_driver);
+       if (err)
+               return err;
+
        if (io[0]) {
                int i;
                /* Only probe the ports we were given. */
@@ -3405,6 +3443,7 @@ static void __exit parport_pc_exit(void)
                pci_unregister_driver (&parport_pc_pci_driver);
        if (pnp_registered_parport)
                pnp_unregister_driver (&parport_pc_pnp_driver);
+       platform_driver_unregister(&parport_pc_platform_driver);
 
        spin_lock(&ports_lock);
        while (!list_empty(&ports_list)) {
@@ -3413,6 +3452,9 @@ static void __exit parport_pc_exit(void)
                priv = list_entry(ports_list.next,
                                  struct parport_pc_private, list);
                port = priv->port;
+               if (port->dev && port->dev->bus == &platform_bus_type)
+                       platform_device_unregister(
+                               to_platform_device(port->dev));
                spin_unlock(&ports_lock);
                parport_pc_unregister_port(port);
                spin_lock(&ports_lock);
index 78c0a269a2ba3e24200b0c13e72a70c99b978141..90ea3b8b99b02571e1621853a05aa8868d4aaa03 100644 (file)
@@ -305,7 +305,7 @@ static int __devinit parport_register (struct pci_dev *dev,
                dev_dbg(&dev->dev, "PCI parallel port detected: I/O at "
                        "%#lx(%#lx)\n", io_lo, io_hi);
                port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-                                             PARPORT_DMA_NONE, dev);
+                                             PARPORT_DMA_NONE, &dev->dev);
                if (port) {
                        priv->port[priv->num_par++] = port;
                        success = 1;
@@ -392,6 +392,7 @@ static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
 static int parport_serial_pci_resume(struct pci_dev *dev)
 {
        struct parport_serial_private *priv = pci_get_drvdata(dev);
+       int err;
 
        pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
@@ -399,7 +400,12 @@ static int parport_serial_pci_resume(struct pci_dev *dev)
        /*
         * The device may have been disabled.  Re-enable it.
         */
-       pci_enable_device(dev);
+       err = pci_enable_device(dev);
+       if (err) {
+               printk(KERN_ERR "parport_serial: %s: error enabling "
+                       "device for resume (%d)\n", pci_name(dev), err);
+               return err;
+       }
 
        if (priv->serial)
                pciserial_resume_ports(priv->serial);
index 400bb90084cf479b39f1fc1f495111e76c7e0273..d27019c2f860ab3a275575cc149687621b04663e 100644 (file)
@@ -322,6 +322,7 @@ static int __devinit init_one_port(struct sbus_dev *sdev)
                goto out_free_ops;
 
        p->size = size;
+       p->dev = &sdev->ofdev.dev;
 
        if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
                               IRQF_SHARED, p->name, p)) != 0) {
index fd9129e424f906e6e5a65de04cafb5b843385ba9..cd66442acfee71126414fe0a1578454406aa5297 100644 (file)
@@ -365,6 +365,11 @@ void parport_announce_port (struct parport *port)
        parport_daisy_init(port);
 #endif
 
+       if (!port->dev)
+               printk(KERN_WARNING "%s: fix this legacy "
+                               "no-device port driver!\n",
+                               port->name);
+
        parport_proc_register(port);
        mutex_lock(&registration_lock);
        spin_lock_irq(&parportlist_lock);
index 40c79b03c7ef983b14e44532ddd35110dfa22d3a..fa5c0197d571c81325ace3d08d2e6c7246fa74a9 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include "acpiphp.h"
 
 #define MY_NAME        "acpiphp"
index fca978fb158e22e5313ebf8564faf09ee6bae160..9ef4e989afc43b0fc70153258ebb91821aaff82a 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
 #include "../pci.h"
index 59392946c2bd350b0605877eaf4ae42af0ea81b3..0316eeaaeb29cb288f45066dbf6e746610db66b1 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>
 #include "../pci.h"
 #include "../../../arch/i386/pci/pci.h"        /* for struct irq_routing_table */
 #include "ibmphp.h"
index f55ac3885cb3fa98bf6ae632514edb7f2749c2e2..46abaa8c41f1f90a9bc5b7265ae0cd3619521b80 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
 
index 63f3bd1eecc40300c4dfb46af9633a08cf6a8178..bd433ef6bfc66ffd4381f6e9714debc98d370751 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/sysfs.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
index 847936fe327e602a05ab7009866e274dede21471..458c08ef2654bcc5089442044dc99aaa4aedc7d6 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/eeh.h>       /* for eeh_add_device() */
 #include <asm/rtas.h>          /* rtas_call */
@@ -170,10 +169,10 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,
 {
        const int *indexes, *names, *types, *domains;
 
-       indexes = get_property(dn, "ibm,drc-indexes", NULL);
-       names = get_property(dn, "ibm,drc-names", NULL);
-       types = get_property(dn, "ibm,drc-types", NULL);
-       domains = get_property(dn, "ibm,drc-power-domains", NULL);
+       indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+       names = of_get_property(dn, "ibm,drc-names", NULL);
+       types = of_get_property(dn, "ibm,drc-types", NULL);
+       domains = of_get_property(dn, "ibm,drc-power-domains", NULL);
 
        if (!indexes || !names || !types || !domains) {
                /* Slot does not have dynamically-removable children */
@@ -206,7 +205,7 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
        char *name_tmp, *type_tmp;
        int i, rc;
 
-       my_index = get_property(dn, "ibm,my-drc-index", NULL);
+       my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
        if (!my_index) {
                /* Node isn't DLPAR/hotplug capable */
                return -EINVAL;
index 2c94d44279a34cd66a72651bf279278620e29028..d2fc35598cddd2b94189a7da53be2cf219ccd67b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/workqueue.h>
 #include "../pci.h"
index 9e1321d0d5e683d281c9e10fc42c826c38e8f4cf..e6740d1a0824d36540b415018814ab6dc3b82344 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/msi.h>
index 3bb7739d26a50af35f6c7344a1cda7daa1fbefdc..8e58ea3d95c09fab4c72656a616a33cd5c73f84a 100644 (file)
@@ -119,7 +119,7 @@ static inline int pci_create_newid_file(struct pci_driver *drv)
  * system is in its list of supported devices.  Returns the matching
  * pci_device_id structure or %NULL if there is no match.
  *
- * Depreciated, don't use this as it will not catch any dynamic ids
+ * Deprecated, don't use this as it will not catch any dynamic ids
  * that a driver might want to check for.
  */
 const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
index ed87aa59f0b1320f6289eb3d6d3ba2e3ca9f1453..0425a7b7350d987760bfff76cbd0e0af6d311800 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
index fda06941e73062cdf9a6629dc9452153cf69f6b3..383107ba4bd3f8859c8fde3c8c722e734c9fd229 100644 (file)
@@ -175,6 +175,7 @@ static int __init mst_pcmcia_init(void)
        if (!mst_pcmcia_device)
                return -ENOMEM;
 
+       mst_pcmcia_device->dev.uevent_suppress = 0;
        mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
 
        ret = platform_device_add(mst_pcmcia_device);
index b7b9e149c5b9c73278b095ca99a368af8e8eac51..a2daa3f531b28855144eac20da587e017c4cca37 100644 (file)
@@ -261,6 +261,7 @@ static int __init sharpsl_pcmcia_init(void)
        if (!sharpsl_pcmcia_device)
                return -ENOMEM;
 
+       sharpsl_pcmcia_device->dev.uevent_suppress = 0;
        sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
        sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
 
index aec83ec5ea23f2471c55fbbe3dafd073b296c42e..3e20b1cc7778930f2477dc626fc281606b7e320b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/dma-mapping.h>
 
 #include "base.h"
 
@@ -22,6 +23,14 @@ static LIST_HEAD(pnp_protocols);
 LIST_HEAD(pnp_global);
 DEFINE_SPINLOCK(pnp_lock);
 
+/*
+ * ACPI or PNPBIOS should tell us about all platform devices, so we can
+ * skip some blind probes.  ISAPNP typically enumerates only plug-in ISA
+ * devices, not built-in things like COM ports.
+ */
+int pnp_platform_devices;
+EXPORT_SYMBOL(pnp_platform_devices);
+
 void *pnp_alloc(long size)
 {
        void *result;
@@ -114,6 +123,8 @@ int __pnp_add_device(struct pnp_dev *dev)
        int ret;
        pnp_fixup_device(dev);
        dev->dev.bus = &pnp_bus_type;
+       dev->dev.dma_mask = &dev->dma_mask;
+       dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK;
        dev->dev.release = &pnp_release_device;
        dev->status = PNP_READY;
        spin_lock(&pnp_lock);
index 62eda5d5902413136a2006e8ba2242c1c76ad641..a00548799e98f8655fbb9efcdd53c10e0837f06c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.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, or (at your option) any
@@ -18,7 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 #include <acpi/acpi_bus.h>
@@ -82,7 +82,7 @@ static void __init pnpidacpi_to_pnpid(char *id, char *str)
 static int pnpacpi_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
 {
        acpi_status status;
-       status = pnpacpi_parse_allocated_resource((acpi_handle)dev->data, 
+       status = pnpacpi_parse_allocated_resource((acpi_handle)dev->data,
                &dev->res);
        return ACPI_FAILURE(status) ? -ENODEV : 0;
 }
@@ -112,9 +112,9 @@ static int pnpacpi_set_resources(struct pnp_dev * dev, struct pnp_resource_table
 static int pnpacpi_disable_resources(struct pnp_dev *dev)
 {
        acpi_status status;
-       
+
        /* acpi_unregister_gsi(pnp_irq(dev, 0)); */
-       status = acpi_evaluate_object((acpi_handle)dev->data, 
+       status = acpi_evaluate_object((acpi_handle)dev->data,
                "_DIS", NULL, NULL);
        return ACPI_FAILURE(status) ? -ENODEV : 0;
 }
@@ -167,7 +167,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
                strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));
 
        dev->number = num;
-       
+
        /* set the initial values for the PnP device */
        dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
        if (!dev_id)
@@ -185,14 +185,14 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
        }
 
        if(dev->capabilities & PNP_CONFIGURABLE) {
-               status = pnpacpi_parse_resource_option_data(device->handle, 
+               status = pnpacpi_parse_resource_option_data(device->handle,
                        dev);
                if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
                        pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", dev_id->id);
                        goto err1;
                }
        }
-       
+
        /* parse compatible ids */
        if (device->flags.compatible_ids) {
                struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
@@ -236,6 +236,42 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
        return AE_OK;
 }
 
+static int __init acpi_pnp_match(struct device *dev, void *_pnp)
+{
+       struct acpi_device      *acpi = to_acpi_device(dev);
+       struct pnp_dev          *pnp = _pnp;
+
+       /* true means it matched */
+       return acpi->flags.hardware_id
+               && !acpi_get_physical_device(acpi->handle)
+               && compare_pnp_id(pnp->id, acpi->pnp.hardware_id);
+}
+
+static int __init acpi_pnp_find_device(struct device *dev, acpi_handle *handle)
+{
+       struct device           *adev;
+       struct acpi_device      *acpi;
+
+       adev = bus_find_device(&acpi_bus_type, NULL,
+                       to_pnp_dev(dev),
+                       acpi_pnp_match);
+       if (!adev)
+               return -ENODEV;
+
+       acpi = to_acpi_device(adev);
+       *handle = acpi->handle;
+       put_device(adev);
+       return 0;
+}
+
+/* complete initialization of a PNPACPI device includes having
+ * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling.
+ */
+static struct acpi_bus_type __initdata acpi_pnp_bus = {
+       .bus = &pnp_bus_type,
+       .find_device = acpi_pnp_find_device,
+};
+
 int pnpacpi_disabled __initdata;
 static int __init pnpacpi_init(void)
 {
@@ -245,8 +281,11 @@ static int __init pnpacpi_init(void)
        }
        pnp_info("PnP ACPI init");
        pnp_register_protocol(&pnpacpi_protocol);
+       register_acpi_bus_type(&acpi_pnp_bus);
        acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
        pnp_info("PnP ACPI: found %d devices", num);
+       unregister_acpi_bus_type(&acpi_pnp_bus);
+       pnp_platform_devices = 1;
        return 0;
 }
 subsys_initcall(pnpacpi_init);
index 95738dbd5d4555cec6428595b06ce72cd32aa8be..3a201b77b963af5134d0578d2624451f8d8fa8c5 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/delay.h>
 #include <linux/acpi.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 
 #include <asm/page.h>
 #include <asm/desc.h>
@@ -159,9 +160,7 @@ static int pnp_dock_thread(void * unused)
 {
        static struct pnp_docking_station_info now;
        int docked = -1, d = 0;
-       daemonize("kpnpbiosd");
-       allow_signal(SIGKILL);
-       while(!unloading && !signal_pending(current))
+       while (!unloading)
        {
                int status;
                
@@ -170,11 +169,8 @@ static int pnp_dock_thread(void * unused)
                 */
                msleep_interruptible(2000);
 
-               if(signal_pending(current)) {
-                       if (try_to_freeze())
-                               continue;
-                       break;
-               }
+               if (try_to_freeze())
+                       continue;
 
                status = pnp_bios_dock_station_info(&now);
 
@@ -574,6 +570,7 @@ static int __init pnpbios_init(void)
        /* scan for pnpbios devices */
        build_devlist();
 
+       pnp_platform_devices = 1;
        return 0;
 }
 
@@ -581,6 +578,7 @@ subsys_initcall(pnpbios_init);
 
 static int __init pnpbios_thread_init(void)
 {
+       struct task_struct *task;
 #if defined(CONFIG_PPC_MERGE)
        if (check_legacy_ioport(PNPBIOS_BASE))
                return 0;
@@ -589,7 +587,8 @@ static int __init pnpbios_thread_init(void)
                return 0;
 #ifdef CONFIG_HOTPLUG
        init_completion(&unload_sem);
-       if (kernel_thread(pnp_dock_thread, NULL, CLONE_KERNEL) > 0)
+       task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
+       if (!IS_ERR(task))
                unloading = 0;
 #endif
        return 0;
index e97ecefe85841c966be495f27588ea128684bc25..277df50c89aee76e5e9ad20298ae6bd08dfd5780 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
+#include <linux/io.h>
 #include "base.h"
 
 
@@ -106,6 +107,34 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
        return;
 }
 
+static void quirk_smc_enable(struct pnp_dev *dev)
+{
+       unsigned int firbase;
+
+       if (!dev->active || !pnp_port_valid(dev, 1))
+               return;
+
+       /*
+        * On the HP/Compaq nw8240 (and probably other similar machines),
+        * there is an SMCF010 device with two I/O port regions:
+        *
+        *      0x3e8-0x3ef SIR
+        *      0x100-0x10f FIR
+        *
+        * _STA reports the device is enabled, but in fact, the BIOS
+        * neglects to enable the FIR range.  Fortunately, it does fully
+        * enable the device if we call _SRS.
+        */
+       firbase = pnp_port_start(dev, 1);
+       if (inb(firbase + 0x7 /* IRCC_MASTER */) == 0xff) {
+               pnp_err("%s (%s) enabled but not responding, disabling and "
+                       "re-enabling", dev->dev.bus_id, pnp_dev_name(dev));
+               pnp_disable_dev(dev);
+               pnp_activate_dev(dev);
+       }
+}
+
+
 /*
  *  PnP Quirks
  *  Cards or devices that need some tweaking due to incomplete resource info
@@ -126,6 +155,7 @@ static struct pnp_fixup pnp_fixups[] = {
        { "CTL0043", quirk_sb16audio_resources },
        { "CTL0044", quirk_sb16audio_resources },
        { "CTL0045", quirk_sb16audio_resources },
+       { "SMCf010", quirk_smc_enable },
        { "" }
 };
 
index 7d7cab1d91b460a7311db72c8869e77d8eaf9de1..ec2d36a1bc67ae98c22b8cd2589572b05633f646 100644 (file)
@@ -886,12 +886,12 @@ static int ps3_vuart_probe(struct device *_dev)
 
        if (++vuart_bus_priv.use_count == 1) {
 
-               result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
+               result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
                        (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
 
                if (result) {
                        dev_dbg(&dev->core,
-                               "%s:%d: ps3_alloc_vuart_irq failed (%d)\n",
+                               "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
                                __func__, __LINE__, result);
                        result = -EPERM;
                        goto fail_alloc_irq;
@@ -937,7 +937,7 @@ static int ps3_vuart_probe(struct device *_dev)
 fail_probe:
        ps3_vuart_set_interrupt_mask(dev, 0);
 fail_request_irq:
-       ps3_free_vuart_irq(vuart_bus_priv.virq);
+       ps3_vuart_irq_destroy(vuart_bus_priv.virq);
        vuart_bus_priv.virq = NO_IRQ;
 fail_alloc_irq:
        --vuart_bus_priv.use_count;
@@ -975,7 +975,7 @@ static int ps3_vuart_remove(struct device *_dev)
        if (--vuart_bus_priv.use_count == 0) {
                BUG();
                free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
-               ps3_free_vuart_irq(vuart_bus_priv.virq);
+               ps3_vuart_irq_destroy(vuart_bus_priv.virq);
                vuart_bus_priv.virq = NO_IRQ;
        }
 
index ef1eae98ba449f8e9c558042b464f0bd41fd5744..76422eded36ec762fb422d5f44de42f4ba8a8067 100644 (file)
@@ -21,21 +21,31 @@ config RTC_CLASS
          will be called rtc-class.
 
 config RTC_HCTOSYS
-       bool "Set system time from RTC on startup"
+       bool "Set system time from RTC on startup and resume"
        depends on RTC_CLASS = y
        default y
        help
-         If you say yes here, the system time will be set using
-         the value read from the specified RTC device. This is useful
-         in order to avoid unnecessary fsck runs.
+         If you say yes here, the system time (wall clock) will be set using
+         the value read from a specified RTC device. This is useful to avoid
+         unnecessary fsck runs at boot time, and to network better.
 
 config RTC_HCTOSYS_DEVICE
-       string "The RTC to read the time from"
+       string "RTC used to set the system time"
        depends on RTC_HCTOSYS = y
        default "rtc0"
        help
-         The RTC device that will be used as the source for
-         the system time, usually rtc0.
+         The RTC device that will be used to (re)initialize the system
+         clock, usually rtc0.  Initialization is done when the system
+         starts up, and when it resumes from a low power state.
+
+         This clock should be battery-backed, so that it reads the correct
+         time when the system boots from a power-off state.  Otherwise, your
+         system will need an external clock source (like an NTP server).
+
+         If the clock you specify here is not battery backed, it may still
+         be useful to reinitialize system time when resuming from system
+         sleep states.  Do not specify an RTC here unless it stays powered
+         during all this system's supported sleep states.
 
 config RTC_DEBUG
        bool "RTC debug support"
@@ -48,7 +58,7 @@ comment "RTC interfaces"
        depends on RTC_CLASS
 
 config RTC_INTF_SYSFS
-       tristate "sysfs"
+       boolean "sysfs"
        depends on RTC_CLASS && SYSFS
        default RTC_CLASS
        help
@@ -59,7 +69,7 @@ config RTC_INTF_SYSFS
          will be called rtc-sysfs.
 
 config RTC_INTF_PROC
-       tristate "proc"
+       boolean "proc"
        depends on RTC_CLASS && PROC_FS
        default RTC_CLASS
        help
@@ -71,7 +81,7 @@ config RTC_INTF_PROC
          will be called rtc-proc.
 
 config RTC_INTF_DEV
-       tristate "dev"
+       boolean "dev"
        depends on RTC_CLASS
        default RTC_CLASS
        help
@@ -88,48 +98,30 @@ config RTC_INTF_DEV_UIE_EMUL
        bool "RTC UIE emulation on dev interface"
        depends on RTC_INTF_DEV
        help
-         Provides an emulation for RTC_UIE if the underlaying rtc chip
+         Provides an emulation for RTC_UIE if the underlying rtc chip
          driver does not expose RTC_UIE ioctls.  Those requests generate
          once-per-second update interrupts, used for synchronization.
 
-comment "RTC drivers"
+config RTC_DRV_TEST
+       tristate "Test driver/device"
        depends on RTC_CLASS
-
-# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
-# requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a
-# global rtc_lock ... it's not yet just another platform_device.
-
-config RTC_DRV_CMOS
-       tristate "PC-style 'CMOS' real time clock"
-       depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
-               || M32R || ATARI || POWERPC)
-       help
-         Say "yes" here to get direct support for the real time clock
-         found in every PC or ACPI-based system, and some other boards.
-         Specifically the original MC146818, compatibles like those in
-         PC south bridges, the DS12887 or M48T86, some multifunction
-         or LPC bus chips, and so on.
-
-         Your system will need to define the platform device used by
-         this driver, otherwise it won't be accessible.  This means
-         you can safely enable this driver if you don't know whether
-         or not your board has this kind of hardware.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-cmos.
-
-config RTC_DRV_X1205
-       tristate "Xicor/Intersil X1205"
-       depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for the
-         Xicor/Intersil X1205 RTC chip.
+         RTC test driver. It's a software RTC which can be
+         used to test the RTC subsystem APIs. It gets
+         the time from the system clock.
+         You want this driver only if you are doing development
+         on the RTC subsystem. Please read the source code
+         for further details.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-x1205.
+         will be called rtc-test.
+
+comment "I2C RTC drivers"
+       depends on RTC_CLASS
 
 config RTC_DRV_DS1307
-       tristate "Dallas/Maxim DS1307 and similar I2C RTC chips"
+       tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
        depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for various compatible RTC
@@ -146,53 +138,55 @@ config RTC_DRV_DS1307
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1307.
 
-config RTC_DRV_DS1553
-       tristate "Dallas DS1553"
-       depends on RTC_CLASS
+config RTC_DRV_DS1672
+       tristate "Dallas/Maxim DS1672"
+       depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for the
-         Dallas DS1553 timekeeping chip.
+         Dallas/Maxim DS1672 timekeeping chip.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-ds1553.
+         will be called rtc-ds1672.
 
-config RTC_DRV_ISL1208
-       tristate "Intersil 1208"
+config RTC_DRV_MAX6900
+       tristate "Maxim 6900"
        depends on RTC_CLASS && I2C
        help
-         If you say yes here you get support for the
-         Intersil 1208 RTC chip.
+         If you say yes here you will get support for the
+         Maxim MAX6900 I2C RTC chip.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-isl1208.
+         will be called rtc-max6900.
 
-config RTC_DRV_DS1672
-       tristate "Dallas/Maxim DS1672"
+config RTC_DRV_RS5C372
+       tristate "Ricoh RS5C372A/B"
        depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for the
-         Dallas/Maxim DS1672 timekeeping chip.
+         Ricoh RS5C372A and RS5C372B RTC chips.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-ds1672.
+         will be called rtc-rs5c372.
 
-config RTC_DRV_DS1742
-       tristate "Dallas DS1742/1743"
-       depends on RTC_CLASS
+config RTC_DRV_ISL1208
+       tristate "Intersil 1208"
+       depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for the
-         Dallas DS1742/1743 timekeeping chip.
+         Intersil 1208 RTC chip.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-ds1742.
+         will be called rtc-isl1208.
 
-config RTC_DRV_OMAP
-       tristate "TI OMAP1"
-       depends on RTC_CLASS && ( \
-               ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 )
+config RTC_DRV_X1205
+       tristate "Xicor/Intersil X1205"
+       depends on RTC_CLASS && I2C
        help
-         Say "yes" here to support the real time clock on TI OMAP1 chips.
-         This driver can also be built as a module called rtc-omap.
+         If you say yes here you get support for the
+         Xicor/Intersil X1205 RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-x1205.
 
 config RTC_DRV_PCF8563
        tristate "Philips PCF8563/Epson RTC8564"
@@ -207,16 +201,20 @@ config RTC_DRV_PCF8563
 
 config RTC_DRV_PCF8583
        tristate "Philips PCF8583"
-       depends on RTC_CLASS && I2C && ARCH_RPC
+       depends on RTC_CLASS && I2C
        help
          If you say yes here you get support for the Philips PCF8583
-         RTC chip found on Acorn RiscPCs.  This driver supports the
+         RTC chip found on Acorn RiscPCs. This driver supports the
          platform specific method of retrieving the current year from
-         the RTC's SRAM.
+         the RTC's SRAM. It will work on other platforms with the same
+         chip, but the year will probably have to be tweaked.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-pcf8583.
 
+comment "SPI RTC drivers"
+       depends on RTC_CLASS
+
 config RTC_DRV_RS5C348
        tristate "Ricoh RS5C348A/B"
        depends on RTC_CLASS && SPI
@@ -227,15 +225,92 @@ config RTC_DRV_RS5C348
          This driver can also be built as a module. If so, the module
          will be called rtc-rs5c348.
 
-config RTC_DRV_RS5C372
-       tristate "Ricoh RS5C372A/B"
-       depends on RTC_CLASS && I2C
+config RTC_DRV_MAX6902
+       tristate "Maxim 6902"
+       depends on RTC_CLASS && SPI
+       help
+         If you say yes here you will get support for the
+         Maxim MAX6902 SPI RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-max6902.
+
+comment "Platform RTC drivers"
+       depends on RTC_CLASS
+
+# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
+# requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a
+# global rtc_lock ... it's not yet just another platform_device.
+
+config RTC_DRV_CMOS
+       tristate "PC-style 'CMOS'"
+       depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
+               || M32R || ATARI || POWERPC)
+       help
+         Say "yes" here to get direct support for the real time clock
+         found in every PC or ACPI-based system, and some other boards.
+         Specifically the original MC146818, compatibles like those in
+         PC south bridges, the DS12887 or M48T86, some multifunction
+         or LPC bus chips, and so on.
+
+         Your system will need to define the platform device used by
+         this driver, otherwise it won't be accessible.  This means
+         you can safely enable this driver if you don't know whether
+         or not your board has this kind of hardware.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-cmos.
+
+config RTC_DRV_DS1553
+       tristate "Dallas DS1553"
+       depends on RTC_CLASS
        help
          If you say yes here you get support for the
-         Ricoh RS5C372A and RS5C372B RTC chips.
+         Dallas DS1553 timekeeping chip.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-rs5c372.
+         will be called rtc-ds1553.
+
+config RTC_DRV_DS1742
+       tristate "Dallas DS1742/1743"
+       depends on RTC_CLASS
+       help
+         If you say yes here you get support for the
+         Dallas DS1742/1743 timekeeping chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-ds1742.
+
+config RTC_DRV_M48T86
+       tristate "ST M48T86/Dallas DS12887"
+       depends on RTC_CLASS
+       help
+         If you say Y here you will get support for the
+         ST M48T86 and Dallas DS12887 RTC chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-m48t86.
+
+config RTC_DRV_V3020
+       tristate "EM Microelectronic V3020"
+       depends on RTC_CLASS
+       help
+         If you say yes here you will get support for the
+         EM Microelectronic v3020 RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-v3020.
+
+comment "on-CPU RTC drivers"
+       depends on RTC_CLASS
+
+config RTC_DRV_OMAP
+       tristate "TI OMAP1"
+       depends on RTC_CLASS && ( \
+               ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 )
+       help
+         Say "yes" here to support the real time clock on TI OMAP1 chips.
+         This driver can also be built as a module called rtc-omap.
 
 config RTC_DRV_S3C
        tristate "Samsung S3C series SoC RTC"
@@ -253,16 +328,6 @@ config RTC_DRV_S3C
          This driver can also be build as a module. If so, the module
          will be called rtc-s3c.
 
-config RTC_DRV_M48T86
-       tristate "ST M48T86/Dallas DS12887"
-       depends on RTC_CLASS
-       help
-         If you say Y here you will get support for the
-         ST M48T86 and Dallas DS12887 RTC chips.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-m48t86.
-
 config RTC_DRV_EP93XX
        tristate "Cirrus Logic EP93XX"
        depends on RTC_CLASS && ARCH_EP93XX
@@ -308,7 +373,7 @@ config RTC_DRV_PL031
        depends on RTC_CLASS && ARM_AMBA
        help
          If you say Y here you will get access to ARM AMBA
-         PrimeCell PL031 UART found on certain ARM SOCs.
+         PrimeCell PL031 RTC found on certain ARM SOCs.
 
          To compile this driver as a module, choose M here: the
          module will be called rtc-pl031.
@@ -319,41 +384,6 @@ config RTC_DRV_AT91RM9200
        help
          Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock).
 
-config RTC_DRV_TEST
-       tristate "Test driver/device"
-       depends on RTC_CLASS
-       help
-         If you say yes here you get support for the
-         RTC test driver. It's a software RTC which can be
-         used to test the RTC subsystem APIs. It gets
-         the time from the system clock.
-         You want this driver only if you are doing development
-         on the RTC subsystem. Please read the source code
-         for further details.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-test.
-
-config RTC_DRV_MAX6902
-       tristate "Maxim 6902"
-       depends on RTC_CLASS && SPI
-       help
-         If you say yes here you will get support for the
-         Maxim MAX6902 spi RTC chip.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-max6902.
-
-config RTC_DRV_V3020
-       tristate "EM Microelectronic V3020"
-       depends on RTC_CLASS
-       help
-         If you say yes here you will get support for the
-         EM Microelectronic v3020 RTC chip.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-v3020.
-
 config RTC_DRV_BFIN
        tristate "Blackfin On-Chip RTC"
        depends on RTC_CLASS && BFIN
@@ -364,4 +394,10 @@ config RTC_DRV_BFIN
          This driver can also be built as a module. If so, the module
          will be called rtc-bfin.
 
+config RTC_DRV_RS5C313
+       tristate "Ricoh RS5C313"
+       depends on RTC_CLASS && BROKEN
+       help
+         If you say yes here you get support for the Ricoh RS5C313 RTC chips.
+
 endmenu
index 9218cf28d6ed4c727e1c3d7639ab0e011dd23426..a1afbc236073e54a2f9916dbd3442672dc2b6dc0 100644 (file)
@@ -11,9 +11,9 @@ obj-$(CONFIG_RTC_HCTOSYS)     += hctosys.o
 obj-$(CONFIG_RTC_CLASS)                += rtc-core.o
 rtc-core-y                     := class.o interface.o
 
-obj-$(CONFIG_RTC_INTF_SYSFS)   += rtc-sysfs.o
-obj-$(CONFIG_RTC_INTF_PROC)    += rtc-proc.o
-obj-$(CONFIG_RTC_INTF_DEV)     += rtc-dev.o
+rtc-core-$(CONFIG_RTC_INTF_DEV)        += rtc-dev.o
+rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
+rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
 
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_X1205)    += rtc-x1205.o
@@ -30,10 +30,12 @@ obj-$(CONFIG_RTC_DRV_S3C)   += rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_RS5C348)  += rtc-rs5c348.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_DS1553)   += rtc-ds1553.o
+obj-$(CONFIG_RTC_DRV_RS5C313)  += rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_EP93XX)   += rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_SA1100)   += rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_VR41XX)   += rtc-vr41xx.o
 obj-$(CONFIG_RTC_DRV_PL031)    += rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
index 04aaa634723467ac90cbd8bd4d41419bdfc89647..8b3cd31d6a61898ae892539e84d7d3b8ebca6d39 100644 (file)
 #include <linux/kdev_t.h>
 #include <linux/idr.h>
 
+#include "rtc-core.h"
+
+
 static DEFINE_IDR(rtc_idr);
 static DEFINE_MUTEX(idr_lock);
 struct class *rtc_class;
 
-static void rtc_device_release(struct class_device *class_dev)
+static void rtc_device_release(struct device *dev)
 {
-       struct rtc_device *rtc = to_rtc_device(class_dev);
+       struct rtc_device *rtc = to_rtc_device(dev);
        mutex_lock(&idr_lock);
        idr_remove(&rtc_idr, rtc->id);
        mutex_unlock(&idr_lock);
        kfree(rtc);
 }
 
+#if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
+
+/*
+ * On suspend(), measure the delta between one RTC and the
+ * system's wall clock; restore it on resume().
+ */
+
+static struct timespec delta;
+static time_t          oldtime;
+
+static int rtc_suspend(struct device *dev, pm_message_t mesg)
+{
+       struct rtc_device       *rtc = to_rtc_device(dev);
+       struct rtc_time         tm;
+
+       if (strncmp(rtc->dev.bus_id,
+                               CONFIG_RTC_HCTOSYS_DEVICE,
+                               BUS_ID_SIZE) != 0)
+               return 0;
+
+       rtc_read_time(rtc, &tm);
+       rtc_tm_to_time(&tm, &oldtime);
+
+       /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
+       set_normalized_timespec(&delta,
+                               xtime.tv_sec - oldtime,
+                               xtime.tv_nsec - (NSEC_PER_SEC >> 1));
+
+       return 0;
+}
+
+static int rtc_resume(struct device *dev)
+{
+       struct rtc_device       *rtc = to_rtc_device(dev);
+       struct rtc_time         tm;
+       time_t                  newtime;
+       struct timespec         time;
+
+       if (strncmp(rtc->dev.bus_id,
+                               CONFIG_RTC_HCTOSYS_DEVICE,
+                               BUS_ID_SIZE) != 0)
+               return 0;
+
+       rtc_read_time(rtc, &tm);
+       if (rtc_valid_tm(&tm) != 0) {
+               pr_debug("%s:  bogus resume time\n", rtc->dev.bus_id);
+               return 0;
+       }
+       rtc_tm_to_time(&tm, &newtime);
+       if (newtime <= oldtime) {
+               if (newtime < oldtime)
+                       pr_debug("%s:  time travel!\n", rtc->dev.bus_id);
+               return 0;
+       }
+
+       /* restore wall clock using delta against this RTC;
+        * adjust again for avg 1/2 second RTC sampling error
+        */
+       set_normalized_timespec(&time,
+                               newtime + delta.tv_sec,
+                               (NSEC_PER_SEC >> 1) + delta.tv_nsec);
+       do_settimeofday(&time);
+
+       return 0;
+}
+
+#else
+#define rtc_suspend    NULL
+#define rtc_resume     NULL
+#endif
+
+
 /**
  * rtc_device_register - register w/ RTC class
  * @dev: the device to register
@@ -70,23 +145,29 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
        rtc->ops = ops;
        rtc->owner = owner;
        rtc->max_user_freq = 64;
-       rtc->class_dev.dev = dev;
-       rtc->class_dev.class = rtc_class;
-       rtc->class_dev.release = rtc_device_release;
+       rtc->dev.parent = dev;
+       rtc->dev.class = rtc_class;
+       rtc->dev.release = rtc_device_release;
 
        mutex_init(&rtc->ops_lock);
        spin_lock_init(&rtc->irq_lock);
        spin_lock_init(&rtc->irq_task_lock);
 
        strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
-       snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id);
+       snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id);
 
-       err = class_device_register(&rtc->class_dev);
+       rtc_dev_prepare(rtc);
+
+       err = device_register(&rtc->dev);
        if (err)
                goto exit_kfree;
 
+       rtc_dev_add_device(rtc);
+       rtc_sysfs_add_device(rtc);
+       rtc_proc_add_device(rtc);
+
        dev_info(dev, "rtc core: registered %s as %s\n",
-                       rtc->name, rtc->class_dev.class_id);
+                       rtc->name, rtc->dev.bus_id);
 
        return rtc;
 
@@ -113,26 +194,22 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
  */
 void rtc_device_unregister(struct rtc_device *rtc)
 {
-       if (class_device_get(&rtc->class_dev) != NULL) {
+       if (get_device(&rtc->dev) != NULL) {
                mutex_lock(&rtc->ops_lock);
                /* remove innards of this RTC, then disable it, before
                 * letting any rtc_class_open() users access it again
                 */
-               class_device_unregister(&rtc->class_dev);
+               rtc_sysfs_del_device(rtc);
+               rtc_dev_del_device(rtc);
+               rtc_proc_del_device(rtc);
+               device_unregister(&rtc->dev);
                rtc->ops = NULL;
                mutex_unlock(&rtc->ops_lock);
-               class_device_put(&rtc->class_dev);
+               put_device(&rtc->dev);
        }
 }
 EXPORT_SYMBOL_GPL(rtc_device_unregister);
 
-int rtc_interface_register(struct class_interface *intf)
-{
-       intf->class = rtc_class;
-       return class_interface_register(intf);
-}
-EXPORT_SYMBOL_GPL(rtc_interface_register);
-
 static int __init rtc_init(void)
 {
        rtc_class = class_create(THIS_MODULE, "rtc");
@@ -140,11 +217,16 @@ static int __init rtc_init(void)
                printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
                return PTR_ERR(rtc_class);
        }
+       rtc_class->suspend = rtc_suspend;
+       rtc_class->resume = rtc_resume;
+       rtc_dev_init();
+       rtc_sysfs_init(rtc_class);
        return 0;
 }
 
 static void __exit rtc_exit(void)
 {
+       rtc_dev_exit();
        class_destroy(rtc_class);
 }
 
index d02fe9a0001fcfdd58b0b70688b5a6c25a712824..178527252c6a6d04c8dbd55c1ca1ab22aa938e69 100644 (file)
@@ -26,15 +26,15 @@ static int __init rtc_hctosys(void)
 {
        int err;
        struct rtc_time tm;
-       struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+       struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
 
-       if (class_dev == NULL) {
+       if (rtc == NULL) {
                printk("%s: unable to open rtc device (%s)\n",
                        __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
                return -ENODEV;
        }
 
-       err = rtc_read_time(class_dev, &tm);
+       err = rtc_read_time(rtc, &tm);
        if (err == 0) {
                err = rtc_valid_tm(&tm);
                if (err == 0) {
@@ -46,7 +46,7 @@ static int __init rtc_hctosys(void)
 
                        do_settimeofday(&tv);
 
-                       dev_info(class_dev->dev,
+                       dev_info(rtc->dev.parent,
                                "setting the system clock to "
                                "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
                                tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
@@ -54,14 +54,14 @@ static int __init rtc_hctosys(void)
                                (unsigned int) tv.tv_sec);
                }
                else
-                       dev_err(class_dev->dev,
+                       dev_err(rtc->dev.parent,
                                "hctosys: invalid date/time\n");
        }
        else
-               dev_err(class_dev->dev,
+               dev_err(rtc->dev.parent,
                        "hctosys: unable to read the hardware clock\n");
 
-       rtc_class_close(class_dev);
+       rtc_class_close(rtc);
 
        return 0;
 }
index ef40df0f169d2a1039ddca745f586dd122731afa..ad66c6ecf36533d339573106f4bd17db05305e26 100644 (file)
 
 #include <linux/rtc.h>
 
-int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
+int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
 {
        int err;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        err = mutex_lock_interruptible(&rtc->ops_lock);
        if (err)
@@ -28,7 +27,7 @@ int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
                err = -EINVAL;
        else {
                memset(tm, 0, sizeof(struct rtc_time));
-               err = rtc->ops->read_time(class_dev->dev, tm);
+               err = rtc->ops->read_time(rtc->dev.parent, tm);
        }
 
        mutex_unlock(&rtc->ops_lock);
@@ -36,10 +35,9 @@ int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
 }
 EXPORT_SYMBOL_GPL(rtc_read_time);
 
-int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm)
+int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
 {
        int err;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        err = rtc_valid_tm(tm);
        if (err != 0)
@@ -54,17 +52,16 @@ int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm)
        else if (!rtc->ops->set_time)
                err = -EINVAL;
        else
-               err = rtc->ops->set_time(class_dev->dev, tm);
+               err = rtc->ops->set_time(rtc->dev.parent, tm);
 
        mutex_unlock(&rtc->ops_lock);
        return err;
 }
 EXPORT_SYMBOL_GPL(rtc_set_time);
 
-int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
+int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
 {
        int err;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        err = mutex_lock_interruptible(&rtc->ops_lock);
        if (err)
@@ -73,11 +70,11 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
        if (!rtc->ops)
                err = -ENODEV;
        else if (rtc->ops->set_mmss)
-               err = rtc->ops->set_mmss(class_dev->dev, secs);
+               err = rtc->ops->set_mmss(rtc->dev.parent, secs);
        else if (rtc->ops->read_time && rtc->ops->set_time) {
                struct rtc_time new, old;
 
-               err = rtc->ops->read_time(class_dev->dev, &old);
+               err = rtc->ops->read_time(rtc->dev.parent, &old);
                if (err == 0) {
                        rtc_time_to_tm(secs, &new);
 
@@ -89,7 +86,8 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
                         */
                        if (!((old.tm_hour == 23 && old.tm_min == 59) ||
                                (new.tm_hour == 23 && new.tm_min == 59)))
-                               err = rtc->ops->set_time(class_dev->dev, &new);
+                               err = rtc->ops->set_time(rtc->dev.parent,
+                                               &new);
                }
        }
        else
@@ -101,10 +99,9 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
 }
 EXPORT_SYMBOL_GPL(rtc_set_mmss);
 
-int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 {
        int err;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        err = mutex_lock_interruptible(&rtc->ops_lock);
        if (err)
@@ -116,7 +113,7 @@ int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
                err = -EINVAL;
        else {
                memset(alarm, 0, sizeof(struct rtc_wkalrm));
-               err = rtc->ops->read_alarm(class_dev->dev, alarm);
+               err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
        }
 
        mutex_unlock(&rtc->ops_lock);
@@ -124,10 +121,13 @@ int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
 }
 EXPORT_SYMBOL_GPL(rtc_read_alarm);
 
-int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 {
        int err;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
+
+       err = rtc_valid_tm(&alarm->time);
+       if (err != 0)
+               return err;
 
        err = mutex_lock_interruptible(&rtc->ops_lock);
        if (err)
@@ -138,7 +138,7 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
        else if (!rtc->ops->set_alarm)
                err = -EINVAL;
        else
-               err = rtc->ops->set_alarm(class_dev->dev, alarm);
+               err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
 
        mutex_unlock(&rtc->ops_lock);
        return err;
@@ -147,16 +147,14 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
 /**
  * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
- * @class_dev: the rtc's class device
+ * @rtc: the rtc device
  * @num: how many irqs are being reported (usually one)
  * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
  * Context: in_interrupt(), irqs blocked
  */
-void rtc_update_irq(struct class_device *class_dev,
+void rtc_update_irq(struct rtc_device *rtc,
                unsigned long num, unsigned long events)
 {
-       struct rtc_device *rtc = to_rtc_device(class_dev);
-
        spin_lock(&rtc->irq_lock);
        rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
        spin_unlock(&rtc->irq_lock);
@@ -171,40 +169,43 @@ void rtc_update_irq(struct class_device *class_dev,
 }
 EXPORT_SYMBOL_GPL(rtc_update_irq);
 
-struct class_device *rtc_class_open(char *name)
+struct rtc_device *rtc_class_open(char *name)
 {
-       struct class_device *class_dev = NULL,
-                               *class_dev_tmp;
+       struct device *dev;
+       struct rtc_device *rtc = NULL;
 
        down(&rtc_class->sem);
-       list_for_each_entry(class_dev_tmp, &rtc_class->children, node) {
-               if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) {
-                       class_dev = class_device_get(class_dev_tmp);
+       list_for_each_entry(dev, &rtc_class->devices, node) {
+               if (strncmp(dev->bus_id, name, BUS_ID_SIZE) == 0) {
+                       dev = get_device(dev);
+                       if (dev)
+                               rtc = to_rtc_device(dev);
                        break;
                }
        }
 
-       if (class_dev) {
-               if (!try_module_get(to_rtc_device(class_dev)->owner))
-                       class_dev = NULL;
+       if (rtc) {
+               if (!try_module_get(rtc->owner)) {
+                       put_device(dev);
+                       rtc = NULL;
+               }
        }
        up(&rtc_class->sem);
 
-       return class_dev;
+       return rtc;
 }
 EXPORT_SYMBOL_GPL(rtc_class_open);
 
-void rtc_class_close(struct class_device *class_dev)
+void rtc_class_close(struct rtc_device *rtc)
 {
-       module_put(to_rtc_device(class_dev)->owner);
-       class_device_put(class_dev);
+       module_put(rtc->owner);
+       put_device(&rtc->dev);
 }
 EXPORT_SYMBOL_GPL(rtc_class_close);
 
-int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
+int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
 {
        int retval = -EBUSY;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        if (task == NULL || task->func == NULL)
                return -EINVAL;
@@ -220,9 +221,8 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
 }
 EXPORT_SYMBOL_GPL(rtc_irq_register);
 
-void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
+void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
 {
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        spin_lock_irq(&rtc->irq_task_lock);
        if (rtc->irq_task == task)
@@ -231,11 +231,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
-int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled)
+int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
 {
        int err = 0;
        unsigned long flags;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        if (rtc->ops->irq_set_state == NULL)
                return -ENXIO;
@@ -246,17 +245,16 @@ int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int
        spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
 
        if (err == 0)
-               err = rtc->ops->irq_set_state(class_dev->dev, enabled);
+               err = rtc->ops->irq_set_state(rtc->dev.parent, enabled);
 
        return err;
 }
 EXPORT_SYMBOL_GPL(rtc_irq_set_state);
 
-int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
+int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
 {
        int err = 0;
        unsigned long flags;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
 
        if (rtc->ops->irq_set_freq == NULL)
                return -ENXIO;
@@ -267,7 +265,7 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int
        spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
 
        if (err == 0) {
-               err = rtc->ops->irq_set_freq(class_dev->dev, freq);
+               err = rtc->ops->irq_set_freq(rtc->dev.parent, freq);
                if (err == 0)
                        rtc->irq_freq = freq;
        }
index ac0e68e2f025d388504c4005519d90e006496b1f..33795e5a5595fff8eee39ae03d7eef697354c941 100644 (file)
@@ -263,7 +263,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
 
                at91_sys_write(AT91_RTC_SCCR, rtsr);    /* clear status reg */
 
-               rtc_update_irq(&rtc->class_dev, 1, events);
+               rtc_update_irq(rtc, 1, events);
 
                pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
                        events >> 8, events & 0x000000FF);
@@ -348,21 +348,10 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
 
 /* AT91RM9200 RTC Power management control */
 
-static struct timespec at91_rtc_delta;
 static u32 at91_rtc_imr;
 
 static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct rtc_time tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-
-       /* calculate time delta for suspend */
-       at91_rtc_readtime(&pdev->dev, &tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       save_time_delta(&at91_rtc_delta, &time);
-
        /* this IRQ is shared with DBGU and other hardware which isn't
         * necessarily doing PM like we are...
         */
@@ -374,36 +363,17 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
                else
                        at91_sys_write(AT91_RTC_IDR, at91_rtc_imr);
        }
-
-       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
-               1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
-               tm.tm_hour, tm.tm_min, tm.tm_sec);
-
        return 0;
 }
 
 static int at91_rtc_resume(struct platform_device *pdev)
 {
-       struct rtc_time tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-
-       at91_rtc_readtime(&pdev->dev, &tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       restore_time_delta(&at91_rtc_delta, &time);
-
        if (at91_rtc_imr) {
                if (device_may_wakeup(&pdev->dev))
                        disable_irq_wake(AT91_ID_SYS);
                else
                        at91_sys_write(AT91_RTC_IER, at91_rtc_imr);
        }
-
-       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
-               1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
-               tm.tm_hour, tm.tm_min, tm.tm_sec);
-
        return 0;
 }
 #else
index 7c0d609100775148dfe6da456f6eee7af7755e96..6085261aa2c15b581a8c7dba2a7b2830a945db86 100644 (file)
@@ -46,6 +46,10 @@ struct cmos_rtc {
        int                     irq;
        struct resource         *iomem;
 
+       void                    (*wake_on)(struct device *);
+       void                    (*wake_off)(struct device *);
+
+       u8                      enabled_wake;
        u8                      suspend_ctrl;
 
        /* newer hardware extends the original register set */
@@ -203,7 +207,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
        rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
        if (is_intr(rtc_intr))
-               rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+               rtc_update_irq(cmos->rtc, 1, rtc_intr);
 
        /* update alarm */
        CMOS_WRITE(hrs, RTC_HOURS_ALARM);
@@ -223,7 +227,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
                rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
                rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
                if (is_intr(rtc_intr))
-                       rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+                       rtc_update_irq(cmos->rtc, 1, rtc_intr);
        }
 
        spin_unlock_irq(&rtc_lock);
@@ -304,7 +308,7 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
        rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
        rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
        if (is_intr(rtc_intr))
-               rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+               rtc_update_irq(cmos->rtc, 1, rtc_intr);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return 0;
 }
@@ -379,12 +383,12 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
                return IRQ_NONE;
 }
 
-#ifdef CONFIG_PNPACPI
-#define        is_pnpacpi()    1
+#ifdef CONFIG_PNP
+#define        is_pnp()        1
 #define        INITSECTION
 
 #else
-#define        is_pnpacpi()    0
+#define        is_pnp()        0
 #define        INITSECTION     __init
 #endif
 
@@ -405,13 +409,20 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
        cmos_rtc.irq = rtc_irq;
        cmos_rtc.iomem = ports;
 
-       /* For ACPI systems the info comes from the FADT.  On others,
-        * board specific setup provides it as appropriate.
+       /* For ACPI systems extension info comes from the FADT.  On others,
+        * board specific setup provides it as appropriate.  Systems where
+        * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and
+        * some almost-clones) can provide hooks to make that behave.
         */
        if (info) {
                cmos_rtc.day_alrm = info->rtc_day_alarm;
                cmos_rtc.mon_alrm = info->rtc_mon_alarm;
                cmos_rtc.century = info->rtc_century;
+
+               if (info->wake_on && info->wake_off) {
+                       cmos_rtc.wake_on = info->wake_on;
+                       cmos_rtc.wake_off = info->wake_off;
+               }
        }
 
        cmos_rtc.rtc = rtc_device_register(driver_name, dev,
@@ -427,14 +438,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
         * REVISIT for non-x86 systems we may need to handle io memory
         * resources: ioremap them, and request_mem_region().
         */
-       if (is_pnpacpi()) {
+       if (is_pnp()) {
                retval = request_resource(&ioport_resource, ports);
                if (retval < 0) {
                        dev_dbg(dev, "i/o registers already in use\n");
                        goto cleanup0;
                }
        }
-       rename_region(ports, cmos_rtc.rtc->class_dev.class_id);
+       rename_region(ports, cmos_rtc.rtc->dev.bus_id);
 
        spin_lock_irq(&rtc_lock);
 
@@ -470,8 +481,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 
        if (is_valid_irq(rtc_irq))
                retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED,
-                               cmos_rtc.rtc->class_dev.class_id,
-                               &cmos_rtc.rtc->class_dev);
+                               cmos_rtc.rtc->dev.bus_id,
+                               cmos_rtc.rtc);
        if (retval < 0) {
                dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
                goto cleanup1;
@@ -483,7 +494,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
         */
 
        pr_info("%s: alarms up to one %s%s\n",
-                       cmos_rtc.rtc->class_dev.class_id,
+                       cmos_rtc.rtc->dev.bus_id,
                        is_valid_irq(rtc_irq)
                                ?  (cmos_rtc.mon_alrm
                                        ? "year"
@@ -520,12 +531,12 @@ static void __exit cmos_do_remove(struct device *dev)
 
        cmos_do_shutdown();
 
-       if (is_pnpacpi())
+       if (is_pnp())
                release_resource(cmos->iomem);
        rename_region(cmos->iomem, NULL);
 
        if (is_valid_irq(cmos->irq))
-               free_irq(cmos->irq, &cmos_rtc.rtc->class_dev);
+               free_irq(cmos->irq, cmos_rtc.rtc);
 
        rtc_device_unregister(cmos_rtc.rtc);
 
@@ -555,16 +566,20 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
                irqstat = CMOS_READ(RTC_INTR_FLAGS);
                irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
                if (is_intr(irqstat))
-                       rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat);
+                       rtc_update_irq(cmos->rtc, 1, irqstat);
        }
        spin_unlock_irq(&rtc_lock);
 
-       /* ACPI HOOK:  enable ACPI_EVENT_RTC when (tmp & RTC_AIE)
-        * ... it'd be best if we could do that under rtc_lock.
-        */
+       if (tmp & RTC_AIE) {
+               cmos->enabled_wake = 1;
+               if (cmos->wake_on)
+                       cmos->wake_on(dev);
+               else
+                       enable_irq_wake(cmos->irq);
+       }
 
        pr_debug("%s: suspend%s, ctrl %02x\n",
-                       cmos_rtc.rtc->class_dev.class_id,
+                       cmos_rtc.rtc->dev.bus_id,
                        (tmp & RTC_AIE) ? ", alarm may wake" : "",
                        tmp);
 
@@ -576,26 +591,28 @@ static int cmos_resume(struct device *dev)
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
        unsigned char   tmp = cmos->suspend_ctrl;
 
-       /* REVISIT:  a mechanism to resync the system clock (jiffies)
-        * on resume should be portable between platforms ...
-        */
-
        /* re-enable any irqs previously active */
        if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
 
-               /* ACPI HOOK:  disable ACPI_EVENT_RTC when (tmp & RTC_AIE) */
+               if (cmos->enabled_wake) {
+                       if (cmos->wake_off)
+                               cmos->wake_off(dev);
+                       else
+                               disable_irq_wake(cmos->irq);
+                       cmos->enabled_wake = 0;
+               }
 
                spin_lock_irq(&rtc_lock);
                CMOS_WRITE(tmp, RTC_CONTROL);
                tmp = CMOS_READ(RTC_INTR_FLAGS);
                tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
                if (is_intr(tmp))
-                       rtc_update_irq(&cmos->rtc->class_dev, 1, tmp);
+                       rtc_update_irq(cmos->rtc, 1, tmp);
                spin_unlock_irq(&rtc_lock);
        }
 
        pr_debug("%s: resume, ctrl %02x\n",
-                       cmos_rtc.rtc->class_dev.class_id,
+                       cmos_rtc.rtc->dev.bus_id,
                        cmos->suspend_ctrl);
 
 
@@ -613,7 +630,7 @@ static int cmos_resume(struct device *dev)
  * the device node will always be created as a PNPACPI device.
  */
 
-#ifdef CONFIG_PNPACPI
+#ifdef CONFIG_PNP
 
 #include <linux/pnp.h>
 
@@ -684,11 +701,11 @@ static void __exit cmos_exit(void)
 }
 module_exit(cmos_exit);
 
-#else  /* no PNPACPI */
+#else  /* no PNP */
 
 /*----------------------------------------------------------------*/
 
-/* Platform setup should have set up an RTC device, when PNPACPI is
+/* Platform setup should have set up an RTC device, when PNP is
  * unavailable ... this could happen even on (older) PCs.
  */
 
@@ -734,7 +751,7 @@ static void __exit cmos_exit(void)
 module_exit(cmos_exit);
 
 
-#endif /* !PNPACPI */
+#endif /* !PNP */
 
 MODULE_AUTHOR("David Brownell");
 MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs");
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
new file mode 100644 (file)
index 0000000..5f9df74
--- /dev/null
@@ -0,0 +1,70 @@
+#ifdef CONFIG_RTC_INTF_DEV
+
+extern void __init rtc_dev_init(void);
+extern void __exit rtc_dev_exit(void);
+extern void rtc_dev_prepare(struct rtc_device *rtc);
+extern void rtc_dev_add_device(struct rtc_device *rtc);
+extern void rtc_dev_del_device(struct rtc_device *rtc);
+
+#else
+
+static inline void rtc_dev_init(void)
+{
+}
+
+static inline void rtc_dev_exit(void)
+{
+}
+
+static inline void rtc_dev_prepare(struct rtc_device *rtc)
+{
+}
+
+static inline void rtc_dev_add_device(struct rtc_device *rtc)
+{
+}
+
+static inline void rtc_dev_del_device(struct rtc_device *rtc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_RTC_INTF_PROC
+
+extern void rtc_proc_add_device(struct rtc_device *rtc);
+extern void rtc_proc_del_device(struct rtc_device *rtc);
+
+#else
+
+static inline void rtc_proc_add_device(struct rtc_device *rtc)
+{
+}
+
+static inline void rtc_proc_del_device(struct rtc_device *rtc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_RTC_INTF_SYSFS
+
+extern void __init rtc_sysfs_init(struct class *);
+extern void rtc_sysfs_add_device(struct rtc_device *rtc);
+extern void rtc_sysfs_del_device(struct rtc_device *rtc);
+
+#else
+
+static inline void rtc_sysfs_init(struct class *rtc)
+{
+}
+
+static inline void rtc_sysfs_add_device(struct rtc_device *rtc)
+{
+}
+
+static inline void rtc_sysfs_del_device(struct rtc_device *rtc)
+{
+}
+
+#endif
index 137330b8636b1192ec2965ee22defd28a600a4db..f4e5f0040ff7a43263a2af50b9eb694624f3fa91 100644 (file)
@@ -13,8 +13,8 @@
 
 #include <linux/module.h>
 #include <linux/rtc.h>
+#include "rtc-core.h"
 
-static struct class *rtc_dev_class;
 static dev_t rtc_devt;
 
 #define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */
@@ -32,9 +32,9 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
        if (!(mutex_trylock(&rtc->char_lock)))
                return -EBUSY;
 
-       file->private_data = &rtc->class_dev;
+       file->private_data = rtc;
 
-       err = ops->open ? ops->open(rtc->class_dev.dev) : 0;
+       err = ops->open ? ops->open(rtc->dev.parent) : 0;
        if (err == 0) {
                spin_lock_irq(&rtc->irq_lock);
                rtc->irq_data = 0;
@@ -61,7 +61,7 @@ static void rtc_uie_task(struct work_struct *work)
        int num = 0;
        int err;
 
-       err = rtc_read_time(&rtc->class_dev, &tm);
+       err = rtc_read_time(rtc, &tm);
 
        local_irq_disable();
        spin_lock(&rtc->irq_lock);
@@ -79,7 +79,7 @@ static void rtc_uie_task(struct work_struct *work)
        }
        spin_unlock(&rtc->irq_lock);
        if (num)
-               rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+               rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF);
        local_irq_enable();
 }
 static void rtc_uie_timer(unsigned long data)
@@ -121,7 +121,7 @@ static int set_uie(struct rtc_device *rtc)
        struct rtc_time tm;
        int err;
 
-       err = rtc_read_time(&rtc->class_dev, &tm);
+       err = rtc_read_time(rtc, &tm);
        if (err)
                return err;
        spin_lock_irq(&rtc->irq_lock);
@@ -180,7 +180,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        if (ret == 0) {
                /* Check for any data updates */
                if (rtc->ops->read_callback)
-                       data = rtc->ops->read_callback(rtc->class_dev.dev,
+                       data = rtc->ops->read_callback(rtc->dev.parent,
                                                       data);
 
                if (sizeof(int) != sizeof(long) &&
@@ -210,8 +210,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                unsigned int cmd, unsigned long arg)
 {
        int err = 0;
-       struct class_device *class_dev = file->private_data;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
+       struct rtc_device *rtc = file->private_data;
        const struct rtc_class_ops *ops = rtc->ops;
        struct rtc_time tm;
        struct rtc_wkalrm alarm;
@@ -252,7 +251,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
        /* try the driver's ioctl interface */
        if (ops->ioctl) {
-               err = ops->ioctl(class_dev->dev, cmd, arg);
+               err = ops->ioctl(rtc->dev.parent, cmd, arg);
                if (err != -ENOIOCTLCMD)
                        return err;
        }
@@ -264,7 +263,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case RTC_ALM_READ:
-               err = rtc_read_alarm(class_dev, &alarm);
+               err = rtc_read_alarm(rtc, &alarm);
                if (err < 0)
                        return err;
 
@@ -278,17 +277,53 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
                alarm.enabled = 0;
                alarm.pending = 0;
-               alarm.time.tm_mday = -1;
-               alarm.time.tm_mon = -1;
-               alarm.time.tm_year = -1;
                alarm.time.tm_wday = -1;
                alarm.time.tm_yday = -1;
                alarm.time.tm_isdst = -1;
-               err = rtc_set_alarm(class_dev, &alarm);
+
+               /* RTC_ALM_SET alarms may be up to 24 hours in the future.
+                * Rather than expecting every RTC to implement "don't care"
+                * for day/month/year fields, just force the alarm to have
+                * the right values for those fields.
+                *
+                * RTC_WKALM_SET should be used instead.  Not only does it
+                * eliminate the need for a separate RTC_AIE_ON call, it
+                * doesn't have the "alarm 23:59:59 in the future" race.
+                *
+                * NOTE:  some legacy code may have used invalid fields as
+                * wildcards, exposing hardware "periodic alarm" capabilities.
+                * Not supported here.
+                */
+               {
+                       unsigned long now, then;
+
+                       err = rtc_read_time(rtc, &tm);
+                       if (err < 0)
+                               return err;
+                       rtc_tm_to_time(&tm, &now);
+
+                       alarm.time.tm_mday = tm.tm_mday;
+                       alarm.time.tm_mon = tm.tm_mon;
+                       alarm.time.tm_year = tm.tm_year;
+                       err  = rtc_valid_tm(&alarm.time);
+                       if (err < 0)
+                               return err;
+                       rtc_tm_to_time(&alarm.time, &then);
+
+                       /* alarm may need to wrap into tomorrow */
+                       if (then < now) {
+                               rtc_time_to_tm(now + 24 * 60 * 60, &tm);
+                               alarm.time.tm_mday = tm.tm_mday;
+                               alarm.time.tm_mon = tm.tm_mon;
+                               alarm.time.tm_year = tm.tm_year;
+                       }
+               }
+
+               err = rtc_set_alarm(rtc, &alarm);
                break;
 
        case RTC_RD_TIME:
-               err = rtc_read_time(class_dev, &tm);
+               err = rtc_read_time(rtc, &tm);
                if (err < 0)
                        return err;
 
@@ -300,7 +335,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                if (copy_from_user(&tm, uarg, sizeof(tm)))
                        return -EFAULT;
 
-               err = rtc_set_time(class_dev, &tm);
+               err = rtc_set_time(rtc, &tm);
                break;
 
        case RTC_IRQP_READ:
@@ -310,7 +345,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
        case RTC_IRQP_SET:
                if (ops->irq_set_freq)
-                       err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg);
+                       err = rtc_irq_set_freq(rtc, rtc->irq_task, arg);
                break;
 
 #if 0
@@ -336,11 +371,11 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                if (copy_from_user(&alarm, uarg, sizeof(alarm)))
                        return -EFAULT;
 
-               err = rtc_set_alarm(class_dev, &alarm);
+               err = rtc_set_alarm(rtc, &alarm);
                break;
 
        case RTC_WKALM_RD:
-               err = rtc_read_alarm(class_dev, &alarm);
+               err = rtc_read_alarm(rtc, &alarm);
                if (err < 0)
                        return err;
 
@@ -372,7 +407,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
        clear_uie(rtc);
 #endif
        if (rtc->ops->release)
-               rtc->ops->release(rtc->class_dev.dev);
+               rtc->ops->release(rtc->dev.parent);
 
        mutex_unlock(&rtc->char_lock);
        return 0;
@@ -397,17 +432,18 @@ static const struct file_operations rtc_dev_fops = {
 
 /* insertion/removal hooks */
 
-static int rtc_dev_add_device(struct class_device *class_dev,
-                               struct class_interface *class_intf)
+void rtc_dev_prepare(struct rtc_device *rtc)
 {
-       int err = 0;
-       struct rtc_device *rtc = to_rtc_device(class_dev);
+       if (!rtc_devt)
+               return;
 
        if (rtc->id >= RTC_DEV_MAX) {
-               dev_err(class_dev->dev, "too many RTCs\n");
-               return -EINVAL;
+               pr_debug("%s: too many RTC devices\n", rtc->name);
+               return;
        }
 
+       rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id);
+
        mutex_init(&rtc->char_lock);
        spin_lock_init(&rtc->irq_lock);
        init_waitqueue_head(&rtc->irq_queue);
@@ -418,100 +454,36 @@ static int rtc_dev_add_device(struct class_device *class_dev,
 
        cdev_init(&rtc->char_dev, &rtc_dev_fops);
        rtc->char_dev.owner = rtc->owner;
+}
 
-       if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) {
-               dev_err(class_dev->dev,
-                       "failed to add char device %d:%d\n",
+void rtc_dev_add_device(struct rtc_device *rtc)
+{
+       if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1))
+               printk(KERN_WARNING "%s: failed to add char device %d:%d\n",
+                       rtc->name, MAJOR(rtc_devt), rtc->id);
+       else
+               pr_debug("%s: dev (%d:%d)\n", rtc->name,
                        MAJOR(rtc_devt), rtc->id);
-               return -ENODEV;
-       }
-
-       rtc->rtc_dev = class_device_create(rtc_dev_class, NULL,
-                                               MKDEV(MAJOR(rtc_devt), rtc->id),
-                                               class_dev->dev, "rtc%d", rtc->id);
-       if (IS_ERR(rtc->rtc_dev)) {
-               dev_err(class_dev->dev, "cannot create rtc_dev device\n");
-               err = PTR_ERR(rtc->rtc_dev);
-               goto err_cdev_del;
-       }
-
-       dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n",
-               MAJOR(rtc->rtc_dev->devt),
-               MINOR(rtc->rtc_dev->devt));
-
-       return 0;
-
-err_cdev_del:
-
-       cdev_del(&rtc->char_dev);
-       return err;
 }
 
-static void rtc_dev_remove_device(struct class_device *class_dev,
-                                       struct class_interface *class_intf)
+void rtc_dev_del_device(struct rtc_device *rtc)
 {
-       struct rtc_device *rtc = to_rtc_device(class_dev);
-
-       if (rtc->rtc_dev) {
-               dev_dbg(class_dev->dev, "removing char %d:%d\n",
-                       MAJOR(rtc->rtc_dev->devt),
-                       MINOR(rtc->rtc_dev->devt));
-
-               class_device_unregister(rtc->rtc_dev);
+       if (rtc->dev.devt)
                cdev_del(&rtc->char_dev);
-       }
 }
 
-/* interface registration */
-
-static struct class_interface rtc_dev_interface = {
-       .add = &rtc_dev_add_device,
-       .remove = &rtc_dev_remove_device,
-};
-
-static int __init rtc_dev_init(void)
+void __init rtc_dev_init(void)
 {
        int err;
 
-       rtc_dev_class = class_create(THIS_MODULE, "rtc-dev");
-       if (IS_ERR(rtc_dev_class))
-               return PTR_ERR(rtc_dev_class);
-
        err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");
-       if (err < 0) {
+       if (err < 0)
                printk(KERN_ERR "%s: failed to allocate char dev region\n",
                        __FILE__);
-               goto err_destroy_class;
-       }
-
-       err = rtc_interface_register(&rtc_dev_interface);
-       if (err < 0) {
-               printk(KERN_ERR "%s: failed to register the interface\n",
-                       __FILE__);
-               goto err_unregister_chrdev;
-       }
-
-       return 0;
-
-err_unregister_chrdev:
-       unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
-
-err_destroy_class:
-       class_destroy(rtc_dev_class);
-
-       return err;
 }
 
-static void __exit rtc_dev_exit(void)
+void __exit rtc_dev_exit(void)
 {
-       class_interface_unregister(&rtc_dev_interface);
-       class_destroy(rtc_dev_class);
-       unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
+       if (rtc_devt)
+               unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
 }
-
-subsys_initcall(rtc_dev_init);
-module_exit(rtc_dev_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("RTC class dev interface");
-MODULE_LICENSE("GPL");
index e27176c0e18fb0cd2ec6f11457d0f7c3ce4664ff..afa64c7fa2e2d67152b50fe75b011e7cf2c8a6f2 100644 (file)
@@ -203,7 +203,7 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
                events |= RTC_UF;
        else
                events |= RTC_AF;
-       rtc_update_irq(&pdata->rtc->class_dev, 1, events);
+       rtc_update_irq(pdata->rtc, 1, events);
        return IRQ_HANDLED;
 }
 
index 7bbc26a34bd25d7007abaaea57d017343f24ce59..ba795a4db1e97289829c3c69dbee613fa2720a25 100644 (file)
@@ -117,85 +117,4 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
 }
 EXPORT_SYMBOL(rtc_tm_to_time);
 
-
-/* Merge the valid (i.e. non-negative) fields of alarm into the current
- * time.  If the valid alarm fields are earlier than the equivalent
- * fields in the time, carry one into the least significant invalid
- * field, so that the alarm expiry is in the future.  It assumes that the
- * least significant invalid field is more significant than the most
- * significant valid field, and that the seconds field is valid.
- *
- * This is used by alarms that take relative (rather than absolute)
- * times, and/or have a simple binary second counter instead of
- * day/hour/minute/sec registers.
- */
-void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm)
-{
-       int *alarmp = &alarm->tm_sec;
-       int *timep = &now->tm_sec;
-       int carry_into, i;
-
-       /* Ignore everything past the 6th element (tm_year). */
-       for (i = 5; i > 0; i--) {
-               if (alarmp[i] < 0)
-                       alarmp[i] = timep[i];
-               else
-                       break;
-       }
-
-       /* No carry needed if all fields are valid. */
-       if (i == 5)
-               return;
-
-       for (carry_into = i + 1; i >= 0; i--) {
-               if (alarmp[i] < timep[i])
-                       break;
-
-               if (alarmp[i] > timep[i])
-                       return;
-       }
-
-       switch (carry_into) {
-               case 1:
-                       alarm->tm_min++;
-
-                       if (alarm->tm_min < 60)
-                               return;
-
-                       alarm->tm_min = 0;
-                       /* fall-through */
-
-               case 2:
-                       alarm->tm_hour++;
-
-                       if (alarm->tm_hour < 60)
-                               return;
-
-                       alarm->tm_hour = 0;
-                       /* fall-through */
-
-               case 3:
-                       alarm->tm_mday++;
-
-                       if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon])
-                               return;
-
-                       alarm->tm_mday = 1;
-                       /* fall-through */
-
-               case 4:
-                       alarm->tm_mon++;
-
-                       if (alarm->tm_mon <= 12)
-                               return;
-
-                       alarm->tm_mon = 1;
-                       /* fall-through */
-
-               case 5:
-                       alarm->tm_year++;
-       }
-}
-EXPORT_SYMBOL(rtc_merge_alarm);
-
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
new file mode 100644 (file)
index 0000000..eee4ee5
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * rtc class driver for the Maxim MAX6900 chip
+ *
+ * Author: Dale Farnsworth <dale@farnsworth.org>
+ *
+ * based on previously existing rtc class drivers
+ *
+ * 2007 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+
+#define DRV_NAME "max6900"
+#define DRV_VERSION "0.1"
+
+/*
+ * register indices
+ */
+#define MAX6900_REG_SC                 0       /* seconds      00-59 */
+#define MAX6900_REG_MN                 1       /* minutes      00-59 */
+#define MAX6900_REG_HR                 2       /* hours        00-23 */
+#define MAX6900_REG_DT                 3       /* day of month 00-31 */
+#define MAX6900_REG_MO                 4       /* month        01-12 */
+#define MAX6900_REG_DW                 5       /* day of week   1-7  */
+#define MAX6900_REG_YR                 6       /* year         00-99 */
+#define MAX6900_REG_CT                 7       /* control */
+#define MAX6900_REG_LEN                        8
+
+#define MAX6900_REG_CT_WP              (1 << 7)        /* Write Protect */
+
+/*
+ * register read/write commands
+ */
+#define MAX6900_REG_CONTROL_WRITE      0x8e
+#define MAX6900_REG_BURST_READ         0xbf
+#define MAX6900_REG_BURST_WRITE                0xbe
+#define MAX6900_REG_RESERVED_READ      0x96
+
+#define MAX6900_IDLE_TIME_AFTER_WRITE  3       /* specification says 2.5 mS */
+
+#define MAX6900_I2C_ADDR               0xa0
+
+static unsigned short normal_i2c[] = {
+       MAX6900_I2C_ADDR >> 1,
+       I2C_CLIENT_END
+};
+
+I2C_CLIENT_INSMOD;                     /* defines addr_data */
+
+static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind);
+
+static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
+{
+       u8 reg_addr[1] = { MAX6900_REG_BURST_READ };
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr   = client->addr,
+                       .flags  = 0, /* write */
+                       .len    = sizeof(reg_addr),
+                       .buf    = reg_addr
+               },
+               {
+                       .addr   = client->addr,
+                       .flags  = I2C_M_RD,
+                       .len    = MAX6900_REG_LEN,
+                       .buf    = buf
+               }
+       };
+       int rc;
+
+       rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (rc != ARRAY_SIZE(msgs)) {
+               dev_err(&client->dev, "%s: register read failed\n",
+                       __FUNCTION__);
+               return -EIO;
+       }
+       return 0;
+}
+
+static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
+{
+       u8 i2c_buf[MAX6900_REG_LEN + 1] = { MAX6900_REG_BURST_WRITE };
+       struct i2c_msg msgs[1] = {
+               {
+                       .addr   = client->addr,
+                       .flags  = 0, /* write */
+                       .len    = MAX6900_REG_LEN + 1,
+                       .buf    = i2c_buf
+               }
+       };
+       int rc;
+
+       memcpy(&i2c_buf[1], buf, MAX6900_REG_LEN);
+
+       rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (rc != ARRAY_SIZE(msgs)) {
+               dev_err(&client->dev, "%s: register write failed\n",
+                       __FUNCTION__);
+               return -EIO;
+       }
+       msleep(MAX6900_IDLE_TIME_AFTER_WRITE);
+       return 0;
+}
+
+static int max6900_i2c_validate_client(struct i2c_client *client)
+{
+       u8 regs[MAX6900_REG_LEN];
+       u8 zero_mask[MAX6900_REG_LEN] = {
+               0x80,   /* seconds */
+               0x80,   /* minutes */
+               0x40,   /* hours */
+               0xc0,   /* day of month */
+               0xe0,   /* month */
+               0xf8,   /* day of week */
+               0x00,   /* year */
+               0x7f,   /* control */
+       };
+       int i;
+       int rc;
+       int reserved;
+
+       reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ);
+       if (reserved != 0x07)
+               return -ENODEV;
+
+       rc = max6900_i2c_read_regs(client, regs);
+       if (rc < 0)
+               return rc;
+
+       for (i = 0; i < MAX6900_REG_LEN; ++i) {
+               if (regs[i] & zero_mask[i])
+                       return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+{
+       int rc;
+       u8 regs[MAX6900_REG_LEN];
+
+       rc = max6900_i2c_read_regs(client, regs);
+       if (rc < 0)
+               return rc;
+
+       tm->tm_sec = BCD2BIN(regs[MAX6900_REG_SC]);
+       tm->tm_min = BCD2BIN(regs[MAX6900_REG_MN]);
+       tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f);
+       tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]);
+       tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1;
+       tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + 100;
+       tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]);
+
+       return 0;
+}
+
+static int max6900_i2c_clear_write_protect(struct i2c_client *client)
+{
+       int rc;
+       rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0);
+       if (rc < 0) {
+               dev_err(&client->dev, "%s: control register write failed\n",
+                       __FUNCTION__);
+               return -EIO;
+       }
+       return 0;
+}
+
+static int max6900_i2c_set_time(struct i2c_client *client,
+                               struct rtc_time const *tm)
+{
+       u8 regs[MAX6900_REG_LEN];
+       int rc;
+
+       rc = max6900_i2c_clear_write_protect(client);
+       if (rc < 0)
+               return rc;
+
+       regs[MAX6900_REG_SC] = BIN2BCD(tm->tm_sec);
+       regs[MAX6900_REG_MN] = BIN2BCD(tm->tm_min);
+       regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour);
+       regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday);
+       regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+       regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year - 100);
+       regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday);
+       regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP;       /* set write protect */
+
+       rc = max6900_i2c_write_regs(client, regs);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       return max6900_i2c_read_time(to_i2c_client(dev), tm);
+}
+
+static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       return max6900_i2c_set_time(to_i2c_client(dev), tm);
+}
+
+static int max6900_attach_adapter(struct i2c_adapter *adapter)
+{
+       return i2c_probe(adapter, &addr_data, max6900_probe);
+}
+
+static int max6900_detach_client(struct i2c_client *client)
+{
+       struct rtc_device *const rtc = i2c_get_clientdata(client);
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       return i2c_detach_client(client);
+}
+
+static struct i2c_driver max6900_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+       .id             = I2C_DRIVERID_MAX6900,
+       .attach_adapter = max6900_attach_adapter,
+       .detach_client  = max6900_detach_client,
+};
+
+static const struct rtc_class_ops max6900_rtc_ops = {
+       .read_time      = max6900_rtc_read_time,
+       .set_time       = max6900_rtc_set_time,
+};
+
+static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind)
+{
+       int rc = 0;
+       struct i2c_client *client = NULL;
+       struct rtc_device *rtc = NULL;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+               rc = -ENODEV;
+               goto failout;
+       }
+
+       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (client == NULL) {
+               rc = -ENOMEM;
+               goto failout;
+       }
+
+       client->addr = addr;
+       client->adapter = adapter;
+       client->driver = &max6900_driver;
+       strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE);
+
+       if (kind < 0) {
+               rc = max6900_i2c_validate_client(client);
+               if (rc < 0)
+                       goto failout;
+       }
+
+       rc = i2c_attach_client(client);
+       if (rc < 0)
+               goto failout;
+
+       dev_info(&client->dev,
+                "chip found, driver version " DRV_VERSION "\n");
+
+       rtc = rtc_device_register(max6900_driver.driver.name,
+                                 &client->dev,
+                                 &max6900_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               rc = PTR_ERR(rtc);
+               goto failout_detach;
+       }
+
+       i2c_set_clientdata(client, rtc);
+
+       return 0;
+
+failout_detach:
+       i2c_detach_client(client);
+failout:
+       kfree(client);
+       return rc;
+}
+
+static int __init max6900_init(void)
+{
+       return i2c_add_driver(&max6900_driver);
+}
+
+static void __exit max6900_exit(void)
+{
+       i2c_del_driver(&max6900_driver);
+}
+
+MODULE_DESCRIPTION("Maxim MAX6900 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(max6900_init);
+module_exit(max6900_exit);
index 9de8d67f4f8d8ac71bcbc4c198d4b496d8c4dc27..60a8a4bb8bd285ba10dcde76e8dabc595994c1ad 100644 (file)
@@ -124,7 +124,7 @@ static void rtc_wait_not_busy(void)
        /* now we have ~15 usec to read/write various registers */
 }
 
-static irqreturn_t rtc_irq(int irq, void *class_dev)
+static irqreturn_t rtc_irq(int irq, void *rtc)
 {
        unsigned long           events = 0;
        u8                      irq_data;
@@ -141,7 +141,7 @@ static irqreturn_t rtc_irq(int irq, void *class_dev)
        if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
                events |= RTC_IRQF | RTC_UF;
 
-       rtc_update_irq(class_dev, 1, events);
+       rtc_update_irq(rtc, 1, events);
 
        return IRQ_HANDLED;
 }
@@ -289,34 +289,6 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
        u8 reg;
 
-       /* Much userspace code uses RTC_ALM_SET, thus "don't care" for
-        * day/month/year specifies alarms up to 24 hours in the future.
-        * So we need to handle that ... but let's ignore the "don't care"
-        * values for hours/minutes/seconds.
-        */
-       if (alm->time.tm_mday <= 0
-                       && alm->time.tm_mon < 0
-                       && alm->time.tm_year < 0) {
-               struct rtc_time tm;
-               unsigned long now, then;
-
-               omap_rtc_read_time(dev, &tm);
-               rtc_tm_to_time(&tm, &now);
-
-               alm->time.tm_mday = tm.tm_mday;
-               alm->time.tm_mon = tm.tm_mon;
-               alm->time.tm_year = tm.tm_year;
-               rtc_tm_to_time(&alm->time, &then);
-
-               /* sometimes the alarm wraps into tomorrow */
-               if (then < now) {
-                       rtc_time_to_tm(now + 24 * 60 * 60, &tm);
-                       alm->time.tm_mday = tm.tm_mday;
-                       alm->time.tm_mon = tm.tm_mon;
-                       alm->time.tm_year = tm.tm_year;
-               }
-       }
-
        if (tm2bcd(&alm->time) < 0)
                return -EINVAL;
 
@@ -399,7 +371,7 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev)
                goto fail;
        }
        platform_set_drvdata(pdev, rtc);
-       class_set_devdata(&rtc->class_dev, mem);
+       dev_set_devdata(&rtc->dev, mem);
 
        /* clear pending irqs, and set 1/second periodic,
         * which we'll use instead of update irqs
@@ -418,13 +390,13 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev)
 
        /* handle periodic and alarm irqs */
        if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
-                       rtc->class_dev.class_id, &rtc->class_dev)) {
+                       rtc->dev.bus_id, rtc)) {
                pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
                        pdev->name, omap_rtc_timer);
                goto fail0;
        }
        if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
-                       rtc->class_dev.class_id, &rtc->class_dev)) {
+                       rtc->dev.bus_id, rtc)) {
                pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
                        pdev->name, omap_rtc_alarm);
                goto fail1;
@@ -481,26 +453,17 @@ static int __devexit omap_rtc_remove(struct platform_device *pdev)
        free_irq(omap_rtc_timer, rtc);
        free_irq(omap_rtc_alarm, rtc);
 
-       release_resource(class_get_devdata(&rtc->class_dev));
+       release_resource(dev_get_devdata(&rtc->dev));
        rtc_device_unregister(rtc);
        return 0;
 }
 
 #ifdef CONFIG_PM
 
-static struct timespec rtc_delta;
 static u8 irqstat;
 
 static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct rtc_time rtc_tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-       omap_rtc_read_time(NULL, &rtc_tm);
-       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
-
-       save_time_delta(&rtc_delta, &time);
        irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
 
        /* FIXME the RTC alarm is not currently acting as a wakeup event
@@ -517,14 +480,6 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 
 static int omap_rtc_resume(struct platform_device *pdev)
 {
-       struct rtc_time rtc_tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-       omap_rtc_read_time(NULL, &rtc_tm);
-       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
-
-       restore_time_delta(&rtc_delta, &time);
        if (device_may_wakeup(&pdev->dev))
                disable_irq_wake(omap_rtc_alarm);
        else
index f13daa9fecaa1891c1201c6015eac4ebf40c6d3a..e4bf68ca96f7b2b237888f0a32b7f1b3fc86b449 100644 (file)
@@ -51,7 +51,7 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id)
 {
        struct rtc_device *rtc = dev_id;
 
-       rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+       rtc_update_irq(rtc, 1, RTC_AF);
 
        return IRQ_HANDLED;
 }
index 1bd624fc685c8c70722acdef390e30a86ef9318e..8d300e6d0d9e92eedc96a87cc2055cc4062d7180 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
-static struct class_device *rtc_dev = NULL;
-static DEFINE_MUTEX(rtc_lock);
+#include "rtc-core.h"
+
 
 static int rtc_proc_show(struct seq_file *seq, void *offset)
 {
        int err;
-       struct class_device *class_dev = seq->private;
-       const struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
+       struct rtc_device *rtc = seq->private;
+       const struct rtc_class_ops *ops = rtc->ops;
        struct rtc_wkalrm alrm;
        struct rtc_time tm;
 
-       err = rtc_read_time(class_dev, &tm);
+       err = rtc_read_time(rtc, &tm);
        if (err == 0) {
                seq_printf(seq,
                        "rtc_time\t: %02d:%02d:%02d\n"
@@ -36,7 +36,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
                        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
        }
 
-       err = rtc_read_alarm(class_dev, &alrm);
+       err = rtc_read_alarm(rtc, &alrm);
        if (err == 0) {
                seq_printf(seq, "alrm_time\t: ");
                if ((unsigned int)alrm.time.tm_hour <= 24)
@@ -74,19 +74,19 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
        seq_printf(seq, "24hr\t\t: yes\n");
 
        if (ops->proc)
-               ops->proc(class_dev->dev, seq);
+               ops->proc(rtc->dev.parent, seq);
 
        return 0;
 }
 
 static int rtc_proc_open(struct inode *inode, struct file *file)
 {
-       struct class_device *class_dev = PDE(inode)->data;
+       struct rtc_device *rtc = PDE(inode)->data;
 
        if (!try_module_get(THIS_MODULE))
                return -ENODEV;
 
-       return single_open(file, rtc_proc_show, class_dev);
+       return single_open(file, rtc_proc_show, rtc);
 }
 
 static int rtc_proc_release(struct inode *inode, struct file *file)
@@ -103,62 +103,22 @@ static const struct file_operations rtc_proc_fops = {
        .release        = rtc_proc_release,
 };
 
-static int rtc_proc_add_device(struct class_device *class_dev,
-                                       struct class_interface *class_intf)
+void rtc_proc_add_device(struct rtc_device *rtc)
 {
-       mutex_lock(&rtc_lock);
-       if (rtc_dev == NULL) {
+       if (rtc->id == 0) {
                struct proc_dir_entry *ent;
 
-               rtc_dev = class_dev;
-
                ent = create_proc_entry("driver/rtc", 0, NULL);
                if (ent) {
-                       struct rtc_device *rtc = to_rtc_device(class_dev);
-
                        ent->proc_fops = &rtc_proc_fops;
                        ent->owner = rtc->owner;
-                       ent->data = class_dev;
-
-                       dev_dbg(class_dev->dev, "rtc intf: proc\n");
+                       ent->data = rtc;
                }
-               else
-                       rtc_dev = NULL;
        }
-       mutex_unlock(&rtc_lock);
-
-       return 0;
 }
 
-static void rtc_proc_remove_device(struct class_device *class_dev,
-                                       struct class_interface *class_intf)
+void rtc_proc_del_device(struct rtc_device *rtc)
 {
-       mutex_lock(&rtc_lock);
-       if (rtc_dev == class_dev) {
+       if (rtc->id == 0)
                remove_proc_entry("driver/rtc", NULL);
-               rtc_dev = NULL;
-       }
-       mutex_unlock(&rtc_lock);
-}
-
-static struct class_interface rtc_proc_interface = {
-       .add = &rtc_proc_add_device,
-       .remove = &rtc_proc_remove_device,
-};
-
-static int __init rtc_proc_init(void)
-{
-       return rtc_interface_register(&rtc_proc_interface);
 }
-
-static void __exit rtc_proc_exit(void)
-{
-       class_interface_unregister(&rtc_proc_interface);
-}
-
-subsys_initcall(rtc_proc_init);
-module_exit(rtc_proc_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("RTC class proc interface");
-MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
new file mode 100644 (file)
index 0000000..9d6de37
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Ricoh RS5C313 RTC device/driver
+ *  Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ *  2005-09-19 modifed by kogiidena
+ *
+ * Based on the old drivers/char/rs5c313_rtc.c  by:
+ *  Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ *
+ * Based on code written by Paul Gortmaker.
+ *  Copyright (C) 1996 Paul Gortmaker
+ *
+ * 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.
+ *
+ * Based on other minimal char device drivers, like Alan's
+ * watchdog, Ted's random, etc. etc.
+ *
+ *     1.07    Paul Gortmaker.
+ *     1.08    Miquel van Smoorenburg: disallow certain things on the
+ *             DEC Alpha as the CMOS clock is also used for other things.
+ *     1.09    Nikita Schmidt: epoch support and some Alpha cleanup.
+ *     1.09a   Pete Zaitcev: Sun SPARC
+ *     1.09b   Jeff Garzik: Modularize, init cleanup
+ *     1.09c   Jeff Garzik: SMP cleanup
+ *     1.10    Paul Barton-Davis: add support for async I/O
+ *     1.10a   Andrea Arcangeli: Alpha updates
+ *     1.10b   Andrew Morton: SMP lock fix
+ *     1.10c   Cesar Barros: SMP locking fixes and cleanup
+ *     1.10d   Paul Gortmaker: delete paranoia check in rtc_exit
+ *     1.10e   Maciej W. Rozycki: Handle DECstation's year weirdness.
+ *      1.11    Takashi Iwai: Kernel access functions
+ *                           rtc_register/rtc_unregister/rtc_control
+ *      1.11a   Daniele Bellucci: Audit create_proc_read_entry in rtc_init
+ *     1.12    Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
+ *             CONFIG_HPET_EMULATE_RTC
+ *     1.13    Nobuhiro Iwamatsu: Updata driver.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "rs5c313"
+#define DRV_VERSION    "1.13"
+
+#ifdef CONFIG_SH_LANDISK
+/*****************************************************/
+/* LANDISK dependence part of RS5C313                */
+/*****************************************************/
+
+#define SCSMR1         0xFFE00000
+#define SCSCR1         0xFFE00008
+#define SCSMR1_CA      0x80
+#define SCSCR1_CKE     0x03
+#define SCSPTR1                0xFFE0001C
+#define SCSPTR1_EIO    0x80
+#define SCSPTR1_SPB1IO 0x08
+#define SCSPTR1_SPB1DT 0x04
+#define SCSPTR1_SPB0IO 0x02
+#define SCSPTR1_SPB0DT 0x01
+
+#define SDA_OEN                SCSPTR1_SPB1IO
+#define SDA            SCSPTR1_SPB1DT
+#define SCL_OEN                SCSPTR1_SPB0IO
+#define SCL            SCSPTR1_SPB0DT
+
+/* RICOH RS5C313 CE port */
+#define RS5C313_CE     0xB0000003
+
+/* RICOH RS5C313 CE port bit */
+#define RS5C313_CE_RTCCE       0x02
+
+/* SCSPTR1 data */
+unsigned char scsptr1_data;
+
+#define RS5C313_CEENABLE    ctrl_outb(RS5C313_CE_RTCCE, RS5C313_CE);
+#define RS5C313_CEDISABLE   ctrl_outb(0x00, RS5C313_CE)
+#define RS5C313_MISCOP      ctrl_outb(0x02, 0xB0000008)
+
+static void rs5c313_init_port(void)
+{
+       /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */
+       ctrl_outb(ctrl_inb(SCSMR1) & ~SCSMR1_CA, SCSMR1);
+       ctrl_outb(ctrl_inb(SCSCR1) & ~SCSCR1_CKE, SCSCR1);
+
+       /* And Initialize SCL for RS5C313 clock */
+       scsptr1_data = ctrl_inb(SCSPTR1) | SCL; /* SCL:H */
+       ctrl_outb(scsptr1_data, SCSPTR1);
+       scsptr1_data = ctrl_inb(SCSPTR1) | SCL_OEN;     /* SCL output enable */
+       ctrl_outb(scsptr1_data, SCSPTR1);
+       RS5C313_CEDISABLE;      /* CE:L */
+}
+
+static void rs5c313_write_data(unsigned char data)
+{
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               /* SDA:Write Data */
+               scsptr1_data = (scsptr1_data & ~SDA) |
+                               ((((0x80 >> i) & data) >> (7 - i)) << 2);
+               ctrl_outb(scsptr1_data, SCSPTR1);
+               if (i == 0) {
+                       scsptr1_data |= SDA_OEN;        /* SDA:output enable */
+                       ctrl_outb(scsptr1_data, SCSPTR1);
+               }
+               ndelay(700);
+               scsptr1_data &= ~SCL;   /* SCL:L */
+               ctrl_outb(scsptr1_data, SCSPTR1);
+               ndelay(700);
+               scsptr1_data |= SCL;    /* SCL:H */
+               ctrl_outb(scsptr1_data, SCSPTR1);
+       }
+
+       scsptr1_data &= ~SDA_OEN;       /* SDA:output disable */
+       ctrl_outb(scsptr1_data, SCSPTR1);
+}
+
+static unsigned char rs5c313_read_data(void)
+{
+       int i;
+       unsigned char data;
+
+       for (i = 0; i < 8; i++) {
+               ndelay(700);
+               /* SDA:Read Data */
+               data |= ((ctrl_inb(SCSPTR1) & SDA) >> 2) << (7 - i);
+               scsptr1_data &= ~SCL;   /* SCL:L */
+               ctrl_outb(scsptr1_data, SCSPTR1);
+               ndelay(700);
+               scsptr1_data |= SCL;    /* SCL:H */
+               ctrl_outb(scsptr1_data, SCSPTR1);
+       }
+       return data & 0x0F;
+}
+
+#endif /* CONFIG_SH_LANDISK */
+
+/*****************************************************/
+/* machine independence part of RS5C313              */
+/*****************************************************/
+
+/* RICOH RS5C313 address */
+#define RS5C313_ADDR_SEC       0x00
+#define RS5C313_ADDR_SEC10     0x01
+#define RS5C313_ADDR_MIN       0x02
+#define RS5C313_ADDR_MIN10     0x03
+#define RS5C313_ADDR_HOUR      0x04
+#define RS5C313_ADDR_HOUR10    0x05
+#define RS5C313_ADDR_WEEK      0x06
+#define RS5C313_ADDR_INTINTVREG        0x07
+#define RS5C313_ADDR_DAY       0x08
+#define RS5C313_ADDR_DAY10     0x09
+#define RS5C313_ADDR_MON       0x0A
+#define RS5C313_ADDR_MON10     0x0B
+#define RS5C313_ADDR_YEAR      0x0C
+#define RS5C313_ADDR_YEAR10    0x0D
+#define RS5C313_ADDR_CNTREG    0x0E
+#define RS5C313_ADDR_TESTREG   0x0F
+
+/* RICOH RS5C313 control register */
+#define RS5C313_CNTREG_ADJ_BSY 0x01
+#define RS5C313_CNTREG_WTEN_XSTP       0x02
+#define RS5C313_CNTREG_12_24   0x04
+#define RS5C313_CNTREG_CTFG    0x08
+
+/* RICOH RS5C313 test register */
+#define RS5C313_TESTREG_TEST   0x01
+
+/* RICOH RS5C313 control bit */
+#define RS5C313_CNTBIT_READ    0x40
+#define RS5C313_CNTBIT_AD      0x20
+#define RS5C313_CNTBIT_DT      0x10
+
+static unsigned char rs5c313_read_reg(unsigned char addr)
+{
+
+       rs5c313_write_data(addr | RS5C313_CNTBIT_READ | RS5C313_CNTBIT_AD);
+       return rs5c313_read_data();
+}
+
+static void rs5c313_write_reg(unsigned char addr, unsigned char data)
+{
+       data &= 0x0f;
+       rs5c313_write_data(addr | RS5C313_CNTBIT_AD);
+       rs5c313_write_data(data | RS5C313_CNTBIT_DT);
+       return;
+}
+
+static inline unsigned char rs5c313_read_cntreg(unsigned char addr)
+{
+       return rs5c313_read_reg(RS5C313_ADDR_CNTREG);
+}
+
+static inline void rs5c313_write_cntreg(unsigned char data)
+{
+       rs5c313_write_reg(RS5C313_ADDR_CNTREG, data);
+}
+
+static inline void rs5c313_write_intintvreg(unsigned char data)
+{
+       rs5c313_write_reg(RS5C313_ADDR_INTINTVREG, data);
+}
+
+static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       int data;
+
+       while (1) {
+               RS5C313_CEENABLE;       /* CE:H */
+
+               /* Initialize control reg. 24 hour */
+               rs5c313_write_cntreg(0x04);
+
+               if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
+                       break;
+
+               RS5C313_CEDISABLE;
+               ndelay(700);    /* CE:L */
+
+       }
+
+       data = rs5c313_read_reg(RS5C313_ADDR_SEC);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4);
+       tm->tm_sec = BCD2BIN(data);
+
+       data = rs5c313_read_reg(RS5C313_ADDR_MIN);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4);
+       tm->tm_min = BCD2BIN(data);
+
+       data = rs5c313_read_reg(RS5C313_ADDR_HOUR);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4);
+       tm->tm_hour = BCD2BIN(data);
+
+       data = rs5c313_read_reg(RS5C313_ADDR_DAY);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4);
+       tm->tm_mday = BCD2BIN(data);
+
+       data = rs5c313_read_reg(RS5C313_ADDR_MON);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4);
+       tm->tm_mon = BCD2BIN(data) - 1;
+
+       data = rs5c313_read_reg(RS5C313_ADDR_YEAR);
+       data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4);
+       tm->tm_year = BCD2BIN(data);
+
+       if (tm->tm_year < 70)
+               tm->tm_year += 100;
+
+       data = rs5c313_read_reg(RS5C313_ADDR_WEEK);
+       tm->tm_wday = BCD2BIN(data);
+
+       RS5C313_CEDISABLE;
+       ndelay(700);            /* CE:L */
+
+       return 0;
+}
+
+static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       int data;
+
+       /* busy check. */
+       while (1) {
+               RS5C313_CEENABLE;       /* CE:H */
+
+               /* Initiatlize control reg. 24 hour */
+               rs5c313_write_cntreg(0x04);
+
+               if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
+                       break;
+               RS5C313_MISCOP;
+               RS5C313_CEDISABLE;
+               ndelay(700);    /* CE:L */
+       }
+
+       data = BIN2BCD(tm->tm_sec);
+       rs5c313_write_reg(RS5C313_ADDR_SEC, data);
+       rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4));
+
+       data = BIN2BCD(tm->tm_min);
+       rs5c313_write_reg(RS5C313_ADDR_MIN, data );
+       rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4));
+
+       data = BIN2BCD(tm->tm_hour);
+       rs5c313_write_reg(RS5C313_ADDR_HOUR, data);
+       rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4));
+
+       data = BIN2BCD(tm->tm_mday);
+       rs5c313_write_reg(RS5C313_ADDR_DAY, data);
+       rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4));
+
+       data = BIN2BCD(tm->tm_mon + 1);
+       rs5c313_write_reg(RS5C313_ADDR_MON, data);
+       rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4));
+
+       data = BIN2BCD(tm->tm_year % 100);
+       rs5c313_write_reg(RS5C313_ADDR_YEAR, data);
+       rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4));
+
+       data = BIN2BCD(tm->tm_wday);
+       rs5c313_write_reg(RS5C313_ADDR_WEEK, data);
+
+       RS5C313_CEDISABLE;      /* CE:H */
+       ndelay(700);
+
+       return 0;
+}
+
+static void rs5c313_check_xstp_bit(void)
+{
+       struct rtc_time tm;
+
+       RS5C313_CEENABLE;       /* CE:H */
+       if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) {
+               /* INT interval reg. OFF */
+               rs5c313_write_intintvreg(0x00);
+               /* Initialize control reg. 24 hour & adjust */
+               rs5c313_write_cntreg(0x07);
+
+               /* busy check. */
+               while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)
+                       RS5C313_MISCOP;
+
+               memset(&tm, 0, sizeof(struct rtc_time));
+               tm.tm_mday      = 1;
+               tm.tm_mon       = 1;
+
+               rs5c313_rtc_set_time(NULL, &tm);
+               printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to "
+                               "1 Jan 2000\n");
+       }
+       RS5C313_CEDISABLE;
+       ndelay(700);            /* CE:L */
+}
+
+static const struct rtc_class_ops rs5c313_rtc_ops = {
+       .read_time = rs5c313_rtc_read_time,
+       .set_time = rs5c313_rtc_set_time,
+};
+
+static int rs5c313_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc = rtc_device_register("rs5c313", &pdev->dev,
+                               &rs5c313_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       platform_set_drvdata(pdev, rtc);
+
+       return err;
+}
+
+static int __devexit rs5c313_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_device *rtc = platform_get_drvdata( pdev );
+
+       rtc_device_unregister(rtc);
+
+       return 0;
+}
+
+static struct platform_driver rs5c313_rtc_platform_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = rs5c313_rtc_probe,
+       .remove = __devexit_p( rs5c313_rtc_remove ),
+};
+
+static int __init rs5c313_rtc_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&rs5c313_rtc_platform_driver);
+       if (err)
+               return err;
+
+       rs5c313_init_port();
+       rs5c313_check_xstp_bit();
+
+       return 0;
+}
+
+static void __exit rs5c313_rtc_exit(void)
+{
+       platform_driver_unregister( &rs5c313_rtc_platform_driver );
+}
+
+module_init(rs5c313_rtc_init);
+module_exit(rs5c313_rtc_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>");
+MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver");
+MODULE_LICENSE("GPL");
index 9a79a24a74874189deab5885af6ea98c6de50746..54b6130534686586aa817c449c5c02ca418b6e08 100644 (file)
@@ -50,7 +50,7 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
 {
        struct rtc_device *rdev = id;
 
-       rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF);
+       rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
        return IRQ_HANDLED;
 }
 
@@ -58,7 +58,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
 {
        struct rtc_device *rdev = id;
 
-       rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF);
+       rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF);
        return IRQ_HANDLED;
 }
 
@@ -548,37 +548,15 @@ static int ticnt_save;
 
 static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct rtc_time tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-
        /* save TICNT for anyone using periodic interrupts */
-
        ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
-
-       /* calculate time delta for suspend */
-
-       s3c_rtc_gettime(&pdev->dev, &tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       save_time_delta(&s3c_rtc_delta, &time);
        s3c_rtc_enable(pdev, 0);
-
        return 0;
 }
 
 static int s3c_rtc_resume(struct platform_device *pdev)
 {
-       struct rtc_time tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-
        s3c_rtc_enable(pdev, 1);
-       s3c_rtc_gettime(&pdev->dev, &tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       restore_time_delta(&s3c_rtc_delta, &time);
-
        writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
        return 0;
 }
index 677bae820dc3f681ff8cb3c115699033d519defc..0918b787c4dd033671a0bd1902594b1ae858b653 100644 (file)
@@ -93,7 +93,7 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
        if (rtsr & RTSR_HZ)
                events |= RTC_UF | RTC_IRQF;
 
-       rtc_update_irq(&rtc->class_dev, 1, events);
+       rtc_update_irq(rtc, 1, events);
 
        if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
                rtc_update_alarm(&rtc_alarm);
@@ -119,7 +119,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
         */
        OSSR = OSSR_M1; /* clear match on timer1 */
 
-       rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF);
+       rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
 
        if (rtc_timer1_count == 1)
                rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
index 198b9f22fbff5ca93748e2c06b4f04d815ec94b5..e0f91dfce0f56bcb8f340058d208557e613a44dd 100644 (file)
@@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
 
        writeb(tmp, rtc->regbase + RCR1);
 
-       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+       rtc_update_irq(rtc->rtc_dev, 1, events);
 
        spin_unlock(&rtc->lock);
 
@@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
 
                rtc->rearm_aie = 1;
 
-               rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+               rtc_update_irq(rtc->rtc_dev, 1, events);
        }
 
        spin_unlock(&rtc->lock);
@@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
 
        spin_lock(&rtc->lock);
 
-       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF);
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
 
        spin_unlock(&rtc->lock);
 
@@ -341,7 +341,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
                tm->tm_sec--;
 #endif
 
-       dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+       dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
                __FUNCTION__,
                tm->tm_sec, tm->tm_min, tm->tm_hour,
index 899ab8c514facbda5965be87bff5422b8aa0ebf0..69df94b4484169d0a61b5c08f32f3e0e6133f716 100644 (file)
 #include <linux/module.h>
 #include <linux/rtc.h>
 
+#include "rtc-core.h"
+
+
 /* device attributes */
 
-static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf)
+static ssize_t
+rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
        return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
 }
-static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL);
 
-static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf)
+static ssize_t
+rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
        ssize_t retval;
        struct rtc_time tm;
 
-       retval = rtc_read_time(dev, &tm);
+       retval = rtc_read_time(to_rtc_device(dev), &tm);
        if (retval == 0) {
                retval = sprintf(buf, "%04d-%02d-%02d\n",
                        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
@@ -33,14 +39,15 @@ static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf)
 
        return retval;
 }
-static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL);
 
-static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf)
+static ssize_t
+rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
        ssize_t retval;
        struct rtc_time tm;
 
-       retval = rtc_read_time(dev, &tm);
+       retval = rtc_read_time(to_rtc_device(dev), &tm);
        if (retval == 0) {
                retval = sprintf(buf, "%02d:%02d:%02d\n",
                        tm.tm_hour, tm.tm_min, tm.tm_sec);
@@ -48,14 +55,15 @@ static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf)
 
        return retval;
 }
-static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL);
 
-static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf)
+static ssize_t
+rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
        ssize_t retval;
        struct rtc_time tm;
 
-       retval = rtc_read_time(dev, &tm);
+       retval = rtc_read_time(to_rtc_device(dev), &tm);
        if (retval == 0) {
                unsigned long time;
                rtc_tm_to_time(&tm, &time);
@@ -64,23 +72,18 @@ static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf)
 
        return retval;
 }
-static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL);
-
-static struct attribute *rtc_attrs[] = {
-       &class_device_attr_name.attr,
-       &class_device_attr_date.attr,
-       &class_device_attr_time.attr,
-       &class_device_attr_since_epoch.attr,
-       NULL,
-};
 
-static struct attribute_group rtc_attr_group = {
-       .attrs = rtc_attrs,
+static struct device_attribute rtc_attrs[] = {
+       __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
+       __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
+       __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
+       __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
+       { },
 };
 
-
 static ssize_t
-rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
+rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
        ssize_t retval;
        unsigned long alarm;
@@ -94,7 +97,7 @@ rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
         * REVISIT maybe we should require RTC implementations to
         * disable the RTC alarm after it triggers, for uniformity.
         */
-       retval = rtc_read_alarm(dev, &alm);
+       retval = rtc_read_alarm(to_rtc_device(dev), &alm);
        if (retval == 0 && alm.enabled) {
                rtc_tm_to_time(&alm.time, &alarm);
                retval = sprintf(buf, "%lu\n", alarm);
@@ -104,16 +107,18 @@ rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
 }
 
 static ssize_t
-rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
+rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t n)
 {
        ssize_t retval;
        unsigned long now, alarm;
        struct rtc_wkalrm alm;
+       struct rtc_device *rtc = to_rtc_device(dev);
 
        /* Only request alarms that trigger in the future.  Disable them
         * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
         */
-       retval = rtc_read_time(dev, &alm.time);
+       retval = rtc_read_time(rtc, &alm.time);
        if (retval < 0)
                return retval;
        rtc_tm_to_time(&alm.time, &now);
@@ -124,7 +129,7 @@ rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
                 * entirely prevent that here, without even the minimal
                 * locking from the /dev/rtcN api.
                 */
-               retval = rtc_read_alarm(dev, &alm);
+               retval = rtc_read_alarm(rtc, &alm);
                if (retval < 0)
                        return retval;
                if (alm.enabled)
@@ -141,10 +146,10 @@ rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
        }
        rtc_time_to_tm(alarm, &alm.time);
 
-       retval = rtc_set_alarm(dev, &alm);
+       retval = rtc_set_alarm(rtc, &alm);
        return (retval < 0) ? retval : n;
 }
-static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
                rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
 
 
@@ -153,71 +158,37 @@ static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
  * suspend-to-disk.  So: no attribute unless that side effect is possible.
  * (Userspace may disable that mechanism later.)
  */
-static inline int rtc_does_wakealarm(struct class_device *class_dev)
+static inline int rtc_does_wakealarm(struct rtc_device *rtc)
 {
-       struct rtc_device *rtc;
-
-       if (!device_can_wakeup(class_dev->dev))
+       if (!device_can_wakeup(rtc->dev.parent))
                return 0;
-       rtc = to_rtc_device(class_dev);
        return rtc->ops->set_alarm != NULL;
 }
 
 
-static int rtc_sysfs_add_device(struct class_device *class_dev,
-                                       struct class_interface *class_intf)
+void rtc_sysfs_add_device(struct rtc_device *rtc)
 {
        int err;
 
-       dev_dbg(class_dev->dev, "rtc intf: sysfs\n");
+       /* not all RTCs support both alarms and wakeup */
+       if (!rtc_does_wakealarm(rtc))
+               return;
 
-       err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
+       err = device_create_file(&rtc->dev, &dev_attr_wakealarm);
        if (err)
-               dev_err(class_dev->dev, "failed to create %s\n",
-                               "sysfs attributes");
-       else if (rtc_does_wakealarm(class_dev)) {
-               /* not all RTCs support both alarms and wakeup */
-               err = class_device_create_file(class_dev,
-                                       &class_device_attr_wakealarm);
-               if (err) {
-                       dev_err(class_dev->dev, "failed to create %s\n",
-                                       "alarm attribute");
-                       sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
-               }
-       }
-
-       return err;
+               dev_err(rtc->dev.parent, "failed to create "
+                               "alarm attribute, %d",
+                               err);
 }
 
-static void rtc_sysfs_remove_device(struct class_device *class_dev,
-                               struct class_interface *class_intf)
+void rtc_sysfs_del_device(struct rtc_device *rtc)
 {
-       if (rtc_does_wakealarm(class_dev))
-               class_device_remove_file(class_dev,
-                               &class_device_attr_wakealarm);
-       sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+       /* REVISIT did we add it successfully? */
+       if (rtc_does_wakealarm(rtc))
+               device_remove_file(&rtc->dev, &dev_attr_wakealarm);
 }
 
-/* interface registration */
-
-static struct class_interface rtc_sysfs_interface = {
-       .add = &rtc_sysfs_add_device,
-       .remove = &rtc_sysfs_remove_device,
-};
-
-static int __init rtc_sysfs_init(void)
+void __init rtc_sysfs_init(struct class *rtc_class)
 {
-       return rtc_interface_register(&rtc_sysfs_interface);
+       rtc_class->dev_attrs = rtc_attrs;
 }
-
-static void __exit rtc_sysfs_exit(void)
-{
-       class_interface_unregister(&rtc_sysfs_interface);
-}
-
-subsys_initcall(rtc_sysfs_init);
-module_exit(rtc_sysfs_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("RTC class sysfs interface");
-MODULE_LICENSE("GPL");
index f50a1b8e160706982f91c5a051abcc88f73d333e..254c9fce27dabf324c388859363f76614bdde2bb 100644 (file)
@@ -101,11 +101,11 @@ static ssize_t test_irq_store(struct device *dev,
        retval = count;
        local_irq_disable();
        if (strncmp(buf, "tick", 4) == 0)
-               rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF);
+               rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF);
        else if (strncmp(buf, "alarm", 5) == 0)
-               rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF);
+               rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
        else if (strncmp(buf, "update", 6) == 0)
-               rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF);
+               rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF);
        else
                retval = -EINVAL;
        local_irq_enable();
index e40322b71938100a2dc5578c010ba7c523344cb3..af7596ef29e2d837f2c9c8ea6b6d4fc7b7d37102 100644 (file)
@@ -97,6 +97,7 @@ static DEFINE_SPINLOCK(rtc_lock);
 static char rtc_name[] = "RTC";
 static unsigned long periodic_frequency;
 static unsigned long periodic_count;
+static unsigned int alarm_enabled;
 
 struct resource rtc_resource[2] = {
        {       .name   = rtc_name,
@@ -188,6 +189,7 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        low = rtc1_read(ECMPLREG);
        mid = rtc1_read(ECMPMREG);
        high = rtc1_read(ECMPHREG);
+       wkalrm->enabled = alarm_enabled;
 
        spin_unlock_irq(&rtc_lock);
 
@@ -206,10 +208,18 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 
        spin_lock_irq(&rtc_lock);
 
+       if (alarm_enabled)
+               disable_irq(ELAPSEDTIME_IRQ);
+
        rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
        rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
        rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
 
+       if (wkalrm->enabled)
+               enable_irq(ELAPSEDTIME_IRQ);
+
+       alarm_enabled = wkalrm->enabled;
+
        spin_unlock_irq(&rtc_lock);
 
        return 0;
@@ -221,10 +231,24 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
 
        switch (cmd) {
        case RTC_AIE_ON:
-               enable_irq(ELAPSEDTIME_IRQ);
+               spin_lock_irq(&rtc_lock);
+
+               if (!alarm_enabled) {
+                       enable_irq(ELAPSEDTIME_IRQ);
+                       alarm_enabled = 1;
+               }
+
+               spin_unlock_irq(&rtc_lock);
                break;
        case RTC_AIE_OFF:
-               disable_irq(ELAPSEDTIME_IRQ);
+               spin_lock_irq(&rtc_lock);
+
+               if (alarm_enabled) {
+                       disable_irq(ELAPSEDTIME_IRQ);
+                       alarm_enabled = 0;
+               }
+
+               spin_unlock_irq(&rtc_lock);
                break;
        case RTC_PIE_ON:
                enable_irq(RTCLONG1_IRQ);
@@ -275,7 +299,7 @@ static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id)
 
        rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
 
-       rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+       rtc_update_irq(rtc, 1, RTC_AF);
 
        return IRQ_HANDLED;
 }
@@ -291,7 +315,7 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
        rtc1_write(RTCL1LREG, count);
        rtc1_write(RTCL1HREG, count >> 16);
 
-       rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
+       rtc_update_irq(rtc, 1, RTC_PF);
 
        return IRQ_HANDLED;
 }
index bbd5b8b66f420b9288a84a21ba89f622457afee3..d6b06ab81188884a1a63729653366a7ab4ee7b8d 100644 (file)
@@ -23,7 +23,7 @@
 
 /*
  * The room for the SCCB (only for writing) is not equal to a pages size
- * (as it is specified as the maximum size in the the SCLP documentation)
+ * (as it is specified as the maximum size in the SCLP documentation)
  * because of the additional data structure described above.
  */
 #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
index cba64e4cfcd470492cdf9235c0a86ac2f1ba30a2..f770018fe1d5c02c691686b32115b59bf1d6472e 100644 (file)
@@ -996,18 +996,25 @@ __qdio_outbound_processing(struct qdio_q *q)
        if (qdio_has_outbound_q_moved(q))
                qdio_kick_outbound_handler(q);
 
-       if (q->is_iqdio_q) {
+       if (q->queue_type == QDIO_ZFCP_QFMT) {
+               if ((!q->hydra_gives_outbound_pcis) &&
+                   (!qdio_is_outbound_q_done(q)))
+                       qdio_mark_q(q);
+       }
+       else if (((!q->is_iqdio_q) && (!q->is_pci_out)) ||
+                (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) {
                /* 
-                * for asynchronous queues, we better check, if the sent
-                * buffer is already switched from PRIMED to EMPTY.
+                * make sure buffer switch from PRIMED to EMPTY is noticed
+                * and outbound_handler is called
                 */
-               if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) &&
-                   !qdio_is_outbound_q_done(q))
-                       qdio_mark_q(q);
-
-       } else if (!q->hydra_gives_outbound_pcis)
-               if (!qdio_is_outbound_q_done(q))
-                       qdio_mark_q(q);
+               if (qdio_is_outbound_q_done(q)) {
+                       del_timer(&q->timer);
+               } else {
+                       if (!timer_pending(&q->timer))
+                               mod_timer(&q->timer, jiffies +
+                                         QDIO_FORCE_CHECK_TIMEOUT);
+               }
+       }
 
        qdio_release_q(q);
 }
@@ -1826,6 +1833,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
                        q->queue_type = QDIO_IQDIO_QFMT_ASYNCH;
                q->int_parm=int_parm;
                q->is_input_q=0;
+               q->is_pci_out = 0;
                q->schid = irq_ptr->schid;
                q->cdev = cdev;
                q->irq_ptr = irq_ptr;
@@ -1838,6 +1846,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
                q->tasklet.data=(unsigned long)q;
                q->tasklet.func=(void(*)(unsigned long))
                        &qdio_outbound_processing;
+               q->timer.function=(void(*)(unsigned long))
+                       &qdio_outbound_processing;
+               q->timer.data = (long)q;
+               init_timer(&q->timer);
 
                atomic_set(&q->busy_siga_counter,0);
                q->timing.busy_start=0;
@@ -2635,6 +2647,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
 
        for (i=0;i<irq_ptr->no_output_qs;i++) {
                tasklet_kill(&irq_ptr->output_qs[i]->tasklet);
+               del_timer(&irq_ptr->output_qs[i]->timer);
                wait_event_interruptible_timeout(cdev->private->wait_q,
                                                 !atomic_read(&irq_ptr->
                                                              output_qs[i]->
@@ -3458,6 +3471,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                qdio_perf_stat_inc(&perf_stats.outbound_cnt);
                return;
        }
+       if (callflags & QDIO_FLAG_PCI_OUT)
+               q->is_pci_out = 1;
+       else
+               q->is_pci_out = 0;
        if (q->is_iqdio_q) {
                /* one siga for every sbal */
                while (count--)
index 2895392eaae4392a5d9be226ca18c1a267367d50..6d7aad18f6f0132fa24d5b10b9c5d9f88638347a 100644 (file)
@@ -60,6 +60,7 @@
 #define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10)
 #define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
 #define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
+#define QDIO_FORCE_CHECK_TIMEOUT (10*HZ)
 
 enum qdio_irq_states {
        QDIO_IRQ_STATE_INACTIVE,
@@ -511,8 +512,8 @@ struct qdio_q {
 
        void *irq_ptr;
 
-#ifdef QDIO_USE_TIMERS_FOR_POLLING
        struct timer_list timer;
+#ifdef QDIO_USE_TIMERS_FOR_POLLING
        atomic_t timer_already_set;
        spinlock_t timer_lock;
 #else /* QDIO_USE_TIMERS_FOR_POLLING */
@@ -558,6 +559,7 @@ struct qdio_q {
        } timing;
        atomic_t busy_siga_counter;
         unsigned int queue_type;
+       unsigned int is_pci_out;
 
        /* leave this member at the end. won't be cleared in qdio_fill_qs */
        struct slib *slib; /* a page is allocated under this pointer,
index e10e85e85c842643a48cac9771b10671c38c6b99..c358764f3264b56a478b88dce21f6ae94cc96e82 100644 (file)
@@ -1862,12 +1862,14 @@ static void netiucv_remove_connection(struct iucv_connection *conn)
        write_lock_bh(&iucv_connection_rwlock);
        list_del_init(&conn->list);
        write_unlock_bh(&iucv_connection_rwlock);
+       fsm_deltimer(&conn->timer);
+       netiucv_purge_skb_queue(&conn->collect_queue);
        if (conn->path) {
                iucv_path_sever(conn->path, iucvMagic);
                kfree(conn->path);
                conn->path = NULL;
        }
-       fsm_deltimer(&conn->timer);
+       netiucv_purge_skb_queue(&conn->commit_queue);
        kfree_fsm(conn->fsm);
        kfree_skb(conn->rx_buff);
        kfree_skb(conn->tx_buff);
@@ -2115,7 +2117,6 @@ static void __exit netiucv_exit(void)
        while (!list_empty(&iucv_connection_list)) {
                cp = list_entry(iucv_connection_list.next,
                                struct iucv_connection, list);
-               list_del(&cp->list);
                ndev = cp->netdev;
                priv = netdev_priv(ndev);
                dev = priv->dev;
index dd7034fbfff89ec8b51fe12788dd35703291bfab..4640f32daae5832ed75e410a5bcc131bfc180098 100644 (file)
@@ -620,10 +620,10 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
 
 struct qeth_eddp_context *
 qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
-                        struct qeth_hdr *qhdr)
+                        struct qeth_hdr *qhdr, unsigned char sk_protocol)
 {
        QETH_DBF_TEXT(trace, 5, "creddpc");
-       switch (skb->sk->sk_protocol){
+       switch (sk_protocol) {
        case IPPROTO_TCP:
                return qeth_eddp_create_context_tcp(card, skb, qhdr);
        default:
index 103768d3bab2a4b2065b88558075831c8d2446e8..52910c9252c085c05cd3aa882f51cf72bb981107 100644 (file)
@@ -34,7 +34,8 @@ struct qeth_eddp_context_reference {
 };
 
 extern struct qeth_eddp_context *
-qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,struct qeth_hdr *);
+qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,
+                        struct qeth_hdr *, unsigned char);
 
 extern void
 qeth_eddp_put_context(struct qeth_eddp_context *);
index 6fd8870551d36ff9245975c994f1d904d983dd8e..0b96d49dd636bc55f6f8f8f360472ab9c18fede1 100644 (file)
@@ -1682,6 +1682,21 @@ qeth_put_reply(struct qeth_reply *reply)
                kfree(reply);
 }
 
+static void
+qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
+{
+       int rc;
+       int com;
+       char * ipa_name;
+
+       com = cmd->hdr.command;
+       rc  = cmd->hdr.return_code;
+       ipa_name = qeth_get_ipa_cmd_name(com);
+
+       PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
+                  QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
+}
+
 static struct qeth_ipa_cmd *
 qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
 {
@@ -1690,8 +1705,11 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
        QETH_DBF_TEXT(trace,5,"chkipad");
        if (IS_IPA(iob->data)){
                cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
-               if (IS_IPA_REPLY(cmd))
+               if (IS_IPA_REPLY(cmd)) {
+                       if (cmd->hdr.return_code)
+                               qeth_issue_ipa_msg(cmd, card);
                        return cmd;
+               }
                else {
                        switch (cmd->hdr.command) {
                        case IPA_CMD_STOPLAN:
@@ -2816,6 +2834,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
        struct qeth_qdio_out_buffer *buf;
        int rc;
        int i;
+       unsigned int qdio_flags;
 
        QETH_DBF_TEXT(trace, 6, "flushbuf");
 
@@ -2841,7 +2860,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
                        if (!atomic_read(&queue->set_pci_flags_count)){
                                /*
                                 * there's no outstanding PCI any more, so we
-                                * have to request a PCI to be sure the the PCI
+                                * have to request a PCI to be sure that the PCI
                                 * will wake at some time in the future then we
                                 * can flush packed buffers that might still be
                                 * hanging around, which can happen if no
@@ -2859,13 +2878,13 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
                queue->card->perf_stats.outbound_do_qdio_start_time =
                        qeth_get_micros();
        }
+       qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
        if (under_int)
-               rc = do_QDIO(CARD_DDEV(queue->card),
-                            QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT,
-                            queue->queue_no, index, count, NULL);
-       else
-               rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT,
-                            queue->queue_no, index, count, NULL);
+               qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
+       if (atomic_read(&queue->set_pci_flags_count))
+               qdio_flags |= QDIO_FLAG_PCI_OUT;
+       rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
+                    queue->queue_no, index, count, NULL);
        if (queue->card->options.performance_stats)
                queue->card->perf_stats.outbound_do_qdio_time +=
                        qeth_get_micros() -
@@ -4490,7 +4509,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                qeth_fill_header(card, hdr, new_skb, ipv, cast_type);
        }
        if (large_send == QETH_LARGE_SEND_EDDP) {
-               ctx = qeth_eddp_create_context(card, new_skb, hdr);
+               ctx = qeth_eddp_create_context(card, new_skb, hdr,
+                                              skb->sk->sk_protocol);
                if (ctx == NULL) {
                        __qeth_free_new_skb(skb, new_skb);
                        PRINT_WARN("could not create eddp context\n");
@@ -5948,9 +5968,6 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card,
        cmd = (struct qeth_ipa_cmd *) data;
        if (cmd->hdr.return_code) {
                QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
-               PRINT_WARN("Error in registering MAC address on " \
-                          "device %s: x%x\n", CARD_BUS_ID(card),
-                          cmd->hdr.return_code);
                card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
                cmd->hdr.return_code = -EIO;
        } else {
@@ -5985,9 +6002,6 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card,
        QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
        cmd = (struct qeth_ipa_cmd *) data;
        if (cmd->hdr.return_code) {
-               PRINT_WARN("Error in deregistering MAC address on " \
-                          "device %s: x%x\n", CARD_BUS_ID(card),
-                          cmd->hdr.return_code);
                QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
                cmd->hdr.return_code = -EIO;
                return 0;
@@ -6651,7 +6665,7 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
        QETH_DBF_TEXT(trace,4,"chgmaccb");
 
        cmd = (struct qeth_ipa_cmd *) data;
-       if (!card->options.layer2 || card->info.guestlan ||
+       if (!card->options.layer2 ||
            !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
                memcpy(card->dev->dev_addr,
                       &cmd->data.setadapterparms.data.change_addr.addr,
@@ -8497,6 +8511,7 @@ __qeth_reboot_event_card(struct device *dev, void *data)
        card = (struct qeth_card *) dev->driver_data;
        qeth_clear_ip_list(card, 0, 0);
        qeth_qdio_clear_card(card, 0);
+       qeth_clear_qdio_buffers(card);
        return 0;
 }
 
index 77c83209d70ee697da2abc2ad3c4c73a042aeaaf..f54fdfdbf06fcf300f8e812b67451fcdf09055f0 100644 (file)
@@ -157,12 +157,113 @@ unsigned char READ_CCW[]={
 };
 
 
+struct ipa_rc_msg {
+       enum qeth_ipa_return_codes rc;
+       char *msg;
+};
 
+struct ipa_rc_msg qeth_ipa_rc_msg[] = {
+       {IPA_RC_SUCCESS,                "success"},
+       {IPA_RC_NOTSUPP,                "Command not supported"},
+       {IPA_RC_IP_TABLE_FULL,          "Add Addr IP Table Full - ipv6"},
+       {IPA_RC_UNKNOWN_ERROR,          "IPA command failed - reason unknown"},
+       {IPA_RC_UNSUPPORTED_COMMAND,    "Command not supported"},
+       {IPA_RC_DUP_IPV6_REMOTE,"ipv6 address already registered remote"},
+       {IPA_RC_DUP_IPV6_HOME,          "ipv6 address already registered"},
+       {IPA_RC_UNREGISTERED_ADDR,      "Address not registered"},
+       {IPA_RC_NO_ID_AVAILABLE,        "No identifiers available"},
+       {IPA_RC_ID_NOT_FOUND,           "Identifier not found"},
+       {IPA_RC_INVALID_IP_VERSION,     "IP version incorrect"},
+       {IPA_RC_LAN_FRAME_MISMATCH,     "LAN and frame mismatch"},
+       {IPA_RC_L2_UNSUPPORTED_CMD,     "Unsupported layer 2 command"},
+       {IPA_RC_L2_DUP_MAC,             "Duplicate MAC address"},
+       {IPA_RC_L2_ADDR_TABLE_FULL,     "Layer2 address table full"},
+       {IPA_RC_L2_DUP_LAYER3_MAC,      "Duplicate with layer 3 MAC"},
+       {IPA_RC_L2_GMAC_NOT_FOUND,      "GMAC not found"},
+       {IPA_RC_L2_MAC_NOT_FOUND,       "L2 mac address not found"},
+       {IPA_RC_L2_INVALID_VLAN_ID,     "L2 invalid vlan id"},
+       {IPA_RC_L2_DUP_VLAN_ID,         "L2 duplicate vlan id"},
+       {IPA_RC_L2_VLAN_ID_NOT_FOUND,   "L2 vlan id not found"},
+       {IPA_RC_DATA_MISMATCH,          "Data field mismatch (v4/v6 mixed)"},
+       {IPA_RC_INVALID_MTU_SIZE,       "Invalid MTU size"},
+       {IPA_RC_INVALID_LANTYPE,        "Invalid LAN type"},
+       {IPA_RC_INVALID_LANNUM,         "Invalid LAN num"},
+       {IPA_RC_DUPLICATE_IP_ADDRESS,   "Address already registered"},
+       {IPA_RC_IP_ADDR_TABLE_FULL,     "IP address table full"},
+       {IPA_RC_LAN_PORT_STATE_ERROR,   "LAN port state error"},
+       {IPA_RC_SETIP_NO_STARTLAN,      "Setip no startlan received"},
+       {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
+       {IPA_RC_IP_ADDR_ALREADY_USED,   "IP address already in use on LAN"},
+       {IPA_RC_MULTICAST_FULL,         "No task available, multicast full"},
+       {IPA_RC_SETIP_INVALID_VERSION,  "SETIP invalid IP version"},
+       {IPA_RC_UNSUPPORTED_SUBCMD,     "Unsupported assist subcommand"},
+       {IPA_RC_ARP_ASSIST_NO_ENABLE,   "Only partial success, no enable"},
+       {IPA_RC_PRIMARY_ALREADY_DEFINED,"Primary already defined"},
+       {IPA_RC_SECOND_ALREADY_DEFINED, "Secondary already defined"},
+       {IPA_RC_INVALID_SETRTG_INDICATOR,"Invalid SETRTG indicator"},
+       {IPA_RC_MC_ADDR_ALREADY_DEFINED,"Multicast address already defined"},
+       {IPA_RC_LAN_OFFLINE,            "STRTLAN_LAN_DISABLED - LAN offline"},
+       {IPA_RC_INVALID_IP_VERSION2,    "Invalid IP version"},
+       {IPA_RC_FFFF,                   "Unknown Error"}
+};
 
 
 
+char *
+qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
+{
+       int x = 0;
+       qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
+                       sizeof(struct ipa_rc_msg) - 1].rc = rc;
+       while(qeth_ipa_rc_msg[x].rc != rc)
+               x++;
+       return qeth_ipa_rc_msg[x].msg;
+}
 
 
+struct ipa_cmd_names {
+       enum qeth_ipa_cmds cmd;
+       char *name;
+};
+
+struct ipa_cmd_names qeth_ipa_cmd_names[] = {
+       {IPA_CMD_STARTLAN,      "startlan"},
+       {IPA_CMD_STOPLAN,       "stoplan"},
+       {IPA_CMD_SETVMAC,       "setvmac"},
+       {IPA_CMD_DELVMAC,       "delvmca"},
+       {IPA_CMD_SETGMAC,       "setgmac"},
+       {IPA_CMD_DELGMAC,       "delgmac"},
+       {IPA_CMD_SETVLAN,       "setvlan"},
+       {IPA_CMD_DELVLAN,       "delvlan"},
+       {IPA_CMD_SETCCID,       "setccid"},
+       {IPA_CMD_DELCCID,       "delccid"},
+       {IPA_CMD_MODCCID,       "setip"},
+       {IPA_CMD_SETIP,         "setip"},
+       {IPA_CMD_QIPASSIST,     "qipassist"},
+       {IPA_CMD_SETASSPARMS,   "setassparms"},
+       {IPA_CMD_SETIPM,        "setipm"},
+       {IPA_CMD_DELIPM,        "delipm"},
+       {IPA_CMD_SETRTG,        "setrtg"},
+       {IPA_CMD_DELIP,         "delip"},
+       {IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
+       {IPA_CMD_SET_DIAG_ASS,  "set_diag_ass"},
+       {IPA_CMD_CREATE_ADDR,   "create_addr"},
+       {IPA_CMD_DESTROY_ADDR,  "destroy_addr"},
+       {IPA_CMD_REGISTER_LOCAL_ADDR,   "register_local_addr"},
+       {IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"},
+       {IPA_CMD_UNKNOWN,       "unknown"},
+};
 
+char *
+qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
+{
+       int x = 0;
+       qeth_ipa_cmd_names[
+               sizeof(qeth_ipa_cmd_names)/
+                       sizeof(struct ipa_cmd_names)-1].cmd = cmd;
+       while(qeth_ipa_cmd_names[x].cmd != cmd)
+               x++;
+       return qeth_ipa_cmd_names[x].name;
+}
 
 
index d74bc43da72ae7c72cfb4a27c734e6db4adebccb..1d8083c91765891197ee83114d07e6eaad16d256 100644 (file)
@@ -25,14 +25,14 @@ extern unsigned char IPA_PDU_HEADER[];
 
 #define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
 
-#define QETH_SEQ_NO_LENGTH     4
-#define QETH_MPC_TOKEN_LENGTH  4
+#define QETH_SEQ_NO_LENGTH     4
+#define QETH_MPC_TOKEN_LENGTH  4
 #define QETH_MCL_LENGTH                4
 #define OSA_ADDR_LEN           6
 
-#define QETH_TIMEOUT           (10 * HZ)
-#define QETH_IPA_TIMEOUT       (45 * HZ)
-#define QETH_IDX_COMMAND_SEQNO         0xffff0000
+#define QETH_TIMEOUT           (10 * HZ)
+#define QETH_IPA_TIMEOUT       (45 * HZ)
+#define QETH_IDX_COMMAND_SEQNO 0xffff0000
 #define SR_INFO_LEN            16
 
 #define QETH_CLEAR_CHANNEL_PARM        -10
@@ -93,79 +93,107 @@ enum qeth_checksum_types {
  */
 #define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
 enum qeth_routing_types {
-       NO_ROUTER           = 0, /* TODO: set to bit flag used in IPA Command */
-       PRIMARY_ROUTER      = 1,
-       SECONDARY_ROUTER    = 2,
-       MULTICAST_ROUTER    = 3,
-       PRIMARY_CONNECTOR   = 4,
-       SECONDARY_CONNECTOR = 5,
+       NO_ROUTER               = 0, /* TODO: set to bit flag used in IPA Command */
+       PRIMARY_ROUTER          = 1,
+       SECONDARY_ROUTER        = 2,
+       MULTICAST_ROUTER        = 3,
+       PRIMARY_CONNECTOR       = 4,
+       SECONDARY_CONNECTOR     = 5,
 };
 
-
 /* IPA Commands */
 enum qeth_ipa_cmds {
-       IPA_CMD_STARTLAN              = 0x01,
-       IPA_CMD_STOPLAN               = 0x02,
-       IPA_CMD_SETVMAC               = 0x21,
-       IPA_CMD_DELVMAC               = 0x22,
-       IPA_CMD_SETGMAC               = 0x23,
-       IPA_CMD_DELGMAC               = 0x24,
-       IPA_CMD_SETVLAN               = 0x25,
-       IPA_CMD_DELVLAN               = 0x26,
-       IPA_CMD_SETCCID               = 0x41,
-       IPA_CMD_DELCCID               = 0x42,
-       IPA_CMD_MODCCID               = 0x43,
-       IPA_CMD_SETIP                 = 0xb1,
-       IPA_CMD_DELIP                 = 0xb7,
-       IPA_CMD_QIPASSIST             = 0xb2,
-       IPA_CMD_SETASSPARMS           = 0xb3,
-       IPA_CMD_SETIPM                = 0xb4,
-       IPA_CMD_DELIPM                = 0xb5,
-       IPA_CMD_SETRTG                = 0xb6,
-       IPA_CMD_SETADAPTERPARMS       = 0xb8,
-       IPA_CMD_IPFRAME               = 0xb9,
-       IPA_CMD_ADD_ADDR_ENTRY        = 0xc1,
-       IPA_CMD_DELETE_ADDR_ENTRY     = 0xc2,
-       IPA_CMD_CREATE_ADDR           = 0xc3,
-       IPA_CMD_DESTROY_ADDR          = 0xc4,
-       IPA_CMD_REGISTER_LOCAL_ADDR   = 0xd1,
-       IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2,
+       IPA_CMD_STARTLAN                = 0x01,
+       IPA_CMD_STOPLAN                 = 0x02,
+       IPA_CMD_SETVMAC                 = 0x21,
+       IPA_CMD_DELVMAC                 = 0x22,
+       IPA_CMD_SETGMAC                 = 0x23,
+       IPA_CMD_DELGMAC                 = 0x24,
+       IPA_CMD_SETVLAN                 = 0x25,
+       IPA_CMD_DELVLAN                 = 0x26,
+       IPA_CMD_SETCCID                 = 0x41,
+       IPA_CMD_DELCCID                 = 0x42,
+       IPA_CMD_MODCCID                 = 0x43,
+       IPA_CMD_SETIP                   = 0xb1,
+       IPA_CMD_QIPASSIST               = 0xb2,
+       IPA_CMD_SETASSPARMS             = 0xb3,
+       IPA_CMD_SETIPM                  = 0xb4,
+       IPA_CMD_DELIPM                  = 0xb5,
+       IPA_CMD_SETRTG                  = 0xb6,
+       IPA_CMD_DELIP                   = 0xb7,
+       IPA_CMD_SETADAPTERPARMS         = 0xb8,
+       IPA_CMD_SET_DIAG_ASS            = 0xb9,
+       IPA_CMD_CREATE_ADDR             = 0xc3,
+       IPA_CMD_DESTROY_ADDR            = 0xc4,
+       IPA_CMD_REGISTER_LOCAL_ADDR     = 0xd1,
+       IPA_CMD_UNREGISTER_LOCAL_ADDR   = 0xd2,
+       IPA_CMD_UNKNOWN                 = 0x00
 };
 
 enum qeth_ip_ass_cmds {
        IPA_CMD_ASS_START       = 0x0001,
        IPA_CMD_ASS_STOP        = 0x0002,
-       IPA_CMD_ASS_CONFIGURE   = 0x0003,
-       IPA_CMD_ASS_ENABLE      = 0x0004,
+       IPA_CMD_ASS_CONFIGURE   = 0x0003,
+       IPA_CMD_ASS_ENABLE      = 0x0004,
 };
 
 enum qeth_arp_process_subcmds {
-       IPA_CMD_ASS_ARP_SET_NO_ENTRIES  = 0x0003,
-       IPA_CMD_ASS_ARP_QUERY_CACHE     = 0x0004,
-       IPA_CMD_ASS_ARP_ADD_ENTRY       = 0x0005,
-       IPA_CMD_ASS_ARP_REMOVE_ENTRY    = 0x0006,
-       IPA_CMD_ASS_ARP_FLUSH_CACHE     = 0x0007,
-       IPA_CMD_ASS_ARP_QUERY_INFO      = 0x0104,
-       IPA_CMD_ASS_ARP_QUERY_STATS     = 0x0204,
+       IPA_CMD_ASS_ARP_SET_NO_ENTRIES  = 0x0003,
+       IPA_CMD_ASS_ARP_QUERY_CACHE     = 0x0004,
+       IPA_CMD_ASS_ARP_ADD_ENTRY       = 0x0005,
+       IPA_CMD_ASS_ARP_REMOVE_ENTRY    = 0x0006,
+       IPA_CMD_ASS_ARP_FLUSH_CACHE     = 0x0007,
+       IPA_CMD_ASS_ARP_QUERY_INFO      = 0x0104,
+       IPA_CMD_ASS_ARP_QUERY_STATS     = 0x0204,
 };
 
-/* Return Codes for IPA Commands */
+
+/* Return Codes for IPA Commands
+ * according to OSA card Specs */
+
 enum qeth_ipa_return_codes {
-       IPA_RC_SUCCESS             = 0x0000,
-       IPA_RC_NOTSUPP             = 0x0001,
-       IPA_RC_NO_ACCESS           = 0x0002,
-       IPA_RC_FAILED              = 0x0003,
-       IPA_RC_DATA_MISMATCH       = 0xe001,
-       IPA_RC_INVALID_LAN_TYPE    = 0xe003,
-       IPA_RC_INVALID_LAN_NO      = 0xe004,
-       IPA_RC_IPADDR_ALREADY_REG  = 0xe005,
-       IPA_RC_IPADDR_TABLE_FULL   = 0xe006,
-       IPA_RC_IPADDR_ALREADY_USED = 0xe00a,
-       IPA_RC_ASSNO_NOT_SUPP      = 0xe00d,
-       IPA_RC_ASSCMD_START_FAILED = 0xe00e,
-       IPA_RC_ASSCMD_PART_SUCCESS = 0xe00f,
-       IPA_RC_IPADDR_NOT_DEFINED  = 0xe010,
-       IPA_RC_LAN_OFFLINE         = 0xe080,
+       IPA_RC_SUCCESS                  = 0x0000,
+       IPA_RC_NOTSUPP                  = 0x0001,
+       IPA_RC_IP_TABLE_FULL            = 0x0002,
+       IPA_RC_UNKNOWN_ERROR            = 0x0003,
+       IPA_RC_UNSUPPORTED_COMMAND      = 0x0004,
+       IPA_RC_DUP_IPV6_REMOTE          = 0x0008,
+       IPA_RC_DUP_IPV6_HOME            = 0x0010,
+       IPA_RC_UNREGISTERED_ADDR        = 0x0011,
+       IPA_RC_NO_ID_AVAILABLE          = 0x0012,
+       IPA_RC_ID_NOT_FOUND             = 0x0013,
+       IPA_RC_INVALID_IP_VERSION       = 0x0020,
+       IPA_RC_LAN_FRAME_MISMATCH       = 0x0040,
+       IPA_RC_L2_UNSUPPORTED_CMD       = 0x2003,
+       IPA_RC_L2_DUP_MAC               = 0x2005,
+       IPA_RC_L2_ADDR_TABLE_FULL       = 0x2006,
+       IPA_RC_L2_DUP_LAYER3_MAC        = 0x200a,
+       IPA_RC_L2_GMAC_NOT_FOUND        = 0x200b,
+       IPA_RC_L2_MAC_NOT_FOUND         = 0x2010,
+       IPA_RC_L2_INVALID_VLAN_ID       = 0x2015,
+       IPA_RC_L2_DUP_VLAN_ID           = 0x2016,
+       IPA_RC_L2_VLAN_ID_NOT_FOUND     = 0x2017,
+       IPA_RC_DATA_MISMATCH            = 0xe001,
+       IPA_RC_INVALID_MTU_SIZE         = 0xe002,
+       IPA_RC_INVALID_LANTYPE          = 0xe003,
+       IPA_RC_INVALID_LANNUM           = 0xe004,
+       IPA_RC_DUPLICATE_IP_ADDRESS     = 0xe005,
+       IPA_RC_IP_ADDR_TABLE_FULL       = 0xe006,
+       IPA_RC_LAN_PORT_STATE_ERROR     = 0xe007,
+       IPA_RC_SETIP_NO_STARTLAN        = 0xe008,
+       IPA_RC_SETIP_ALREADY_RECEIVED   = 0xe009,
+       IPA_RC_IP_ADDR_ALREADY_USED     = 0xe00a,
+       IPA_RC_MULTICAST_FULL           = 0xe00b,
+       IPA_RC_SETIP_INVALID_VERSION    = 0xe00d,
+       IPA_RC_UNSUPPORTED_SUBCMD       = 0xe00e,
+       IPA_RC_ARP_ASSIST_NO_ENABLE     = 0xe00f,
+       IPA_RC_PRIMARY_ALREADY_DEFINED  = 0xe010,
+       IPA_RC_SECOND_ALREADY_DEFINED   = 0xe011,
+       IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
+       IPA_RC_MC_ADDR_ALREADY_DEFINED  = 0xe013,
+       IPA_RC_LAN_OFFLINE              = 0xe080,
+       IPA_RC_INVALID_IP_VERSION2      = 0xf001,
+       IPA_RC_FFFF                     = 0xffff
 };
 
 /* IPA function flags; each flag marks availability of respective function */
@@ -183,7 +211,9 @@ enum qeth_ipa_funcs {
        IPA_SETADAPTERPARMS     = 0x00000400L,
        IPA_VLAN_PRIO           = 0x00000800L,
        IPA_PASSTHRU            = 0x00001000L,
+       IPA_FLUSH_ARP_SUPPORT   = 0x00002000L,
        IPA_FULL_VLAN           = 0x00004000L,
+       IPA_INBOUND_PASSTHRU    = 0x00008000L,
        IPA_SOURCE_MAC          = 0x00010000L,
        IPA_OSA_MC_ROUTER       = 0x00020000L,
        IPA_QUERY_ARP_ASSIST    = 0x00040000L,
@@ -204,31 +234,30 @@ enum qeth_ipa_setdelip_flags {
 /* SETADAPTER IPA Command: ****************************************************/
 enum qeth_ipa_setadp_cmd {
        IPA_SETADP_QUERY_COMMANDS_SUPPORTED     = 0x01,
-       IPA_SETADP_ALTER_MAC_ADDRESS            = 0x02,
-       IPA_SETADP_ADD_DELETE_GROUP_ADDRESS     = 0x04,
-       IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR   = 0x08,
-       IPA_SETADP_SET_ADDRESSING_MODE          = 0x10,
-       IPA_SETADP_SET_CONFIG_PARMS             = 0x20,
-       IPA_SETADP_SET_CONFIG_PARMS_EXTENDED    = 0x40,
-       IPA_SETADP_SET_BROADCAST_MODE           = 0x80,
-       IPA_SETADP_SEND_OSA_MESSAGE             = 0x0100,
-       IPA_SETADP_SET_SNMP_CONTROL             = 0x0200,
-       IPA_SETADP_READ_SNMP_PARMS              = 0x0400,
+       IPA_SETADP_ALTER_MAC_ADDRESS            = 0x02,
+       IPA_SETADP_ADD_DELETE_GROUP_ADDRESS     = 0x04,
+       IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR   = 0x08,
+       IPA_SETADP_SET_ADDRESSING_MODE          = 0x10,
+       IPA_SETADP_SET_CONFIG_PARMS             = 0x20,
+       IPA_SETADP_SET_CONFIG_PARMS_EXTENDED    = 0x40,
+       IPA_SETADP_SET_BROADCAST_MODE           = 0x80,
+       IPA_SETADP_SEND_OSA_MESSAGE             = 0x0100,
+       IPA_SETADP_SET_SNMP_CONTROL             = 0x0200,
+       IPA_SETADP_QUERY_CARD_INFO              = 0x0400,
        IPA_SETADP_SET_PROMISC_MODE             = 0x0800,
-       IPA_SETADP_QUERY_CARD_INFO              = 0x1000,
 };
 enum qeth_ipa_mac_ops {
-       CHANGE_ADDR_READ_MAC            = 0,
-       CHANGE_ADDR_REPLACE_MAC         = 1,
-       CHANGE_ADDR_ADD_MAC             = 2,
-       CHANGE_ADDR_DEL_MAC             = 4,
-       CHANGE_ADDR_RESET_MAC           = 8,
+       CHANGE_ADDR_READ_MAC            = 0,
+       CHANGE_ADDR_REPLACE_MAC         = 1,
+       CHANGE_ADDR_ADD_MAC             = 2,
+       CHANGE_ADDR_DEL_MAC             = 4,
+       CHANGE_ADDR_RESET_MAC           = 8,
 };
 enum qeth_ipa_addr_ops {
-       CHANGE_ADDR_READ_ADDR           = 0,
-       CHANGE_ADDR_ADD_ADDR            = 1,
-       CHANGE_ADDR_DEL_ADDR            = 2,
-       CHANGE_ADDR_FLUSH_ADDR_TABLE    = 4,
+       CHANGE_ADDR_READ_ADDR           = 0,
+       CHANGE_ADDR_ADD_ADDR            = 1,
+       CHANGE_ADDR_DEL_ADDR            = 2,
+       CHANGE_ADDR_FLUSH_ADDR_TABLE    = 4,
 };
 enum qeth_ipa_promisc_modes {
        SET_PROMISC_MODE_OFF            = 0,
@@ -407,15 +436,15 @@ struct qeth_ipacmd_hdr {
 struct qeth_ipa_cmd {
        struct qeth_ipacmd_hdr hdr;
        union {
-               struct qeth_ipacmd_setdelip4            setdelip4;
-               struct qeth_ipacmd_setdelip6            setdelip6;
+               struct qeth_ipacmd_setdelip4            setdelip4;
+               struct qeth_ipacmd_setdelip6            setdelip6;
                struct qeth_ipacmd_setdelipm            setdelipm;
-               struct qeth_ipacmd_setassparms          setassparms;
-               struct qeth_ipacmd_layer2setdelmac      setdelmac;
-               struct qeth_ipacmd_layer2setdelvlan     setdelvlan;
-               struct qeth_create_destroy_address      create_destroy_addr;
-               struct qeth_ipacmd_setadpparms          setadapterparms;
-               struct qeth_set_routing                 setrtg;
+               struct qeth_ipacmd_setassparms          setassparms;
+               struct qeth_ipacmd_layer2setdelmac      setdelmac;
+               struct qeth_ipacmd_layer2setdelvlan     setdelvlan;
+               struct qeth_create_destroy_address      create_destroy_addr;
+               struct qeth_ipacmd_setadpparms          setadapterparms;
+               struct qeth_set_routing                 setrtg;
        } data;
 } __attribute__ ((packed));
 
@@ -433,6 +462,12 @@ enum qeth_ipa_arp_return_codes {
        QETH_IPA_ARP_RC_Q_NO_DATA    = 0x0008,
 };
 
+
+extern char *
+qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
+extern char *
+qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
+
 #define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
                               sizeof(struct qeth_ipacmd_setassparms_hdr))
 #define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
@@ -521,7 +556,7 @@ extern unsigned char DM_ACT[];
 extern unsigned char IDX_ACTIVATE_READ[];
 extern unsigned char IDX_ACTIVATE_WRITE[];
 
-#define IDX_ACTIVATE_SIZE      0x22
+#define IDX_ACTIVATE_SIZE      0x22
 #define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c)
 #define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80)
 #define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10)
index d518419cd0c6389bd966fab970fc6768f76f98b6..65ffc21afc37525d53010daff7d0ccf86d9a3bb5 100644 (file)
@@ -384,8 +384,6 @@ qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
                route->type = PRIMARY_CONNECTOR;
        } else if (!strcmp(tmp, "secondary_connector")) {
                route->type = SECONDARY_CONNECTOR;
-       } else if (!strcmp(tmp, "multicast_router")) {
-               route->type = MULTICAST_ROUTER;
        } else if (!strcmp(tmp, "primary_router")) {
                route->type = PRIMARY_ROUTER;
        } else if (!strcmp(tmp, "secondary_router")) {
index 1f9554e0801392e043ff2ac1e120ed44c8da7644..324899c96efe2dcf4b15597d245c5306ceead9f6 100644 (file)
@@ -118,97 +118,32 @@ _zfcp_hex_dump(char *addr, int count)
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_FSF
 
-static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
+static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
 {
-       int i;
+       int idx;
 
        adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
                                    GFP_KERNEL);
-
        if (!adapter->req_list)
                return -ENOMEM;
 
-       for (i=0; i<REQUEST_LIST_SIZE; i++)
-               INIT_LIST_HEAD(&adapter->req_list[i]);
-
+       for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
+               INIT_LIST_HEAD(&adapter->req_list[idx]);
        return 0;
 }
 
 static void zfcp_reqlist_free(struct zfcp_adapter *adapter)
 {
-       struct zfcp_fsf_req *request, *tmp;
-       unsigned int i;
-
-       for (i=0; i<REQUEST_LIST_SIZE; i++) {
-               if (list_empty(&adapter->req_list[i]))
-                       continue;
-
-               list_for_each_entry_safe(request, tmp,
-                                        &adapter->req_list[i], list)
-                       list_del(&request->list);
-       }
-
        kfree(adapter->req_list);
 }
 
-void zfcp_reqlist_add(struct zfcp_adapter *adapter,
-                     struct zfcp_fsf_req *fsf_req)
-{
-       unsigned int i;
-
-       i = fsf_req->req_id % REQUEST_LIST_SIZE;
-       list_add_tail(&fsf_req->list, &adapter->req_list[i]);
-}
-
-void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id)
-{
-       struct zfcp_fsf_req *request, *tmp;
-       unsigned int i, counter;
-       u64 dbg_tmp[2];
-
-       i = req_id % REQUEST_LIST_SIZE;
-       BUG_ON(list_empty(&adapter->req_list[i]));
-
-       counter = 0;
-       list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) {
-               if (request->req_id == req_id) {
-                       dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
-                       dbg_tmp[1] = (u64) counter;
-                       debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
-                       list_del(&request->list);
-                       break;
-               }
-               counter++;
-       }
-}
-
-struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
-                                          unsigned long req_id)
-{
-       struct zfcp_fsf_req *request, *tmp;
-       unsigned int i;
-
-       /* 0 is reserved as an invalid req_id */
-       if (req_id == 0)
-               return NULL;
-
-       i = req_id % REQUEST_LIST_SIZE;
-
-       list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
-               if (request->req_id == req_id)
-                       return request;
-
-       return NULL;
-}
-
 int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
 {
-       unsigned int i;
+       unsigned int idx;
 
-       for (i=0; i<REQUEST_LIST_SIZE; i++)
-               if (!list_empty(&adapter->req_list[i]))
+       for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
+               if (!list_empty(&adapter->req_list[idx]))
                        return 0;
-
        return 1;
 }
 
@@ -913,6 +848,8 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
        unit->sysfs_device.release = zfcp_sysfs_unit_release;
        dev_set_drvdata(&unit->sysfs_device, unit);
 
+       init_waitqueue_head(&unit->scsi_scan_wq);
+
        /* mark unit unusable as long as sysfs registration is not complete */
        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
 
@@ -1104,7 +1041,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
        /* initialize list of fsf requests */
        spin_lock_init(&adapter->req_list_lock);
-       retval = zfcp_reqlist_init(adapter);
+       retval = zfcp_reqlist_alloc(adapter);
        if (retval) {
                ZFCP_LOG_INFO("request list initialization failed\n");
                goto failed_low_mem_buffers;
@@ -1165,6 +1102,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
  sysfs_failed:
        dev_set_drvdata(&ccw_device->dev, NULL);
+       zfcp_reqlist_free(adapter);
  failed_low_mem_buffers:
        zfcp_free_low_mem_buffers(adapter);
        if (qdio_free(ccw_device) != 0)
@@ -1497,7 +1435,7 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
 
        if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) {
                ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "
-                              "with d_id 0x%08x on adapter %s\n",
+                              "with d_id 0x%06x on adapter %s\n",
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
@@ -1522,7 +1460,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
 
        if (!port || (port->wwpn != els_logo->nport_wwpn)) {
                ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port "
-                              "with d_id 0x%08x on adapter %s\n",
+                              "with d_id 0x%06x on adapter %s\n",
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
@@ -1704,7 +1642,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
        /* looks like a valid d_id */
         port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
        atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
-       ZFCP_LOG_DEBUG("adapter %s:  wwpn=0x%016Lx ---> d_id=0x%08x\n",
+       ZFCP_LOG_DEBUG("adapter %s:  wwpn=0x%016Lx ---> d_id=0x%06x\n",
                       zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
        goto out;
 
index 32933ed54b8a05dbe3534ac90395bbbf3d1ee283..22649639230b25fc8a326ab0eb3938070a9fdb26 100644 (file)
@@ -637,6 +637,7 @@ do { \
 #define ZFCP_STATUS_UNIT_SHARED                        0x00000004
 #define ZFCP_STATUS_UNIT_READONLY              0x00000008
 #define ZFCP_STATUS_UNIT_REGISTERED            0x00000010
+#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING     0x00000020
 
 /* FSF request status (this does not have a common part) */
 #define ZFCP_STATUS_FSFREQ_NOT_INIT            0x00000000
@@ -980,6 +981,10 @@ struct zfcp_unit {
         struct scsi_device     *device;        /* scsi device struct pointer */
        struct zfcp_erp_action erp_action;     /* pending error recovery */
         atomic_t               erp_counter;
+       wait_queue_head_t      scsi_scan_wq;   /* can be used to wait until
+                                                 all scsi_scan_target
+                                                 requests have been
+                                                 completed. */
 };
 
 /* FSF request */
@@ -1084,6 +1089,42 @@ extern void _zfcp_hex_dump(char *, int);
 #define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
 #define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))
 
+/*
+ * Helper functions for request ID management.
+ */
+static inline int zfcp_reqlist_hash(unsigned long req_id)
+{
+       return req_id % REQUEST_LIST_SIZE;
+}
+
+static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter,
+                                   struct zfcp_fsf_req *fsf_req)
+{
+       unsigned int idx;
+
+       idx = zfcp_reqlist_hash(fsf_req->req_id);
+       list_add_tail(&fsf_req->list, &adapter->req_list[idx]);
+}
+
+static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter,
+                                      struct zfcp_fsf_req *fsf_req)
+{
+       list_del(&fsf_req->list);
+}
+
+static inline struct zfcp_fsf_req *
+zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
+{
+       struct zfcp_fsf_req *request;
+       unsigned int idx;
+
+       idx = zfcp_reqlist_hash(req_id);
+       list_for_each_entry(request, &adapter->req_list[idx], list)
+               if (request->req_id == req_id)
+                       return request;
+       return NULL;
+}
+
 /*
  *  functions needed for reference/usage counting
  */
index c1f2d4b14c2b4517071d5e8fc6a8d5358a9b7347..aef66bc2b6cac79dff1219b44a287f666a8a4087 100644 (file)
@@ -179,7 +179,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 {
        struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
-       zfcp_erp_adapter_reopen(adapter, 0);
+       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
 void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
@@ -342,9 +342,9 @@ zfcp_erp_adisc(struct zfcp_port *port)
        adisc->wwpn = fc_host_port_name(adapter->scsi_host);
        adisc->wwnn = fc_host_node_name(adapter->scsi_host);
        adisc->nport_id = fc_host_port_id(adapter->scsi_host);
-       ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
+       ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x "
                      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
-                     "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
+                     "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
                      adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
                      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
                      adisc->nport_id);
@@ -352,7 +352,7 @@ zfcp_erp_adisc(struct zfcp_port *port)
        retval = zfcp_fsf_send_els(send_els);
        if (retval != 0) {
                ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
-                               "0x%08x on adapter %s\n", send_els->d_id,
+                               "0x%06x on adapter %s\n", send_els->d_id,
                                zfcp_get_busid_by_adapter(adapter));
                goto freemem;
        }
@@ -398,7 +398,7 @@ zfcp_erp_adisc_handler(unsigned long data)
        if (send_els->status != 0) {
                ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
                                "force physical port reopen "
-                               "(adapter %s, port d_id=0x%08x)\n",
+                               "(adapter %s, port d_id=0x%06x)\n",
                                zfcp_get_busid_by_adapter(adapter), d_id);
                debug_text_event(adapter->erp_dbf, 3, "forcreop");
                if (zfcp_erp_port_forced_reopen(port, 0))
@@ -411,9 +411,9 @@ zfcp_erp_adisc_handler(unsigned long data)
 
        adisc = zfcp_sg_to_address(send_els->resp);
 
-       ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
-                     "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
-                     "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
+       ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id "
+                     "0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+                     "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
                      d_id, fc_host_port_id(adapter->scsi_host),
                      (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
                      adisc->hard_nport_id, adisc->nport_id);
@@ -847,8 +847,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
        if (erp_action->fsf_req) {
                /* take lock to ensure that request is not deleted meanwhile */
                spin_lock(&adapter->req_list_lock);
-               if (zfcp_reqlist_ismember(adapter,
-                                           erp_action->fsf_req->req_id)) {
+               if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) {
                        /* fsf_req still exists */
                        debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
                        debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
@@ -1377,7 +1376,7 @@ zfcp_erp_port_failed(struct zfcp_port *port)
 
        if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
                ZFCP_LOG_NORMAL("port erp failed (adapter %s, "
-                               "port d_id=0x%08x)\n",
+                               "port d_id=0x%06x)\n",
                                zfcp_get_busid_by_port(port), port->d_id);
        else
                ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
@@ -1591,6 +1590,62 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
        return result;
 }
 
+struct zfcp_erp_add_work {
+       struct zfcp_unit  *unit;
+       struct work_struct work;
+};
+
+/**
+ * zfcp_erp_scsi_scan
+ * @data: pointer to a struct zfcp_erp_add_work
+ *
+ * Registers a logical unit with the SCSI stack.
+ */
+static void zfcp_erp_scsi_scan(struct work_struct *work)
+{
+       struct zfcp_erp_add_work *p =
+               container_of(work, struct zfcp_erp_add_work, work);
+       struct zfcp_unit *unit = p->unit;
+       struct fc_rport *rport = unit->port->rport;
+       scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+                        unit->scsi_lun, 0);
+       atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+       wake_up(&unit->scsi_scan_wq);
+       zfcp_unit_put(unit);
+       kfree(p);
+}
+
+/**
+ * zfcp_erp_schedule_work
+ * @unit: pointer to unit which should be registered with SCSI stack
+ *
+ * Schedules work which registers a unit with the SCSI stack
+ */
+static void
+zfcp_erp_schedule_work(struct zfcp_unit *unit)
+{
+       struct zfcp_erp_add_work *p;
+
+       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
+                               "the FCP-LUN 0x%Lx connected to "
+                               "the port with WWPN 0x%Lx connected to "
+                               "the adapter %s with the SCSI stack.\n",
+                               unit->fcp_lun,
+                               unit->port->wwpn,
+                               zfcp_get_busid_by_unit(unit));
+               return;
+       }
+
+       zfcp_unit_get(unit);
+       memset(p, 0, sizeof(*p));
+       atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+       INIT_WORK(&p->work, zfcp_erp_scsi_scan);
+       p->unit = unit;
+       schedule_work(&p->work);
+}
+
 /*
  * function:   
  *
@@ -2401,7 +2456,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
                                retval = ZFCP_ERP_FAILED;
                        }
                } else {
-                       ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> "
+                       ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> "
                                       "trying open\n", port->wwpn, port->d_id);
                        retval = zfcp_erp_port_strategy_open_port(erp_action);
                }
@@ -2441,7 +2496,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
        case ZFCP_ERP_STEP_UNINITIALIZED:
        case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
        case ZFCP_ERP_STEP_PORT_CLOSING:
-               ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> trying open\n",
+               ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n",
                               port->wwpn, port->d_id);
                retval = zfcp_erp_port_strategy_open_port(erp_action);
                break;
@@ -3092,9 +3147,9 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                    && port->rport) {
                        atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
                                        &unit->status);
-                       scsi_scan_target(&port->rport->dev, 0,
-                                        port->rport->scsi_target_id,
-                                        unit->scsi_lun, 0);
+                       if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
+                                            &unit->status) == 0)
+                               zfcp_erp_schedule_work(unit);
                }
                zfcp_unit_put(unit);
                break;
@@ -3121,7 +3176,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                                                zfcp_get_busid_by_port(port),
                                                port->wwpn);
                        else {
-                               scsi_flush_work(adapter->scsi_host);
+                               scsi_target_unblock(&port->rport->dev);
                                port->rport->maxframe_size = port->maxframe_size;
                                port->rport->supported_classes =
                                        port->supported_classes;
index 01386ac688a27887e32cd75dfa336a2c4611f5d9..991d45667a44d0453f06d0134d1345a8a5509d2a 100644 (file)
@@ -184,10 +184,6 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
                                      unsigned long);
 extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
                                         struct scsi_cmnd *);
-extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
-extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long);
-extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *,
-                                                 unsigned long);
 extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
 
 #endif /* ZFCP_EXT_H */
index 4c0a59afd5c85bda51083b6cab01588c11268363..a8b02542ac2da30aaaf9a953153d41e419c18da0 100644 (file)
@@ -828,7 +828,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
 
        if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) {
                ZFCP_LOG_NORMAL("bug: Reopen port indication received for"
-                               "nonexisting port with d_id 0x%08x on "
+                               "nonexisting port with d_id 0x%06x on "
                                "adapter %s. Ignored.\n",
                                status_buffer->d_id & ZFCP_DID_MASK,
                                zfcp_get_busid_by_adapter(adapter));
@@ -853,7 +853,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
                                &status_buffer->status_subtype, sizeof (u32));
                ZFCP_LOG_NORMAL("bug: Undefined status subtype received "
                                "for a reopen indication on port with "
-                               "d_id 0x%08x on the adapter %s. "
+                               "d_id 0x%06x on the adapter %s. "
                                "Ignored. (debug info 0x%x)\n",
                                status_buffer->d_id,
                                zfcp_get_busid_by_adapter(adapter),
@@ -1156,7 +1156,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
        }
 
        ZFCP_LOG_DEBUG("Abort FCP Command request initiated "
-                      "(adapter%s, port d_id=0x%08x, "
+                      "(adapter%s, port d_id=0x%06x, "
                       "unit x%016Lx, old_req_id=0x%lx)\n",
                       zfcp_get_busid_by_adapter(adapter),
                       unit->port->d_id,
@@ -1554,7 +1554,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 
        case FSF_ACCESS_DENIED:
                ZFCP_LOG_NORMAL("access denied, cannot send generic service "
-                               "command (adapter %s, port d_id=0x%08x)\n",
+                               "command (adapter %s, port d_id=0x%06x)\n",
                                zfcp_get_busid_by_port(port), port->d_id);
                for (counter = 0; counter < 2; counter++) {
                        subtable = header->fsf_status_qual.halfword[counter * 2];
@@ -1576,7 +1576,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 
         case FSF_GENERIC_COMMAND_REJECTED:
                ZFCP_LOG_INFO("generic service command rejected "
-                             "(adapter %s, port d_id=0x%08x)\n",
+                             "(adapter %s, port d_id=0x%06x)\n",
                              zfcp_get_busid_by_port(port), port->d_id);
                ZFCP_LOG_INFO("status qualifier:\n");
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
@@ -1602,7 +1602,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 
         case FSF_PORT_BOXED:
                ZFCP_LOG_INFO("port needs to be reopened "
-                             "(adapter %s, port d_id=0x%08x)\n",
+                             "(adapter %s, port d_id=0x%06x)\n",
                              zfcp_get_busid_by_port(port), port->d_id);
                debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
                zfcp_erp_port_boxed(port);
@@ -1683,7 +1683,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
                                  NULL, &lock_flags, &fsf_req);
        if (ret < 0) {
                 ZFCP_LOG_INFO("error: creation of ELS request failed "
-                             "(adapter %s, port d_id: 0x%08x)\n",
+                             "(adapter %s, port d_id: 0x%06x)\n",
                               zfcp_get_busid_by_adapter(adapter), d_id);
                 goto failed_req;
        }
@@ -1708,7 +1708,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
                                                 ZFCP_MAX_SBALS_PER_ELS_REQ);
                 if (bytes <= 0) {
                         ZFCP_LOG_INFO("error: creation of ELS request failed "
-                                     "(adapter %s, port d_id: 0x%08x)\n",
+                                     "(adapter %s, port d_id: 0x%06x)\n",
                                      zfcp_get_busid_by_adapter(adapter), d_id);
                         if (bytes == 0) {
                                 ret = -ENOMEM;
@@ -1725,7 +1725,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
                                                 ZFCP_MAX_SBALS_PER_ELS_REQ);
                 if (bytes <= 0) {
                         ZFCP_LOG_INFO("error: creation of ELS request failed "
-                                     "(adapter %s, port d_id: 0x%08x)\n",
+                                     "(adapter %s, port d_id: 0x%06x)\n",
                                      zfcp_get_busid_by_adapter(adapter), d_id);
                         if (bytes == 0) {
                                 ret = -ENOMEM;
@@ -1739,7 +1739,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
                 /* reject request */
                ZFCP_LOG_INFO("error: microcode does not support chained SBALs"
                               ", ELS request too big (adapter %s, "
-                             "port d_id: 0x%08x)\n",
+                             "port d_id: 0x%06x)\n",
                              zfcp_get_busid_by_adapter(adapter), d_id);
                 ret = -EOPNOTSUPP;
                 goto failed_send;
@@ -1760,13 +1760,13 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
        ret = zfcp_fsf_req_send(fsf_req);
        if (ret) {
                ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
-                              "(adapter %s, port d_id: 0x%08x)\n",
+                              "(adapter %s, port d_id: 0x%06x)\n",
                               zfcp_get_busid_by_adapter(adapter), d_id);
                goto failed_send;
        }
 
        ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: "
-                      "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
+                      "0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
        goto out;
 
  failed_send:
@@ -1859,7 +1859,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
        case FSF_ELS_COMMAND_REJECTED:
                ZFCP_LOG_INFO("ELS has been rejected because command filter "
                              "prohibited sending "
-                             "(adapter: %s, port d_id: 0x%08x)\n",
+                             "(adapter: %s, port d_id: 0x%06x)\n",
                              zfcp_get_busid_by_adapter(adapter), d_id);
 
                break;
@@ -1907,7 +1907,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 
        case FSF_ACCESS_DENIED:
                ZFCP_LOG_NORMAL("access denied, cannot send ELS command "
-                               "(adapter %s, port d_id=0x%08x)\n",
+                               "(adapter %s, port d_id=0x%06x)\n",
                                zfcp_get_busid_by_adapter(adapter), d_id);
                for (counter = 0; counter < 2; counter++) {
                        subtable = header->fsf_status_qual.halfword[counter * 2];
@@ -2070,7 +2070,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
        ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n"
                        "WWNN 0x%016Lx, "
                        "WWPN 0x%016Lx, "
-                       "S_ID 0x%08x,\n"
+                       "S_ID 0x%06x,\n"
                        "adapter version 0x%x, "
                        "LIC version 0x%x, "
                        "FC link speed %d Gb/s\n",
@@ -3043,6 +3043,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
        queue_designator = &header->fsf_status_qual.fsf_queue_designator;
 
        atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+                         ZFCP_STATUS_COMMON_ACCESS_BOXED |
                          ZFCP_STATUS_UNIT_SHARED |
                          ZFCP_STATUS_UNIT_READONLY,
                          &unit->status);
@@ -4645,23 +4646,22 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
        fsf_req->adapter = adapter;
        fsf_req->fsf_command = fsf_cmd;
        INIT_LIST_HEAD(&fsf_req->list);
-       
-       /* this is serialized (we are holding req_queue-lock of adapter */
-       if (adapter->req_no == 0)
-               adapter->req_no++;
-       fsf_req->req_id = adapter->req_no++;
-
        init_timer(&fsf_req->timer);
-       zfcp_fsf_req_qtcb_init(fsf_req);
 
        /* initialize waitqueue which may be used to wait on 
           this request completion */
        init_waitqueue_head(&fsf_req->completion_wq);
 
         ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags);
-        if(ret < 0) {
+        if (ret < 0)
                 goto failed_sbals;
-       }
+
+       /* this is serialized (we are holding req_queue-lock of adapter) */
+       if (adapter->req_no == 0)
+               adapter->req_no++;
+       fsf_req->req_id = adapter->req_no++;
+
+       zfcp_fsf_req_qtcb_init(fsf_req);
 
        /*
         * We hold queue_lock here. Check if QDIOUP is set and let request fail
@@ -4788,7 +4788,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
                retval = -EIO;
                del_timer(&fsf_req->timer);
                spin_lock(&adapter->req_list_lock);
-               zfcp_reqlist_remove(adapter, fsf_req->req_id);
+               zfcp_reqlist_remove(adapter, fsf_req);
                spin_unlock(&adapter->req_list_lock);
                /* undo changes in request queue made for this request */
                zfcp_qdio_zero_sbals(req_queue->buffer,
index 1e12a78e8edd1c17886a66f5e7bf2b530adf6018..bdf5782b8a7acd175dac262d45514d7035a21bbb 100644 (file)
@@ -222,7 +222,7 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
                 * Since we have been using this adapter, it is save to assume
                 * that it is not failed but recoverable. The card seems to
                 * report link-up events by self-initiated queue shutdown.
-                * That is why we need to clear the the link-down flag
+                * That is why we need to clear the link-down flag
                 * which is set again in case we have missed by a mile.
                 */
                zfcp_erp_adapter_reopen(
@@ -283,10 +283,10 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
 }
 
 /**
- * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status
+ * zfcp_qdio_reqid_check - checks for valid reqids.
  */
-static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, 
-                                unsigned long req_id)
+static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
+                                 unsigned long req_id)
 {
        struct zfcp_fsf_req *fsf_req;
        unsigned long flags;
@@ -294,23 +294,22 @@ static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
        debug_long_event(adapter->erp_dbf, 4, req_id);
 
        spin_lock_irqsave(&adapter->req_list_lock, flags);
-       fsf_req = zfcp_reqlist_ismember(adapter, req_id);
+       fsf_req = zfcp_reqlist_find(adapter, req_id);
 
-       if (!fsf_req) {
-               spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-               ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id);
-               zfcp_erp_adapter_reopen(adapter, 0);
-               return -EINVAL;
-       }
+       if (!fsf_req)
+               /*
+                * Unknown request means that we have potentially memory
+                * corruption and must stop the machine immediatly.
+                */
+               panic("error: unknown request id (%ld) on adapter %s.\n",
+                     req_id, zfcp_get_busid_by_adapter(adapter));
 
-       zfcp_reqlist_remove(adapter, req_id);
+       zfcp_reqlist_remove(adapter, fsf_req);
        atomic_dec(&adapter->reqs_active);
        spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
        /* finish the FSF request */
        zfcp_fsf_req_complete(fsf_req);
-
-       return 0;
 }
 
 /*
@@ -374,27 +373,9 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
 
                        /* look for QDIO request identifiers in SB */
                        buffere = &buffer->element[buffere_index];
-                       retval = zfcp_qdio_reqid_check(adapter,
-                                       (unsigned long) buffere->addr);
-
-                       if (retval) {
-                               ZFCP_LOG_NORMAL("bug: unexpected inbound "
-                                               "packet on adapter %s "
-                                               "(reqid=0x%lx, "
-                                               "first_element=%d, "
-                                               "elements_processed=%d)\n",
-                                               zfcp_get_busid_by_adapter(adapter),
-                                               (unsigned long) buffere->addr,
-                                               first_element,
-                                               elements_processed);
-                               ZFCP_LOG_NORMAL("hex dump of inbound buffer "
-                                               "at address %p "
-                                               "(buffer_index=%d, "
-                                               "buffere_index=%d)\n", buffer,
-                                               buffer_index, buffere_index);
-                               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-                                             (char *) buffer, SBAL_SIZE);
-                       }
+                       zfcp_qdio_reqid_check(adapter,
+                                             (unsigned long) buffere->addr);
+
                        /*
                         * A single used SBALE per inbound SBALE has been
                         * implemented by QDIO so far. Hope they will
index 99db02062c3b4af325e8cbfa3b9208d333a867d5..16e2d64658afea075143230bdcc08d9a492a58a8 100644 (file)
@@ -22,6 +22,7 @@
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_SCSI
 
 #include "zfcp_ext.h"
+#include <asm/atomic.h>
 
 static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdp);
@@ -179,6 +180,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
        struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
 
        if (unit) {
+               zfcp_erp_wait(unit->port->adapter);
+               wait_event(unit->scsi_scan_wq,
+                          atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
+                                           &unit->status) == 0);
                atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
                sdpnt->hostdata = NULL;
                unit->device = NULL;
@@ -402,8 +407,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 
        /* Check whether corresponding fsf_req is still pending */
        spin_lock(&adapter->req_list_lock);
-       fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
-                                       scpnt->host_scribble);
+       fsf_req = zfcp_reqlist_find(adapter,
+                                   (unsigned long) scpnt->host_scribble);
        spin_unlock(&adapter->req_list_lock);
        if (!fsf_req) {
                write_unlock_irqrestore(&adapter->abort_lock, flags);
index a39ee80c9715749b7a1089fa99260128557fe8e9..4fab0c23814c90dda8bf55b85e6242c6dbc07d96 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
@@ -157,7 +156,7 @@ static unsigned short get_pins(unsigned minor)
 #define BPP_ICR      0x18
 #define BPP_SIZE     0x1A
 
-/* BPP_CSR.  Bits of type RW1 are cleared with writting '1'. */
+/* BPP_CSR.  Bits of type RW1 are cleared with writing '1'. */
 #define P_DEV_ID_MASK   0xf0000000      /* R   */
 #define P_DEV_ID_ZEBRA  0x40000000
 #define P_DEV_ID_L64854 0xa0000000      /*      == NCR 89C100+89C105. Pity. */
index 94d185829119bcd7e85a18b4cffd55d4046b4321..18d18f1a114ec9cdf8d4443bb236d0cb9b8e0208 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <asm/io.h>
 #include <asm/mostek.h>
 #include <asm/system.h>
index c3135e2fbd5ab804b1988b40e5f621431b3eb092..6afc7e5df0d4fef780dcf51d2557b82aa193add9 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
index 33682ce96a5d683cdc9d6e2687b2e95eaee43f20..3009ad8c407343d209e9b4d0a79639f0dbbfd4fe 100644 (file)
@@ -387,12 +387,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
         *      Ok now init the communication subsystem
         */
 
-       dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
+       dev->queues = kzalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
        if (dev->queues == NULL) {
                printk(KERN_ERR "Error could not allocate comm region.\n");
                return NULL;
        }
-       memset(dev->queues, 0, sizeof(struct aac_queue_block));
 
        if (aac_comm_init(dev)<0){
                kfree(dev->queues);
index 5824a757a7531aa9d71801486754cee84027a3f1..9aca57eda943664011d06863c309fd4178a58622 100644 (file)
@@ -1223,13 +1223,11 @@ int aac_check_health(struct aac_dev * aac)
                 * Warning: no sleep allowed while
                 * holding spinlock
                 */
-               hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
-               fib = kmalloc(sizeof(struct fib), GFP_ATOMIC);
+               hw_fib = kzalloc(sizeof(struct hw_fib), GFP_ATOMIC);
+               fib = kzalloc(sizeof(struct fib), GFP_ATOMIC);
                if (fib && hw_fib) {
                        struct aac_aifcmd * aif;
 
-                       memset(hw_fib, 0, sizeof(struct hw_fib));
-                       memset(fib, 0, sizeof(struct fib));
                        fib->hw_fib_va = hw_fib;
                        fib->dev = aac;
                        aac_fib_init(fib);
index 42c7dcda6d9bd1c9679cddcc8dd01bb0be00ae4c..fcd25f7d0bc636252074d535338d3c9f9e2e81f0 100644 (file)
@@ -248,16 +248,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
                 * manage the linked lists.
                 */
                if ((!dev->aif_thread)
-                || (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC))))
+                || (!(fib = kzalloc(sizeof(struct fib),GFP_ATOMIC))))
                        return 1;
-               if (!(hw_fib = kmalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
+               if (!(hw_fib = kzalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
                        kfree (fib);
                        return 1;
                }
-               memset(hw_fib, 0, sizeof(struct hw_fib));
                memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
                  (index & ~0x00000002L)), sizeof(struct hw_fib));
-               memset(fib, 0, sizeof(struct fib));
                INIT_LIST_HEAD(&fib->fiblink);
                fib->type = FSAFS_NTC_FIB_CONTEXT;
                fib->size = sizeof(struct fib);
index 0c71315cbf1aec8ed3df4f72bf8bb87d6a7f2cbc..291cd14f4e989737b0f54c289250a6cb006a67e0 100644 (file)
@@ -539,8 +539,10 @@ int _aac_rx_init(struct aac_dev *dev)
        }
 
        /* Failure to reset here is an option ... */
+       dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
+       dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
        dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
-       if ((((status & 0xff) != 0xff) || reset_devices) &&
+       if ((((status & 0x0c) != 0x0c) || reset_devices) &&
          !aac_rx_restart_adapter(dev, 0))
                ++restart;
        /*
index 9218f29314fa0edd69f8f2ac449a9463a31e8f3e..ad9761b237dc453890ac613a8497a83aa0da4834 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 8d72bbae96ad1a59a3777b662d8e47b640abc0c1..0bada0028aa0ba0c2081f79c4bdc99477754f6bc 100644 (file)
@@ -966,7 +966,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
                              |  AHD_BUSFREEREV_BUG;
                ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
 
-               /* If the user requested the the SLOWCRC bit to be set. */
+               /* If the user requested that the SLOWCRC bit to be set. */
                if (aic79xx_slowcrc)
                        ahd->features |= AHD_AIC79XXB_SLOWCRC;
 
index 85ae5d836fa4f0e715fd2794c7ed923edf1c2e01..8fee7edc6eb30dbd9281d4ee734f28a43377c65d 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index e6b70123940ce4dd7826feb4bd74bc25aa96a9bf..e78ce0fa44d2dd8c9d0eb8fe87ffd3141b9c2915 100644 (file)
@@ -6,7 +6,7 @@
 #
 # This file is licensed under GPLv2.
 #
-# This file is part of the the aic94xx driver.
+# This file is part of the aic94xx driver.
 #
 # The aic94xx driver is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
index 2a2cc6cf1182a9cdaa2ebf0df1c2b9e15b4b37e3..2311019304c00ef22ec4a8b63167a7c65c7dc488 100644 (file)
@@ -319,10 +319,9 @@ ch_readconfig(scsi_changer *ch)
        int     result,id,lun,i;
        u_int   elem;
 
-       buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+       buffer = kzalloc(512, GFP_KERNEL | GFP_DMA);
        if (!buffer)
                return -ENOMEM;
-       memset(buffer,0,512);
        
        memset(cmd,0,sizeof(cmd));
        cmd[0] = MODE_SENSE;
@@ -530,10 +529,9 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
        u_char  *buffer;
        int result;
 
-       buffer = kmalloc(512, GFP_KERNEL);
+       buffer = kzalloc(512, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
-       memset(buffer,0,512);
 
        dprintk("%s %s voltag: 0x%x => \"%s\"\n",
                clear     ? "clear"     : "set",
@@ -922,11 +920,10 @@ static int ch_probe(struct device *dev)
        if (sd->type != TYPE_MEDIUM_CHANGER)
                return -ENODEV;
     
-       ch = kmalloc(sizeof(*ch), GFP_KERNEL);
+       ch = kzalloc(sizeof(*ch), GFP_KERNEL);
        if (NULL == ch)
                return -ENOMEM;
 
-       memset(ch,0,sizeof(*ch));
        ch->minor = ch_devcount;
        sprintf(ch->name,"ch%d",ch->minor);
        mutex_init(&ch->lock);
index a965ed3548d5583fd2ac56d343b0e8d5a0f64d08..564ea90ed3a00a18cccb80b63799a236297dc579 100644 (file)
@@ -541,7 +541,7 @@ static struct ParameterData __devinitdata cfg_data[] = {
 
 
 /*
- * Safe settings. If set to zero the the BIOS/default values with
+ * Safe settings. If set to zero the BIOS/default values with
  * command line overrides will be used. If set to 1 then safe and
  * slow settings will be used.
  */
@@ -617,7 +617,7 @@ static void __devinit fix_settings(void)
 
 /*
  * Mapping from the eeprom delay index value (index into this array)
- * to the the number of actual seconds that the delay should be for.
+ * to the number of actual seconds that the delay should be for.
  */
 static char __devinitdata eeprom_index_to_delay_map[] = 
        { 1, 3, 5, 10, 16, 30, 60, 120 };
@@ -4136,7 +4136,7 @@ static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long
  * @io_port:   base I/O address
  * @addr:      offset into SEEPROM
  *
- * Returns the the byte read.
+ * Returns the byte read.
  **/
 static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
 {
index f7b9dbd64a96ee1ae0af28d786a12c1f7ef09574..8c7d2bbf9b1a848b90b19a2edd1663e0164c0a2b 100644 (file)
@@ -55,7 +55,6 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
 #include <linux/sched.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/dma-mapping.h>
 
 #include <linux/timer.h>
@@ -1309,13 +1308,12 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
                schedule_timeout_uninterruptible(1);
        } while (m == EMPTY_QUEUE);
 
-       status = kmalloc(4, GFP_KERNEL|ADDR32);
+       status = kzalloc(4, GFP_KERNEL|ADDR32);
        if(status == NULL) {
                adpt_send_nop(pHba, m);
                printk(KERN_ERR"IOP reset failed - no free memory.\n");
                return -ENOMEM;
        }
-       memset(status,0,4);
 
        msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
@@ -1505,21 +1503,19 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
                                        continue;
                                }
                                if( pHba->channel[bus_no].device[scsi_id] == NULL){
-                                       pDev =  kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev =  kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
                                        pHba->channel[bus_no].device[scsi_id] = pDev;
-                                       memset(pDev,0,sizeof(struct adpt_device));
                                } else {
                                        for( pDev = pHba->channel[bus_no].device[scsi_id];      
                                                        pDev->next_lun; pDev = pDev->next_lun){
                                        }
-                                       pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev->next_lun == NULL) {
                                                return -ENOMEM;
                                        }
-                                       memset(pDev->next_lun,0,sizeof(struct adpt_device));
                                        pDev = pDev->next_lun;
                                }
                                pDev->tid = tid;
@@ -1668,12 +1664,11 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
                reply_size = REPLY_FRAME_SIZE;
        }
        reply_size *= 4;
-       reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
+       reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
        if(reply == NULL) {
                printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
                return -ENOMEM;
        }
-       memset(reply,0,REPLY_FRAME_SIZE*4);
        sg_offset = (msg[0]>>4)&0xf;
        msg[2] = 0x40000000; // IOCTL context
        msg[3] = (u32)reply;
@@ -2445,7 +2440,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
                                }
                                pDev = pHba->channel[bus_no].device[scsi_id];   
                                if( pDev == NULL){
-                                       pDev =  kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev =  kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
@@ -2454,12 +2449,11 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
                                        while (pDev->next_lun) {
                                                pDev = pDev->next_lun;
                                        }
-                                       pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
                                }
-                               memset(pDev,0,sizeof(struct adpt_device));
                                pDev->tid = d->lct_data.tid;
                                pDev->scsi_channel = bus_no;
                                pDev->scsi_id = scsi_id;
index 99ce03331b649f41852269149d9b8df5619c2312..ec71061aef61165da0ef3c77ff58e66a260a34c8 100644 (file)
@@ -2212,7 +2212,7 @@ static void __devinit esp_init_swstate(struct esp *esp)
 }
 
 /* This places the ESP into a known state at boot time. */
-static void __devinit esp_bootup_reset(struct esp *esp)
+static void esp_bootup_reset(struct esp *esp)
 {
        u8 val;
 
index 6d223dd76440cc1cf8df4d5e2f82af7835512058..8ba7dd09d01d53e4cfc9bee44e94892f1b116243 100644 (file)
@@ -892,16 +892,16 @@ static int get_system_info(void)
        if (!rootdn)
                return -ENOENT;
 
-       model = get_property(rootdn, "model", NULL);
-       id = get_property(rootdn, "system-id", NULL);
+       model = of_get_property(rootdn, "model", NULL);
+       id = of_get_property(rootdn, "system-id", NULL);
        if (model && id)
                snprintf(system_id, sizeof(system_id), "%s-%s", model, id);
 
-       name = get_property(rootdn, "ibm,partition-name", NULL);
+       name = of_get_property(rootdn, "ibm,partition-name", NULL);
        if (name)
                strncpy(partition_name, name, sizeof(partition_name));
 
-       num = get_property(rootdn, "ibm,partition-no", NULL);
+       num = of_get_property(rootdn, "ibm,partition-no", NULL);
        if (num)
                partition_number = *num;
 
index 0a533f398f52482fa05537f375ebce744d1256b3..d8700aaa61144dd224d8744a76b8df9f3a32aa23 100644 (file)
@@ -162,11 +162,11 @@ static void gather_partition_info(void)
                return;
        }
 
-       ppartition_name = get_property(rootdn, "ibm,partition-name", NULL);
+       ppartition_name = of_get_property(rootdn, "ibm,partition-name", NULL);
        if (ppartition_name)
                strncpy(partition_name, ppartition_name,
                                sizeof(partition_name));
-       p_number_ptr = get_property(rootdn, "ibm,partition-no", NULL);
+       p_number_ptr = of_get_property(rootdn, "ibm,partition-no", NULL);
        if (p_number_ptr)
                partition_number = *p_number_ptr;
        of_node_put(rootdn);
index 2c7b77e833f993ff6d14d65820452d87dbaa8351..4baa79e686794ba5915717c2998860b6031fd91b 100644 (file)
@@ -92,6 +92,7 @@ static unsigned int ipr_fastfail = 0;
 static unsigned int ipr_transop_timeout = 0;
 static unsigned int ipr_enable_cache = 1;
 static unsigned int ipr_debug = 0;
+static unsigned int ipr_dual_ioa_raid = 1;
 static DEFINE_SPINLOCK(ipr_driver_lock);
 
 /* This table describes the differences between DMA controller chips */
@@ -158,6 +159,8 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0);
 MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
 module_param_named(debug, ipr_debug, int, 0);
 MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
+module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
+MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IPR_DRIVER_VERSION);
 
@@ -206,6 +209,8 @@ struct ipr_error_table_t ipr_error_table[] = {
        "8009: Impending cache battery pack failure"},
        {0x02040400, 0, 0,
        "34FF: Disk device format in progress"},
+       {0x02048000, 0, IPR_DEFAULT_LOG_LEVEL,
+       "9070: IOA requested reset"},
        {0x023F0000, 0, 0,
        "Synchronization required"},
        {0x024E0000, 0, 0,
@@ -950,6 +955,53 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
        }
 }
 
+/**
+ * strip_and_pad_whitespace - Strip and pad trailing whitespace.
+ * @i:         index into buffer
+ * @buf:               string to modify
+ *
+ * This function will strip all trailing whitespace, pad the end
+ * of the string with a single space, and NULL terminate the string.
+ *
+ * Return value:
+ *     new length of string
+ **/
+static int strip_and_pad_whitespace(int i, char *buf)
+{
+       while (i && buf[i] == ' ')
+               i--;
+       buf[i+1] = ' ';
+       buf[i+2] = '\0';
+       return i + 2;
+}
+
+/**
+ * ipr_log_vpd_compact - Log the passed extended VPD compactly.
+ * @prefix:            string to print at start of printk
+ * @hostrcb:   hostrcb pointer
+ * @vpd:               vendor/product id/sn struct
+ *
+ * Return value:
+ *     none
+ **/
+static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
+                               struct ipr_vpd *vpd)
+{
+       char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3];
+       int i = 0;
+
+       memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
+       i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer);
+
+       memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN);
+       i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer);
+
+       memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN);
+       buffer[IPR_SERIAL_NUM_LEN + i] = '\0';
+
+       ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer);
+}
+
 /**
  * ipr_log_vpd - Log the passed VPD to the error log.
  * @vpd:               vendor/product id/sn struct
@@ -973,6 +1025,23 @@ static void ipr_log_vpd(struct ipr_vpd *vpd)
        ipr_err("    Serial Number: %s\n", buffer);
 }
 
+/**
+ * ipr_log_ext_vpd_compact - Log the passed extended VPD compactly.
+ * @prefix:            string to print at start of printk
+ * @hostrcb:   hostrcb pointer
+ * @vpd:               vendor/product id/sn/wwn struct
+ *
+ * Return value:
+ *     none
+ **/
+static void ipr_log_ext_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
+                                   struct ipr_ext_vpd *vpd)
+{
+       ipr_log_vpd_compact(prefix, hostrcb, &vpd->vpd);
+       ipr_hcam_err(hostrcb, "%s WWN: %08X%08X\n", prefix,
+                    be32_to_cpu(vpd->wwid[0]), be32_to_cpu(vpd->wwid[1]));
+}
+
 /**
  * ipr_log_ext_vpd - Log the passed extended VPD to the error log.
  * @vpd:               vendor/product id/sn/wwn struct
@@ -1287,10 +1356,11 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
 
        error = &hostrcb->hcam.u.error.u.type_17_error;
        error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
+       strstrip(error->failure_reason);
 
-       ipr_err("%s\n", error->failure_reason);
-       ipr_err("Remote Adapter VPD:\n");
-       ipr_log_ext_vpd(&error->vpd);
+       ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
+                    be32_to_cpu(hostrcb->hcam.u.error.prc));
+       ipr_log_ext_vpd_compact("Remote IOA", hostrcb, &error->vpd);
        ipr_log_hex_data(ioa_cfg, error->data,
                         be32_to_cpu(hostrcb->hcam.length) -
                         (offsetof(struct ipr_hostrcb_error, u) +
@@ -1312,10 +1382,11 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
 
        error = &hostrcb->hcam.u.error.u.type_07_error;
        error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
+       strstrip(error->failure_reason);
 
-       ipr_err("%s\n", error->failure_reason);
-       ipr_err("Remote Adapter VPD:\n");
-       ipr_log_vpd(&error->vpd);
+       ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
+                    be32_to_cpu(hostrcb->hcam.u.error.prc));
+       ipr_log_vpd_compact("Remote IOA", hostrcb, &error->vpd);
        ipr_log_hex_data(ioa_cfg, error->data,
                         be32_to_cpu(hostrcb->hcam.length) -
                         (offsetof(struct ipr_hostrcb_error, u) +
@@ -1672,12 +1743,15 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
        u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc);
 
        list_del(&hostrcb->queue);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 
        if (!ioasc) {
                ipr_handle_log_data(ioa_cfg, hostrcb);
+               if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED)
+                       ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
        } else if (ioasc != IPR_IOASC_IOA_WAS_RESET) {
                dev_err(&ioa_cfg->pdev->dev,
                        "Host RCB failed with IOASC: 0x%08X\n", ioasc);
@@ -2635,8 +2709,13 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       while(ioa_cfg->in_reset_reload) {
+               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+               wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+               spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       }
+
        ioa_cfg->errors_logged = 0;
        ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NORMAL);
 
@@ -2958,6 +3037,11 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
        unsigned long lock_flags;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       while(ioa_cfg->in_reset_reload) {
+               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+               wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+               spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       }
 
        if (ioa_cfg->ucode_sglist) {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4656,18 +4740,19 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
        struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
        u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK;
 
        if (!res) {
                ipr_scsi_eh_done(ipr_cmd);
                return;
        }
 
-       if (!ipr_is_gscsi(res))
+       if (!ipr_is_gscsi(res) && masked_ioasc != IPR_IOASC_HW_DEV_BUS_STATUS)
                ipr_gen_sense(ipr_cmd);
 
        ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
 
-       switch (ioasc & IPR_IOASC_IOASC_MASK) {
+       switch (masked_ioasc) {
        case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
                if (ipr_is_naca_model(res))
                        scsi_cmd->result |= (DID_ABORT << 16);
@@ -5363,6 +5448,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
                        ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb);
        }
 
+       scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS);
        dev_info(&ioa_cfg->pdev->dev, "IOA initialized.\n");
 
        ioa_cfg->reset_retries = 0;
@@ -5798,6 +5884,94 @@ static int ipr_ioafp_mode_sense_page28(struct ipr_cmnd *ipr_cmd)
        return IPR_RC_JOB_RETURN;
 }
 
+/**
+ * ipr_ioafp_mode_select_page24 - Issue Mode Select to IOA
+ * @ipr_cmd:   ipr command struct
+ *
+ * This function enables dual IOA RAID support if possible.
+ *
+ * Return value:
+ *     IPR_RC_JOB_RETURN
+ **/
+static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       struct ipr_mode_pages *mode_pages = &ioa_cfg->vpd_cbs->mode_pages;
+       struct ipr_mode_page24 *mode_page;
+       int length;
+
+       ENTER;
+       mode_page = ipr_get_mode_page(mode_pages, 0x24,
+                                     sizeof(struct ipr_mode_page24));
+
+       if (mode_page)
+               mode_page->flags |= IPR_ENABLE_DUAL_IOA_AF;
+
+       length = mode_pages->hdr.length + 1;
+       mode_pages->hdr.length = 0;
+
+       ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11,
+                             ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages),
+                             length);
+
+       ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
+       ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT);
+
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
+/**
+ * ipr_reset_mode_sense_page24_failed - Handle failure of IOAFP mode sense
+ * @ipr_cmd:   ipr command struct
+ *
+ * This function handles the failure of a Mode Sense to the IOAFP.
+ * Some adapters do not handle all mode pages.
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd)
+{
+       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+
+       if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
+               ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
+               return IPR_RC_JOB_CONTINUE;
+       }
+
+       return ipr_reset_cmd_failed(ipr_cmd);
+}
+
+/**
+ * ipr_ioafp_mode_sense_page24 - Issue Page 24 Mode Sense to IOA
+ * @ipr_cmd:   ipr command struct
+ *
+ * This function send a mode sense to the IOA to retrieve
+ * the IOA Advanced Function Control mode page.
+ *
+ * Return value:
+ *     IPR_RC_JOB_RETURN
+ **/
+static int ipr_ioafp_mode_sense_page24(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+       ENTER;
+       ipr_build_mode_sense(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE),
+                            0x24, ioa_cfg->vpd_cbs_dma +
+                            offsetof(struct ipr_misc_cbs, mode_pages),
+                            sizeof(struct ipr_mode_pages));
+
+       ipr_cmd->job_step = ipr_ioafp_mode_select_page24;
+       ipr_cmd->job_step_failed = ipr_reset_mode_sense_page24_failed;
+
+       ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT);
+
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
 /**
  * ipr_init_res_table - Initialize the resource table
  * @ipr_cmd:   ipr command struct
@@ -5866,7 +6040,10 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
                }
        }
 
-       ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
+       if (ioa_cfg->dual_raid && ipr_dual_ioa_raid)
+               ipr_cmd->job_step = ipr_ioafp_mode_sense_page24;
+       else
+               ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
 
        LEAVE;
        return IPR_RC_JOB_CONTINUE;
@@ -5888,8 +6065,11 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
        struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
        struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data;
+       struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
 
        ENTER;
+       if (cap->cap & IPR_CAP_DUAL_IOA_RAID)
+               ioa_cfg->dual_raid = 1;
        dev_info(&ioa_cfg->pdev->dev, "Adapter firmware version: %02X%02X%02X%02X\n",
                 ucode_vpd->major_release, ucode_vpd->card_type,
                 ucode_vpd->minor_release[0], ucode_vpd->minor_release[1]);
@@ -5972,6 +6152,37 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page)
        return 0;
 }
 
+/**
+ * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter.
+ * @ipr_cmd:   ipr command struct
+ *
+ * This function sends a Page 0xD0 inquiry to the adapter
+ * to retrieve adapter capabilities.
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data;
+       struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
+
+       ENTER;
+       ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+       memset(cap, 0, sizeof(*cap));
+
+       if (ipr_inquiry_page_supported(page0, 0xD0)) {
+               ipr_ioafp_inquiry(ipr_cmd, 1, 0xD0,
+                                 ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, cap),
+                                 sizeof(struct ipr_inquiry_cap));
+               return IPR_RC_JOB_RETURN;
+       }
+
+       LEAVE;
+       return IPR_RC_JOB_CONTINUE;
+}
+
 /**
  * ipr_ioafp_page3_inquiry - Send a Page 3 Inquiry to the adapter.
  * @ipr_cmd:   ipr command struct
@@ -5992,7 +6203,7 @@ static int ipr_ioafp_page3_inquiry(struct ipr_cmnd *ipr_cmd)
        if (!ipr_inquiry_page_supported(page0, 1))
                ioa_cfg->cache_state = CACHE_NONE;
 
-       ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+       ipr_cmd->job_step = ipr_ioafp_cap_inquiry;
 
        ipr_ioafp_inquiry(ipr_cmd, 1, 3,
                          ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, page3_data),
@@ -6278,6 +6489,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
        struct ipr_hostrcb *hostrcb;
        struct ipr_uc_sdt sdt;
        int rc, length;
+       u32 ioasc;
 
        mailbox = readl(ioa_cfg->ioa_mailbox);
 
@@ -6310,9 +6522,13 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
                                        (__be32 *)&hostrcb->hcam,
                                        min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32));
 
-       if (!rc)
+       if (!rc) {
                ipr_handle_log_data(ioa_cfg, hostrcb);
-       else
+               ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc);
+               if (ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED &&
+                   ioa_cfg->sdt_state == GET_DUMP)
+                       ioa_cfg->sdt_state = WAIT_FOR_DUMP;
+       } else
                ipr_unit_check_no_data(ioa_cfg);
 
        list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
@@ -6424,6 +6640,48 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
        return rc;
 }
 
+/**
+ * ipr_reset_slot_reset_done - Clear PCI reset to the adapter
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This clears PCI reset to the adapter and delays two seconds.
+ *
+ * Return value:
+ *     IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd)
+{
+       ENTER;
+       pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset);
+       ipr_cmd->job_step = ipr_reset_bist_done;
+       ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
+/**
+ * ipr_reset_slot_reset - Reset the PCI slot of the adapter.
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This asserts PCI reset to the adapter.
+ *
+ * Return value:
+ *     IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       struct pci_dev *pdev = ioa_cfg->pdev;
+
+       ENTER;
+       pci_block_user_cfg_access(pdev);
+       pci_set_pcie_reset_state(pdev, pcie_warm_reset);
+       ipr_cmd->job_step = ipr_reset_slot_reset_done;
+       ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
 /**
  * ipr_reset_allowed - Query whether or not IOA can be reset
  * @ioa_cfg:   ioa config struct
@@ -6463,7 +6721,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
                ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
                ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
        } else {
-               ipr_cmd->job_step = ipr_reset_start_bist;
+               ipr_cmd->job_step = ioa_cfg->reset;
                rc = IPR_RC_JOB_CONTINUE;
        }
 
@@ -6496,7 +6754,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
                writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg);
                ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
        } else {
-               ipr_cmd->job_step = ipr_reset_start_bist;
+               ipr_cmd->job_step = ioa_cfg->reset;
        }
 
        ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
@@ -6591,12 +6849,14 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd)
                ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN;
                ipr_cmd->ioarcb.cmd_pkt.cdb[1] = shutdown_type;
 
-               if (shutdown_type == IPR_SHUTDOWN_ABBREV)
-                       timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT;
+               if (shutdown_type == IPR_SHUTDOWN_NORMAL)
+                       timeout = IPR_SHUTDOWN_TIMEOUT;
                else if (shutdown_type == IPR_SHUTDOWN_PREPARE_FOR_NORMAL)
                        timeout = IPR_INTERNAL_TIMEOUT;
+               else if (ioa_cfg->dual_raid && ipr_dual_ioa_raid)
+                       timeout = IPR_DUAL_IOA_ABBR_SHUTDOWN_TO;
                else
-                       timeout = IPR_SHUTDOWN_TIMEOUT;
+                       timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT;
 
                ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, timeout);
 
@@ -6776,8 +7036,11 @@ static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev)
        struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
-       _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space,
-                                        IPR_SHUTDOWN_NONE);
+       if (ioa_cfg->needs_warm_reset)
+               ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
+       else
+               _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space,
+                                       IPR_SHUTDOWN_NONE);
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
        return PCI_ERS_RESULT_RECOVERED;
 }
@@ -7226,7 +7489,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        unsigned long ipr_regs_pci;
        void __iomem *ipr_regs;
        int rc = PCIBIOS_SUCCESSFUL;
-       volatile u32 mask, uproc;
+       volatile u32 mask, uproc, interrupts;
 
        ENTER;
 
@@ -7265,6 +7528,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        else
                ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
 
+       rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
+
+       if (rc != PCIBIOS_SUCCESSFUL) {
+               dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
+               rc = -EIO;
+               goto out_scsi_host_put;
+       }
+
        ipr_regs_pci = pci_resource_start(pdev, 0);
 
        rc = pci_request_regions(pdev, IPR_NAME);
@@ -7333,9 +7604,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
         * the card is in an unknown state and needs a hard reset
         */
        mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+       interrupts = readl(ioa_cfg->regs.sense_interrupt_reg);
        uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
        if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
                ioa_cfg->needs_hard_reset = 1;
+       if (interrupts & IPR_PCII_ERROR_INTERRUPTS)
+               ioa_cfg->needs_hard_reset = 1;
+       if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
+               ioa_cfg->ioa_unit_checked = 1;
 
        ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
        rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg);
@@ -7346,6 +7622,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
                goto cleanup_nolog;
        }
 
+       if ((dev_id->driver_data & IPR_USE_PCI_WARM_RESET) ||
+           (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) {
+               ioa_cfg->needs_warm_reset = 1;
+               ioa_cfg->reset = ipr_reset_slot_reset;
+       } else
+               ioa_cfg->reset = ipr_reset_start_bist;
+
        spin_lock(&ipr_driver_lock);
        list_add_tail(&ioa_cfg->queue, &ipr_ioa_head);
        spin_unlock(&ipr_driver_lock);
@@ -7428,6 +7711,12 @@ static void __ipr_remove(struct pci_dev *pdev)
        ENTER;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
+       while(ioa_cfg->in_reset_reload) {
+               spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
+               wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+               spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
+       }
+
        ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
 
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
@@ -7551,6 +7840,12 @@ static void ipr_shutdown(struct pci_dev *pdev)
        unsigned long lock_flags = 0;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       while(ioa_cfg->in_reset_reload) {
+               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+               wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+               spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       }
+
        ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
        wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
@@ -7577,19 +7872,22 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
              IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT},
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
              IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
              IPR_USE_LONG_TRANSOP_TIMEOUT },
@@ -7597,7 +7895,7 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
-             IPR_USE_LONG_TRANSOP_TIMEOUT },
+             IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
@@ -7627,6 +7925,7 @@ static struct pci_driver ipr_driver = {
        .remove = ipr_remove,
        .shutdown = ipr_shutdown,
        .err_handler = &ipr_err_handler,
+       .dynids.use_driver_data = 1
 };
 
 /**
index bc53d7cebe0ac645e654b34889e9fb0c4cfbd9f5..d93156671e93d7155505098242f821a46c1ed973 100644 (file)
@@ -37,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.3.2"
-#define IPR_DRIVER_DATE "(March 23, 2007)"
+#define IPR_DRIVER_VERSION "2.4.1"
+#define IPR_DRIVER_DATE "(April 24, 2007)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -91,6 +91,7 @@
  * IOASCs
  */
 #define IPR_IOASC_NR_INIT_CMD_REQUIRED         0x02040200
+#define IPR_IOASC_NR_IOA_RESET_REQUIRED                0x02048000
 #define IPR_IOASC_SYNC_REQUIRED                        0x023f0000
 #define IPR_IOASC_MED_DO_NOT_REALLOC           0x03110C00
 #define IPR_IOASC_HW_SEL_TIMEOUT                       0x04050000
 
 /* Driver data flags */
 #define IPR_USE_LONG_TRANSOP_TIMEOUT           0x00000001
+#define IPR_USE_PCI_WARM_RESET                 0x00000002
 
 #define IPR_DEFAULT_MAX_ERROR_DUMP                     984
 #define IPR_NUM_LOG_HCAMS                              2
 #define IPR_SHUTDOWN_TIMEOUT                   (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ)
 #define IPR_VSET_RW_TIMEOUT                    (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ)
 #define IPR_ABBREV_SHUTDOWN_TIMEOUT            (10 * HZ)
+#define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO  (2 * 60 * HZ)
 #define IPR_DEVICE_RESET_TIMEOUT               (ipr_fastfail ? 10 * HZ : 30 * HZ)
 #define IPR_CANCEL_ALL_TIMEOUT         (ipr_fastfail ? 10 * HZ : 30 * HZ)
 #define IPR_ABORT_TASK_TIMEOUT         (ipr_fastfail ? 10 * HZ : 30 * HZ)
 #define IPR_WAIT_FOR_RESET_TIMEOUT             (2 * HZ)
 #define IPR_CHECK_FOR_RESET_TIMEOUT            (HZ / 10)
 #define IPR_WAIT_FOR_BIST_TIMEOUT              (2 * HZ)
+#define IPR_PCI_RESET_TIMEOUT                  (HZ / 2)
 #define IPR_DUMP_TIMEOUT                       (15 * HZ)
 
 /*
@@ -602,6 +606,12 @@ struct ipr_mode_page28 {
        struct ipr_dev_bus_entry bus[0];
 }__attribute__((packed));
 
+struct ipr_mode_page24 {
+       struct ipr_mode_page_hdr hdr;
+       u8 flags;
+#define IPR_ENABLE_DUAL_IOA_AF 0x80
+}__attribute__((packed));
+
 struct ipr_ioa_vpd {
        struct ipr_std_inq_data std_inq_data;
        u8 ascii_part_num[12];
@@ -624,6 +634,19 @@ struct ipr_inquiry_page3 {
        u8 patch_number[4];
 }__attribute__((packed));
 
+struct ipr_inquiry_cap {
+       u8 peri_qual_dev_type;
+       u8 page_code;
+       u8 reserved1;
+       u8 page_length;
+       u8 ascii_len;
+       u8 reserved2;
+       u8 sis_version[2];
+       u8 cap;
+#define IPR_CAP_DUAL_IOA_RAID          0x80
+       u8 reserved3[15];
+}__attribute__((packed));
+
 #define IPR_INQUIRY_PAGE0_ENTRIES 20
 struct ipr_inquiry_page0 {
        u8 peri_qual_dev_type;
@@ -962,6 +985,7 @@ struct ipr_misc_cbs {
        struct ipr_ioa_vpd ioa_vpd;
        struct ipr_inquiry_page0 page0_data;
        struct ipr_inquiry_page3 page3_data;
+       struct ipr_inquiry_cap cap;
        struct ipr_mode_pages mode_pages;
        struct ipr_supported_device supp_dev;
 };
@@ -1068,6 +1092,10 @@ struct ipr_ioa_cfg {
        u8 allow_cmds:1;
        u8 allow_ml_add_del:1;
        u8 needs_hard_reset:1;
+       u8 dual_raid:1;
+       u8 needs_warm_reset:1;
+
+       u8 revid;
 
        enum ipr_cache_state cache_state;
        u16 type; /* CCIN of the card */
@@ -1161,6 +1189,7 @@ struct ipr_ioa_cfg {
        struct pci_pool *ipr_cmd_pool;
 
        struct ipr_cmnd *reset_cmd;
+       int (*reset) (struct ipr_cmnd *);
 
        struct ata_host ata_host;
        char ipr_cmd_label[8];
index 897a5e2c55e438a806c6e93072547a7386922832..b4b52694497c16312d87ed2d2203e55ad630ff07 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/kthread.h>
+
 #include "sas_internal.h"
 
 #include <scsi/scsi_host.h>
@@ -184,7 +186,7 @@ static int sas_queue_up(struct sas_task *task)
        list_add_tail(&task->list, &core->task_queue);
        core->task_queue_size += 1;
        spin_unlock_irqrestore(&core->task_queue_lock, flags);
-       up(&core->queue_thread_sema);
+       wake_up_process(core->queue_thread);
 
        return 0;
 }
@@ -819,7 +821,7 @@ static void sas_queue(struct sas_ha_struct *sas_ha)
        struct sas_internal *i = to_sas_internal(core->shost->transportt);
 
        spin_lock_irqsave(&core->task_queue_lock, flags);
-       while (!core->queue_thread_kill &&
+       while (!kthread_should_stop() &&
               !list_empty(&core->task_queue)) {
 
                can_queue = sas_ha->lldd_queue_size - core->task_queue_size;
@@ -858,8 +860,6 @@ static void sas_queue(struct sas_ha_struct *sas_ha)
        spin_unlock_irqrestore(&core->task_queue_lock, flags);
 }
 
-static DECLARE_COMPLETION(queue_th_comp);
-
 /**
  * sas_queue_thread -- The Task Collector thread
  * @_sas_ha: pointer to struct sas_ha
@@ -867,40 +867,33 @@ static DECLARE_COMPLETION(queue_th_comp);
 static int sas_queue_thread(void *_sas_ha)
 {
        struct sas_ha_struct *sas_ha = _sas_ha;
-       struct scsi_core *core = &sas_ha->core;
 
-       daemonize("sas_queue_%d", core->shost->host_no);
        current->flags |= PF_NOFREEZE;
 
-       complete(&queue_th_comp);
-
        while (1) {
-               down_interruptible(&core->queue_thread_sema);
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
                sas_queue(sas_ha);
-               if (core->queue_thread_kill)
+               if (kthread_should_stop())
                        break;
        }
 
-       complete(&queue_th_comp);
-
        return 0;
 }
 
 int sas_init_queue(struct sas_ha_struct *sas_ha)
 {
-       int res;
        struct scsi_core *core = &sas_ha->core;
 
        spin_lock_init(&core->task_queue_lock);
        core->task_queue_size = 0;
        INIT_LIST_HEAD(&core->task_queue);
-       init_MUTEX_LOCKED(&core->queue_thread_sema);
 
-       res = kernel_thread(sas_queue_thread, sas_ha, 0);
-       if (res >= 0)
-               wait_for_completion(&queue_th_comp);
-
-       return res < 0 ? res : 0;
+       core->queue_thread = kthread_run(sas_queue_thread, sas_ha,
+                                        "sas_queue_%d", core->shost->host_no);
+       if (IS_ERR(core->queue_thread))
+               return PTR_ERR(core->queue_thread);
+       return 0;
 }
 
 void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
@@ -909,10 +902,7 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
        struct scsi_core *core = &sas_ha->core;
        struct sas_task *task, *n;
 
-       init_completion(&queue_th_comp);
-       core->queue_thread_kill = 1;
-       up(&core->queue_thread_sema);
-       wait_for_completion(&queue_th_comp);
+       kthread_stop(core->queue_thread);
 
        if (!list_empty(&core->task_queue))
                SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n",
index a7de0bca5bdd31efd19b2683e95feaa39e7aadcd..82e8f90c46178472c3cb24243250dea996cdcd46 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -27,10 +27,6 @@ struct lpfc_sli2_slim;
                                           requests */
 #define LPFC_MAX_NS_RETRY      3       /* Number of retry attempts to contact
                                           the NameServer  before giving up. */
-#define LPFC_DFT_HBA_Q_DEPTH   2048    /* max cmds per hba */
-#define LPFC_LC_HBA_Q_DEPTH    1024    /* max cmds per low cost hba */
-#define LPFC_LP101_HBA_Q_DEPTH 128     /* max cmds per low cost hba */
-
 #define LPFC_CMD_PER_LUN       3       /* max outstanding cmds per lun */
 #define LPFC_SG_SEG_CNT                64      /* sg element count per scsi cmnd */
 #define LPFC_IOCB_LIST_CNT     2250    /* list of IOCBs for fast-path usage. */
@@ -244,28 +240,23 @@ struct lpfc_hba {
 #define FC_FABRIC               0x100  /* We are fabric attached */
 #define FC_ESTABLISH_LINK       0x200  /* Reestablish Link */
 #define FC_RSCN_DISCOVERY       0x400  /* Authenticate all devices after RSCN*/
+#define FC_BLOCK_MGMT_IO        0x800   /* Don't allow mgmt mbx or iocb cmds */
 #define FC_LOADING             0x1000  /* HBA in process of loading drvr */
 #define FC_UNLOADING           0x2000  /* HBA in process of unloading drvr */
 #define FC_SCSI_SCAN_TMO        0x4000 /* scsi scan timer running */
 #define FC_ABORT_DISCOVERY      0x8000 /* we want to abort discovery */
 #define FC_NDISC_ACTIVE         0x10000        /* NPort discovery active */
 #define FC_BYPASSED_MODE        0x20000        /* NPort is in bypassed mode */
+#define FC_LOOPBACK_MODE        0x40000        /* NPort is in Loopback mode */
+                                       /* This flag is set while issuing */
+                                       /* INIT_LINK mailbox command */
+#define FC_IGNORE_ERATT         0x80000        /* intr handler should ignore ERATT */
 
        uint32_t fc_topology;   /* link topology, from LINK INIT */
 
        struct lpfc_stats fc_stat;
 
-       /* These are the head/tail pointers for the bind, plogi, adisc, unmap,
-        *  and map lists.  Their counters are immediately following.
-        */
-       struct list_head fc_plogi_list;
-       struct list_head fc_adisc_list;
-       struct list_head fc_reglogin_list;
-       struct list_head fc_prli_list;
-       struct list_head fc_nlpunmap_list;
-       struct list_head fc_nlpmap_list;
-       struct list_head fc_npr_list;
-       struct list_head fc_unused_list;
+       struct list_head fc_nodes;
 
        /* Keep counters for the number of entries in each list. */
        uint16_t fc_plogi_cnt;
@@ -387,13 +378,17 @@ struct lpfc_hba {
 
        mempool_t *mbox_mem_pool;
        mempool_t *nlp_mem_pool;
-       struct list_head freebufList;
-       struct list_head ctrspbuflist;
-       struct list_head rnidrspbuflist;
 
        struct fc_host_statistics link_stats;
 };
 
+static inline void
+lpfc_set_loopback_flag(struct lpfc_hba *phba) {
+       if (phba->cfg_topology == FLAGS_LOCAL_LB)
+               phba->fc_flag |= FC_LOOPBACK_MODE;
+       else
+               phba->fc_flag &= ~FC_LOOPBACK_MODE;
+}
 
 struct rnidrsp {
        void *buf;
index f247e786af99487cda664cae44193adec19af7b3..95fe77e816f80a756b937f6012b8ab989e14ac74 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -20,6 +20,7 @@
  *******************************************************************/
 
 #include <linux/ctype.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -213,6 +214,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
        int mbxstatus = MBXERR_ERROR;
 
        if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+           (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
            (phba->hba_state != LPFC_HBA_READY))
                return -EPERM;
 
@@ -235,6 +237,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
                                                     phba->fc_ratov * 2);
        }
 
+       lpfc_set_loopback_flag(phba);
        if (mbxstatus == MBX_TIMEOUT)
                pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
        else
@@ -247,19 +250,62 @@ lpfc_issue_lip(struct Scsi_Host *host)
 }
 
 static int
-lpfc_selective_reset(struct lpfc_hba *phba)
+lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
 {
        struct completion online_compl;
+       struct lpfc_sli_ring *pring;
+       struct lpfc_sli *psli;
        int status = 0;
+       int cnt = 0;
+       int i;
 
        init_completion(&online_compl);
        lpfc_workq_post_event(phba, &status, &online_compl,
-                             LPFC_EVT_OFFLINE);
+                             LPFC_EVT_OFFLINE_PREP);
+       wait_for_completion(&online_compl);
+
+       if (status != 0)
+               return -EIO;
+
+       psli = &phba->sli;
+
+       for (i = 0; i < psli->num_rings; i++) {
+               pring = &psli->ring[i];
+               /* The linkdown event takes 30 seconds to timeout. */
+               while (pring->txcmplq_cnt) {
+                       msleep(10);
+                       if (cnt++ > 3000) {
+                               lpfc_printf_log(phba,
+                                       KERN_WARNING, LOG_INIT,
+                                       "%d:0466 Outstanding IO when "
+                                       "bringing Adapter offline\n",
+                                       phba->brd_no);
+                               break;
+                       }
+               }
+       }
+
+       init_completion(&online_compl);
+       lpfc_workq_post_event(phba, &status, &online_compl, type);
        wait_for_completion(&online_compl);
 
        if (status != 0)
                return -EIO;
 
+       return 0;
+}
+
+static int
+lpfc_selective_reset(struct lpfc_hba *phba)
+{
+       struct completion online_compl;
+       int status = 0;
+
+       status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
+
+       if (status != 0)
+               return status;
+
        init_completion(&online_compl);
        lpfc_workq_post_event(phba, &status, &online_compl,
                              LPFC_EVT_ONLINE);
@@ -324,23 +370,19 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
 
        init_completion(&online_compl);
 
-       if(strncmp(buf, "online", sizeof("online") - 1) == 0)
+       if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
                lpfc_workq_post_event(phba, &status, &online_compl,
                                      LPFC_EVT_ONLINE);
-       else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
-               lpfc_workq_post_event(phba, &status, &online_compl,
-                                     LPFC_EVT_OFFLINE);
+               wait_for_completion(&online_compl);
+       } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
+               status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
        else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
-               lpfc_workq_post_event(phba, &status, &online_compl,
-                                     LPFC_EVT_WARM_START);
-       else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
-               lpfc_workq_post_event(phba, &status, &online_compl,
-                                     LPFC_EVT_KILL);
+               status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
+       else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
+               status = lpfc_do_offline(phba, LPFC_EVT_KILL);
        else
                return -EINVAL;
 
-       wait_for_completion(&online_compl);
-
        if (!status)
                return strlen(buf);
        else
@@ -645,9 +687,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
        dev_printk(KERN_NOTICE, &phba->pcidev->dev,
                   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
 
-       init_completion(&online_compl);
-       lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE);
-       wait_for_completion(&online_compl);
+       stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
        if (stat1)
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "%d:0463 lpfc_soft_wwpn attribute set failed to reinit "
@@ -789,6 +829,18 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val)
        return -EINVAL;
 }
 
+static void
+lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
+{
+       struct lpfc_nodelist  *ndlp;
+
+       spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
+               if (ndlp->rport)
+                       ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
+       spin_unlock_irq(phba->host->host_lock);
+}
+
 static int
 lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
 {
@@ -804,6 +856,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
        if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
                phba->cfg_nodev_tmo = val;
                phba->cfg_devloss_tmo = val;
+               lpfc_update_rport_devloss_tmo(phba);
                return 0;
        }
 
@@ -839,6 +892,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val)
                phba->cfg_nodev_tmo = val;
                phba->cfg_devloss_tmo = val;
                phba->dev_loss_tmo_changed = 1;
+               lpfc_update_rport_devloss_tmo(phba);
                return 0;
        }
 
@@ -931,9 +985,10 @@ LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology");
 #       1  = 1 Gigabaud
 #       2  = 2 Gigabaud
 #       4  = 4 Gigabaud
-# Value range is [0,4]. Default value is 0.
+#       8  = 8 Gigabaud
+# Value range is [0,8]. Default value is 0.
 */
-LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed");
+LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed");
 
 /*
 # lpfc_fcp_class:  Determines FC class to use for the FCP protocol.
@@ -958,7 +1013,7 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
 /*
 # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
 # cr_delay (msec) or cr_count outstanding commands. cr_delay can take
-# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay
+# value [0,63]. cr_count can take value [1,255]. Default value of cr_delay
 # is 0. Default value of cr_count is 1. The cr_count feature is disabled if
 # cr_delay is set to 0.
 */
@@ -1227,11 +1282,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
        struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
        int rc;
 
-       if (off > sizeof(MAILBOX_t))
+       if (off > MAILBOX_CMD_SIZE)
                return -ERANGE;
 
-       if ((count + off) > sizeof(MAILBOX_t))
-               count = sizeof(MAILBOX_t) - off;
+       if ((count + off) > MAILBOX_CMD_SIZE)
+               count = MAILBOX_CMD_SIZE - off;
 
        if (off % 4 ||  count % 4 || (unsigned long)buf % 4)
                return -EINVAL;
@@ -1307,6 +1362,12 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
                        return -EPERM;
                }
 
+               if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
+                       sysfs_mbox_idle(phba);
+                       spin_unlock_irq(host->host_lock);
+                       return  -EAGAIN;
+               }
+
                if ((phba->fc_flag & FC_OFFLINE_MODE) ||
                    (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
 
@@ -1326,6 +1387,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
                }
 
                if (rc != MBX_SUCCESS) {
+                       if (rc == MBX_TIMEOUT) {
+                               phba->sysfs_mbox.mbox->mbox_cmpl =
+                                       lpfc_sli_def_mbox_cmpl;
+                               phba->sysfs_mbox.mbox = NULL;
+                       }
                        sysfs_mbox_idle(phba);
                        spin_unlock_irq(host->host_lock);
                        return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
@@ -1344,7 +1410,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        phba->sysfs_mbox.offset = off + count;
 
-       if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t))
+       if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
                sysfs_mbox_idle(phba);
 
        spin_unlock_irq(phba->host->host_lock);
@@ -1358,7 +1424,7 @@ static struct bin_attribute sysfs_mbox_attr = {
                .mode = S_IRUSR | S_IWUSR,
                .owner = THIS_MODULE,
        },
-       .size = sizeof(MAILBOX_t),
+       .size = MAILBOX_CMD_SIZE,
        .read = sysfs_mbox_read,
        .write = sysfs_mbox_write,
 };
@@ -1494,6 +1560,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
                        case LA_4GHZ_LINK:
                                fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
                        break;
+                       case LA_8GHZ_LINK:
+                               fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+                       break;
                        default:
                                fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
                        break;
@@ -1546,6 +1615,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
        unsigned long seconds;
        int rc = 0;
 
+       if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+               return NULL;
+
        pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmboxq)
                return NULL;
@@ -1631,6 +1703,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
        else
                hs->seconds_since_last_reset = seconds - psli->stats_start;
 
+       mempool_free(pmboxq, phba->mbox_mem_pool);
+
        return hs;
 }
 
@@ -1644,6 +1718,9 @@ lpfc_reset_stats(struct Scsi_Host *shost)
        MAILBOX_t *pmb;
        int rc = 0;
 
+       if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+               return;
+
        pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmboxq)
                return;
@@ -1699,6 +1776,8 @@ lpfc_reset_stats(struct Scsi_Host *shost)
 
        psli->stats_start = get_seconds();
 
+       mempool_free(pmboxq, phba->mbox_mem_pool);
+
        return;
 }
 
@@ -1706,67 +1785,51 @@ lpfc_reset_stats(struct Scsi_Host *shost)
  * The LPFC driver treats linkdown handling as target loss events so there
  * are no sysfs handlers for link_down_tmo.
  */
-static void
-lpfc_get_starget_port_id(struct scsi_target *starget)
+
+static struct lpfc_nodelist *
+lpfc_get_node_by_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
-       uint32_t did = -1;
-       struct lpfc_nodelist *ndlp = NULL;
+       struct lpfc_nodelist *ndlp;
 
        spin_lock_irq(shost->host_lock);
-       /* Search the mapped list for this target ID */
-       list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
-               if (starget->id == ndlp->nlp_sid) {
-                       did = ndlp->nlp_DID;
-                       break;
+       /* Search for this, mapped, target ID */
+       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
+                   starget->id == ndlp->nlp_sid) {
+                       spin_unlock_irq(shost->host_lock);
+                       return ndlp;
                }
        }
        spin_unlock_irq(shost->host_lock);
+       return NULL;
+}
+
+static void
+lpfc_get_starget_port_id(struct scsi_target *starget)
+{
+       struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
 
-       fc_starget_port_id(starget) = did;
+       fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1;
 }
 
 static void
 lpfc_get_starget_node_name(struct scsi_target *starget)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
-       u64 node_name = 0;
-       struct lpfc_nodelist *ndlp = NULL;
-
-       spin_lock_irq(shost->host_lock);
-       /* Search the mapped list for this target ID */
-       list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
-               if (starget->id == ndlp->nlp_sid) {
-                       node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
-                       break;
-               }
-       }
-       spin_unlock_irq(shost->host_lock);
+       struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
 
-       fc_starget_node_name(starget) = node_name;
+       fc_starget_node_name(starget) =
+               ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0;
 }
 
 static void
 lpfc_get_starget_port_name(struct scsi_target *starget)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
-       u64 port_name = 0;
-       struct lpfc_nodelist *ndlp = NULL;
-
-       spin_lock_irq(shost->host_lock);
-       /* Search the mapped list for this target ID */
-       list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
-               if (starget->id == ndlp->nlp_sid) {
-                       port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
-                       break;
-               }
-       }
-       spin_unlock_irq(shost->host_lock);
+       struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
 
-       fc_starget_port_name(starget) = port_name;
+       fc_starget_port_name(starget) =
+               ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
 }
 
 static void
@@ -1895,25 +1958,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
                        sizeof(struct fcp_rsp) +
                        (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64));
 
-       switch (phba->pcidev->device) {
-       case PCI_DEVICE_ID_LP101:
-       case PCI_DEVICE_ID_BSMB:
-       case PCI_DEVICE_ID_ZSMB:
-               phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH;
-               break;
-       case PCI_DEVICE_ID_RFLY:
-       case PCI_DEVICE_ID_PFLY:
-       case PCI_DEVICE_ID_BMID:
-       case PCI_DEVICE_ID_ZMID:
-       case PCI_DEVICE_ID_TFLY:
-               phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH;
-               break;
-       default:
-               phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH;
-       }
 
-       if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth)
-               lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
+       lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
 
        return;
 }
index 1251788ce2a36efa58b61c096c18b7350b8b5a66..b8c2a8862d8cbc8dda943a54f0153bfb19ed3f22 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -18,6 +18,8 @@
  * included with this package.                                     *
  *******************************************************************/
 
+typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
+
 struct fc_rport;
 void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
 void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -43,20 +45,24 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int);
+void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
+void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
 void lpfc_set_disctmo(struct lpfc_hba *);
 int lpfc_can_disctmo(struct lpfc_hba *);
 int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
 int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
                    struct lpfc_iocbq *, struct lpfc_nodelist *);
-int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *);
 void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
+struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
+int  lpfc_nlp_put(struct lpfc_nodelist *);
 struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
 void lpfc_disc_list_loopmap(struct lpfc_hba *);
 void lpfc_disc_start(struct lpfc_hba *);
 void lpfc_disc_flush_list(struct lpfc_hba *);
 void lpfc_disc_timeout(unsigned long);
 
+struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
 struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
 
 int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
@@ -66,8 +72,7 @@ int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
 
 int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
                     struct serv_parm *, uint32_t);
-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
-                       int);
+int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
 int lpfc_els_abort_flogi(struct lpfc_hba *);
 int lpfc_initial_flogi(struct lpfc_hba *);
 int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
@@ -113,7 +118,10 @@ void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
 int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
 void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
 int lpfc_online(struct lpfc_hba *);
-int lpfc_offline(struct lpfc_hba *);
+void lpfc_block_mgmt_io(struct lpfc_hba *);
+void lpfc_unblock_mgmt_io(struct lpfc_hba *);
+void lpfc_offline_prep(struct lpfc_hba *);
+void lpfc_offline(struct lpfc_hba *);
 
 int lpfc_sli_setup(struct lpfc_hba *);
 int lpfc_sli_queue_setup(struct lpfc_hba *);
@@ -162,8 +170,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
 struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
                                             struct lpfc_sli_ring *,
                                             dma_addr_t);
-int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *,
-                                struct lpfc_iocbq *);
+int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
+                              struct lpfc_iocbq *);
 int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
                          uint64_t, lpfc_ctx_cmd);
 int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
@@ -172,9 +180,8 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
 void lpfc_mbox_timeout(unsigned long);
 void lpfc_mbox_timeout_handler(struct lpfc_hba *);
 
-struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t);
-struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t,
-                                       struct lpfc_name *);
+struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
+struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
 
 int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
                         uint32_t timeout);
@@ -193,6 +200,9 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
 
 /* Function prototypes. */
 const char* lpfc_info(struct Scsi_Host *);
+void lpfc_scan_start(struct Scsi_Host *);
+int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
+
 void lpfc_get_cfgparam(struct lpfc_hba *);
 int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
 void lpfc_free_sysfs_attr(struct lpfc_hba *);
index a51a41b7f15d55566277619d8be5e64d06b31324..34a9e3bb2614058c9ca827be246b65539564e0cb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -334,21 +334,22 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
 
        lpfc_set_disctmo(phba);
 
-       Cnt = Size  > FCELSSIZE ? FCELSSIZE : Size;
 
        list_add_tail(&head, &mp->list);
        list_for_each_entry_safe(mp, next_mp, &head, list) {
                mlast = mp;
 
+               Cnt = Size  > FCELSSIZE ? FCELSSIZE : Size;
+
                Size -= Cnt;
 
-               if (!ctptr)
+               if (!ctptr) {
                        ctptr = (uint32_t *) mlast->virt;
-               else
+               else
                        Cnt -= 16;      /* subtract length of CT header */
 
                /* Loop through entire NameServer list of DIDs */
-               while (Cnt) {
+               while (Cnt >= sizeof (uint32_t)) {
 
                        /* Get next DID from NameServer List */
                        CTentry = *ctptr++;
@@ -442,10 +443,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
                        phba->fc_ns_retry++;
                        /* CT command is being retried */
-                       ndlp =
-                           lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED,
-                                             NameServer_DID);
-                       if (ndlp) {
+                       ndlp = lpfc_findnode_did(phba, NameServer_DID);
+                       if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
                                if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
                                    0) {
                                        goto out;
@@ -729,7 +728,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
        uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
        uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
 
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID);
+       ndlp = lpfc_findnode_did(phba, FDMI_DID);
        if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
                /* FDMI rsp failed */
                lpfc_printf_log(phba,
@@ -1039,6 +1038,9 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
                                case LA_4GHZ_LINK:
                                        ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
                                break;
+                               case LA_8GHZ_LINK:
+                                       ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
+                               break;
                                default:
                                        ae->un.PortSpeed =
                                                HBA_PORTSPEED_UNKNOWN;
@@ -1161,7 +1163,7 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
 {
        struct lpfc_nodelist *ndlp;
 
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID);
+       ndlp = lpfc_findnode_did(phba, FDMI_DID);
        if (ndlp) {
                if (init_utsname()->nodename[0] != '\0') {
                        lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
index 9766f909c9c69e02a912eb90686e62d3fdbd4bbf..498059f3f7f43583727fd98d7ea7120a08e686d2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -31,6 +31,7 @@
 /* worker thread events */
 enum lpfc_work_type {
        LPFC_EVT_ONLINE,
+       LPFC_EVT_OFFLINE_PREP,
        LPFC_EVT_OFFLINE,
        LPFC_EVT_WARM_START,
        LPFC_EVT_KILL,
@@ -68,7 +69,6 @@ struct lpfc_nodelist {
        uint16_t        nlp_maxframe;           /* Max RCV frame size */
        uint8_t         nlp_class_sup;          /* Supported Classes */
        uint8_t         nlp_retry;              /* used for ELS retries */
-       uint8_t         nlp_disc_refcnt;        /* used for DSM */
        uint8_t         nlp_fcp_info;           /* class info, bits 0-3 */
 #define NLP_FCP_2_DEVICE   0x10                        /* FCP-2 device */
 
@@ -79,20 +79,10 @@ struct lpfc_nodelist {
        struct lpfc_work_evt els_retry_evt;
        unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
        unsigned long last_q_full_time;         /* jiffy of last queue full */
+       struct kref     kref;
 };
 
 /* Defines for nlp_flag (uint32) */
-#define NLP_NO_LIST        0x0         /* Indicates immediately free node */
-#define NLP_UNUSED_LIST    0x1         /* Flg to indicate node will be freed */
-#define NLP_PLOGI_LIST     0x2         /* Flg to indicate sent PLOGI */
-#define NLP_ADISC_LIST     0x3         /* Flg to indicate sent ADISC */
-#define NLP_REGLOGIN_LIST  0x4         /* Flg to indicate sent REG_LOGIN */
-#define NLP_PRLI_LIST      0x5         /* Flg to indicate sent PRLI */
-#define NLP_UNMAPPED_LIST  0x6         /* Node is now unmapped */
-#define NLP_MAPPED_LIST    0x7         /* Node is now mapped */
-#define NLP_NPR_LIST       0x8         /* Node is in NPort Recovery state */
-#define NLP_JUST_DQ        0x9         /* just deque ndlp in lpfc_nlp_list */
-#define NLP_LIST_MASK      0xf         /* mask to see what list node is on */
 #define NLP_PLOGI_SND      0x20                /* sent PLOGI request for this entry */
 #define NLP_PRLI_SND       0x40                /* sent PRLI request for this entry */
 #define NLP_ADISC_SND      0x80                /* sent ADISC request for this entry */
@@ -108,20 +98,8 @@ struct lpfc_nodelist {
                                           ACC */
 #define NLP_NPR_ADISC      0x2000000   /* Issue ADISC when dq'ed from
                                           NPR list */
-#define NLP_DELAY_REMOVE   0x4000000   /* Defer removal till end of DSM */
 #define NLP_NODEV_REMOVE   0x8000000   /* Defer removal till discovery ends */
 
-/* Defines for list searchs */
-#define NLP_SEARCH_MAPPED    0x1       /* search mapped */
-#define NLP_SEARCH_UNMAPPED  0x2       /* search unmapped */
-#define NLP_SEARCH_PLOGI     0x4       /* search plogi */
-#define NLP_SEARCH_ADISC     0x8       /* search adisc */
-#define NLP_SEARCH_REGLOGIN  0x10      /* search reglogin */
-#define NLP_SEARCH_PRLI      0x20      /* search prli */
-#define NLP_SEARCH_NPR       0x40      /* search npr */
-#define NLP_SEARCH_UNUSED    0x80      /* search mapped */
-#define NLP_SEARCH_ALL       0xff      /* search all lists */
-
 /* There are 4 different double linked lists nodelist entries can reside on.
  * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
  * when Link Up discovery or Registered State Change Notification (RSCN)
index a5f33a0dd4e7b79fb204cff5553d04c71c76177e..638b3cd677bdd30d68e82523901b50b23ada97b3 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -182,6 +182,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
                icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
                icmd->un.elsreq64.remoteID = did;       /* DID */
                icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
+               icmd->ulpTimeout = phba->fc_ratov * 2;
        } else {
                icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
                icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
@@ -208,9 +209,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
        }
 
        /* Save for completion so we can release these resources */
-       elsiocb->context1 = (uint8_t *) ndlp;
-       elsiocb->context2 = (uint8_t *) pcmd;
-       elsiocb->context3 = (uint8_t *) pbuflist;
+       elsiocb->context1 = lpfc_nlp_get(ndlp);
+       elsiocb->context2 = pcmd;
+       elsiocb->context3 = pbuflist;
        elsiocb->retry = retry;
        elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
 
@@ -222,16 +223,16 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
                /* Xmit ELS command <elsCmd> to remote NPORT <did> */
                lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
                                "%d:0116 Xmit ELS command x%x to remote "
-                               "NPORT x%x Data: x%x x%x\n",
+                               "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
                                phba->brd_no, elscmd,
-                               did, icmd->ulpIoTag, phba->hba_state);
+                               did, elsiocb->iotag, phba->hba_state);
        } else {
                /* Xmit ELS response <elsCmd> to remote NPORT <did> */
                lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
                                "%d:0117 Xmit ELS response x%x to remote "
-                               "NPORT x%x Data: x%x x%x\n",
+                               "NPORT x%x I/O tag: x%x, size: x%x\n",
                                phba->brd_no, elscmd,
-                               ndlp->nlp_DID, icmd->ulpIoTag, cmdSize);
+                               ndlp->nlp_DID, elsiocb->iotag, cmdSize);
        }
 
        return elsiocb;
@@ -304,7 +305,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
                goto fail_free_mbox;
 
        mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
-       mbox->context2 = ndlp;
+       mbox->context2 = lpfc_nlp_get(ndlp);
 
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
        if (rc == MBX_NOT_FINISHED)
@@ -313,6 +314,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
        return 0;
 
  fail_issue_reg_login:
+       lpfc_nlp_put(ndlp);
        mp = (struct lpfc_dmabuf *) mbox->context1;
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
@@ -368,9 +370,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
                        mempool_free(mbox, phba->mbox_mem_pool);
                        goto fail;
                }
-               mempool_free(ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
 
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID);
+               ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID);
                if (!ndlp) {
                        /*
                         * Cannot find existing Fabric ndlp, so allocate a
@@ -387,12 +389,11 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
                                sizeof(struct lpfc_name));
                memcpy(&ndlp->nlp_nodename, &sp->nodeName,
                                sizeof(struct lpfc_name));
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                ndlp->nlp_flag |= NLP_NPR_2B_DISC;
        } else {
                /* This side will wait for the PLOGI */
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
        }
 
        spin_lock_irq(phba->host->host_lock);
@@ -407,8 +408,8 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 }
 
 static void
-lpfc_cmpl_els_flogi(struct lpfc_hba * phba,
-                   struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                   struct lpfc_iocbq *rspiocb)
 {
        IOCB_t *irsp = &rspiocb->iocb;
        struct lpfc_nodelist *ndlp = cmdiocb->context1;
@@ -418,7 +419,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba,
 
        /* Check to see if link went down during discovery */
        if (lpfc_els_chk_latt(phba)) {
-               lpfc_nlp_remove(phba, ndlp);
+               lpfc_nlp_put(ndlp);
                goto out;
        }
 
@@ -433,13 +434,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba,
                phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
                spin_unlock_irq(phba->host->host_lock);
 
-               /* If private loop, then allow max outstandting els to be
+               /* If private loop, then allow max outstanding els to be
                 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
                 * alpa map would take too long otherwise.
                 */
                if (phba->alpa_map[0] == 0) {
-                       phba->cfg_discovery_threads =
-                           LPFC_MAX_DISC_THREADS;
+                       phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
                }
 
                /* FLOGI failure */
@@ -484,7 +484,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba,
        }
 
 flogifail:
-       lpfc_nlp_remove(phba, ndlp);
+       lpfc_nlp_put(ndlp);
 
        if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
            (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
@@ -582,24 +582,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
                icmd = &iocb->iocb;
                if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
-                       if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
-                               list_del(&iocb->list);
-                               pring->txcmplq_cnt--;
-
-                               if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {
-                                       lpfc_sli_issue_abort_iotag32
-                                               (phba, pring, iocb);
-                               }
-                               if (iocb->iocb_cmpl) {
-                                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                                       icmd->un.ulpWord[4] =
-                                           IOERR_SLI_ABORTED;
-                                       spin_unlock_irq(phba->host->host_lock);
-                                       (iocb->iocb_cmpl) (phba, iocb, iocb);
-                                       spin_lock_irq(phba->host->host_lock);
-                               } else
-                                       lpfc_sli_release_iocbq(phba, iocb);
-                       }
+                       if (ndlp && (ndlp->nlp_DID == Fabric_DID))
+                               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
                }
        }
        spin_unlock_irq(phba->host->host_lock);
@@ -608,12 +592,12 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
 }
 
 int
-lpfc_initial_flogi(struct lpfc_hba * phba)
+lpfc_initial_flogi(struct lpfc_hba *phba)
 {
        struct lpfc_nodelist *ndlp;
 
        /* First look for the Fabric ndlp */
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID);
+       ndlp = lpfc_findnode_did(phba, Fabric_DID);
        if (!ndlp) {
                /* Cannot find existing Fabric ndlp, so allocate a new one */
                ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
@@ -621,10 +605,10 @@ lpfc_initial_flogi(struct lpfc_hba * phba)
                        return 0;
                lpfc_nlp_init(phba, ndlp, Fabric_DID);
        } else {
-               lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
+               lpfc_dequeue_node(phba, ndlp);
        }
        if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
        }
        return 1;
 }
@@ -653,7 +637,7 @@ lpfc_more_plogi(struct lpfc_hba * phba)
 }
 
 static struct lpfc_nodelist *
-lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
+lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp,
                         struct lpfc_nodelist *ndlp)
 {
        struct lpfc_nodelist *new_ndlp;
@@ -670,12 +654,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
 
        lp = (uint32_t *) prsp->virt;
        sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-       memset(name, 0, sizeof (struct lpfc_name));
+       memset(name, 0, sizeof(struct lpfc_name));
 
-       /* Now we to find out if the NPort we are logging into, matches the WWPN
+       /* Now we find out if the NPort we are logging into, matches the WWPN
         * we have for that ndlp. If not, we have some work to do.
         */
-       new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
+       new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName);
 
        if (new_ndlp == ndlp)
                return ndlp;
@@ -695,18 +679,15 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
        lpfc_unreg_rpi(phba, new_ndlp);
        new_ndlp->nlp_DID = ndlp->nlp_DID;
        new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
-       new_ndlp->nlp_state = ndlp->nlp_state;
-       lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
+       lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
 
        /* Move this back to NPR list */
-       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       }
+       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
+               lpfc_drop_node(phba, ndlp);
        else {
                lpfc_unreg_rpi(phba, ndlp);
                ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        }
        return new_ndlp;
 }
@@ -720,13 +701,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
        struct lpfc_dmabuf *prsp;
        int disc, rc, did, type;
 
-
        /* we pass cmdiocb to state machine which needs rspiocb as well */
        cmdiocb->context_un.rsp_iocb = rspiocb;
 
        irsp = &rspiocb->iocb;
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL,
-                                               irsp->un.elsreq64.remoteID);
+       ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID);
        if (!ndlp)
                goto out;
 
@@ -1354,7 +1333,7 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
        elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
                                                ndlp->nlp_DID, ELS_CMD_SCR);
        if (!elsiocb) {
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
                return 1;
        }
 
@@ -1373,12 +1352,12 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
        spin_lock_irq(phba->host->host_lock);
        if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
                spin_unlock_irq(phba->host->host_lock);
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
                lpfc_els_free_iocb(phba, elsiocb);
                return 1;
        }
        spin_unlock_irq(phba->host->host_lock);
-       mempool_free( ndlp, phba->nlp_mem_pool);
+       lpfc_nlp_put(ndlp);
        return 0;
 }
 
@@ -1407,7 +1386,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
        elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
                                                ndlp->nlp_DID, ELS_CMD_RNID);
        if (!elsiocb) {
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
                return 1;
        }
 
@@ -1428,7 +1407,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
 
        memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
        memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
-       if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) {
+       if ((ondlp = lpfc_findnode_did(phba, nportid))) {
                memcpy(&fp->OportName, &ondlp->nlp_portname,
                       sizeof (struct lpfc_name));
                memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
@@ -1440,12 +1419,12 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
        spin_lock_irq(phba->host->host_lock);
        if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
                spin_unlock_irq(phba->host->host_lock);
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               lpfc_nlp_put(ndlp);
                lpfc_els_free_iocb(phba, elsiocb);
                return 1;
        }
        spin_unlock_irq(phba->host->host_lock);
-       mempool_free( ndlp, phba->nlp_mem_pool);
+       lpfc_nlp_put(ndlp);
        return 0;
 }
 
@@ -1554,29 +1533,25 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
        case ELS_CMD_PLOGI:
                if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                }
                break;
        case ELS_CMD_ADISC:
                if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
                }
                break;
        case ELS_CMD_PRLI:
                if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
                }
                break;
        case ELS_CMD_LOGO:
                if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_NPR_NODE;
-                       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                }
                break;
        }
@@ -1614,12 +1589,12 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                cmd = *elscmd++;
        }
 
-       if(ndlp)
+       if (ndlp)
                did = ndlp->nlp_DID;
        else {
                /* We should only hit this case for retrying PLOGI */
                did = irsp->un.elsreq64.remoteID;
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
+               ndlp = lpfc_findnode_did(phba, did);
                if (!ndlp && (cmd != ELS_CMD_PLOGI))
                        return 1;
        }
@@ -1746,8 +1721,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                        ndlp->nlp_flag |= NLP_DELAY_TMO;
 
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_NPR_NODE;
-                       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                        ndlp->nlp_last_elscmd = cmd;
 
                        return 1;
@@ -1759,27 +1733,24 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                case ELS_CMD_PLOGI:
                        if (ndlp) {
                                ndlp->nlp_prev_state = ndlp->nlp_state;
-                               ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                               lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                               lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_PLOGI_ISSUE);
                        }
                        lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
                        return 1;
                case ELS_CMD_ADISC:
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
                        lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
                        return 1;
                case ELS_CMD_PRLI:
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
                        lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
                        return 1;
                case ELS_CMD_LOGO:
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_NPR_NODE;
-                       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                        lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
                        return 1;
                }
@@ -1796,10 +1767,14 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 }
 
 int
-lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb)
+lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
 {
        struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
 
+       if (elsiocb->context1) {
+               lpfc_nlp_put(elsiocb->context1);
+               elsiocb->context1 = NULL;
+       }
        /* context2  = cmd,  context2->next = rsp, context3 = bpl */
        if (elsiocb->context2) {
                buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
@@ -1843,7 +1818,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 
        switch (ndlp->nlp_state) {
        case NLP_STE_UNUSED_NODE:       /* node is just allocated */
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                break;
        case NLP_STE_NPR_NODE:          /* NPort Recovery mode */
                lpfc_unreg_rpi(phba, ndlp);
@@ -1856,8 +1831,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 }
 
 static void
-lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-                 struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                 struct lpfc_iocbq *rspiocb)
 {
        IOCB_t *irsp;
        struct lpfc_nodelist *ndlp;
@@ -1872,14 +1847,14 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 
 
        /* Check to see if link went down during discovery */
-       if ((lpfc_els_chk_latt(phba)) || !ndlp) {
+       if (lpfc_els_chk_latt(phba) || !ndlp) {
                if (mbox) {
                        mp = (struct lpfc_dmabuf *) mbox->context1;
                        if (mp) {
                                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                                kfree(mp);
                        }
-                       mempool_free( mbox, phba->mbox_mem_pool);
+                       mempool_free(mbox, phba->mbox_mem_pool);
                }
                goto out;
        }
@@ -1899,15 +1874,15 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
                        lpfc_unreg_rpi(phba, ndlp);
                        mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
-                       mbox->context2 = ndlp;
+                       mbox->context2 = lpfc_nlp_get(ndlp);
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
                        if (lpfc_sli_issue_mbox(phba, mbox,
                                                (MBX_NOWAIT | MBX_STOP_IOCB))
                            != MBX_NOT_FINISHED) {
                                goto out;
                        }
+                       lpfc_nlp_put(ndlp);
                        /* NOTE: we should have messages for unsuccessful
                           reglogin */
                } else {
@@ -1917,7 +1892,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                               (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
                               (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
                                if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
-                                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                                       lpfc_drop_node(phba, ndlp);
                                        ndlp = NULL;
                                }
                        }
@@ -2012,15 +1987,16 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
                return 1;
        }
 
-       if (newnode)
+       if (newnode) {
+               lpfc_nlp_put(ndlp);
                elsiocb->context1 = NULL;
+       }
 
        /* Xmit ELS ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0128 Xmit ELS ACC response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
+                       "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
@@ -2077,10 +2053,9 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
 
        /* Xmit ELS RJT <err> response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0129 Xmit ELS RJT x%x response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       rejectError, elsiocb->iocb.ulpIoTag,
+                       "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
+                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+                       phba->brd_no, rejectError, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
@@ -2119,18 +2094,18 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
        if (!elsiocb)
                return 1;
 
+       icmd = &elsiocb->iocb;
+       oldcmd = &oldiocb->iocb;
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+
        /* Xmit ADISC ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0130 Xmit ADISC ACC response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "%d:0130 Xmit ADISC ACC response iotag x%x xri: "
+                       "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
-       icmd = &elsiocb->iocb;
-       oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
        *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
@@ -2155,8 +2130,8 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
 }
 
 int
-lpfc_els_rsp_prli_acc(struct lpfc_hba * phba,
-                     struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
+                     struct lpfc_nodelist *ndlp)
 {
        PRLI *npr;
        lpfc_vpd_t *vpd;
@@ -2178,18 +2153,18 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba,
        if (!elsiocb)
                return 1;
 
+       icmd = &elsiocb->iocb;
+       oldcmd = &oldiocb->iocb;
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+
        /* Xmit PRLI ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0131 Xmit PRLI ACC response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
+                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
-       icmd = &elsiocb->iocb;
-       oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
        *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
@@ -2232,9 +2207,8 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba,
 }
 
 static int
-lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
-                     uint8_t format,
-                     struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format,
+                     struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
 {
        RNID *rn;
        IOCB_t *icmd;
@@ -2259,17 +2233,17 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
        if (!elsiocb)
                return 1;
 
+       icmd = &elsiocb->iocb;
+       oldcmd = &oldiocb->iocb;
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+
        /* Xmit RNID ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
                        "%d:0132 Xmit RNID ACC response tag x%x "
-                       "Data: x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "xri x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext);
 
-       icmd = &elsiocb->iocb;
-       oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
        *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
@@ -2301,6 +2275,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
 
        phba->fc_stat.elsXmitACC++;
        elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+       lpfc_nlp_put(ndlp);
        elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
                                    * it could be freed */
 
@@ -2315,32 +2290,31 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
 }
 
 int
-lpfc_els_disc_adisc(struct lpfc_hba * phba)
+lpfc_els_disc_adisc(struct lpfc_hba *phba)
 {
        int sentadisc;
        struct lpfc_nodelist *ndlp, *next_ndlp;
 
        sentadisc = 0;
-       /* go thru NPR list and issue any remaining ELS ADISCs */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                       nlp_listp) {
-               if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-                       if (ndlp->nlp_flag & NLP_NPR_ADISC) {
-                               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-                               ndlp->nlp_prev_state = ndlp->nlp_state;
-                               ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
-                               lpfc_nlp_list(phba, ndlp,
-                                       NLP_ADISC_LIST);
-                               lpfc_issue_els_adisc(phba, ndlp, 0);
-                               sentadisc++;
-                               phba->num_disc_nodes++;
-                               if (phba->num_disc_nodes >=
-                                   phba->cfg_discovery_threads) {
-                                       spin_lock_irq(phba->host->host_lock);
-                                       phba->fc_flag |= FC_NLP_MORE;
-                                       spin_unlock_irq(phba->host->host_lock);
-                                       break;
-                               }
+       /* go thru NPR nodes and issue any remaining ELS ADISCs */
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+                   (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
+                       spin_lock_irq(phba->host->host_lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+                       spin_unlock_irq(phba->host->host_lock);
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
+                       lpfc_issue_els_adisc(phba, ndlp, 0);
+                       sentadisc++;
+                       phba->num_disc_nodes++;
+                       if (phba->num_disc_nodes >=
+                           phba->cfg_discovery_threads) {
+                               spin_lock_irq(phba->host->host_lock);
+                               phba->fc_flag |= FC_NLP_MORE;
+                               spin_unlock_irq(phba->host->host_lock);
+                               break;
                        }
                }
        }
@@ -2360,24 +2334,22 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba)
 
        sentplogi = 0;
        /* go thru NPR list and issue any remaining ELS PLOGIs */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                               nlp_listp) {
-               if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
-                  (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {
-                       if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
-                               ndlp->nlp_prev_state = ndlp->nlp_state;
-                               ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                               lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
-                               lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-                               sentplogi++;
-                               phba->num_disc_nodes++;
-                               if (phba->num_disc_nodes >=
-                                   phba->cfg_discovery_threads) {
-                                       spin_lock_irq(phba->host->host_lock);
-                                       phba->fc_flag |= FC_NLP_MORE;
-                                       spin_unlock_irq(phba->host->host_lock);
-                                       break;
-                               }
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+                   (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
+                   (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
+                       lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+                       sentplogi++;
+                       phba->num_disc_nodes++;
+                       if (phba->num_disc_nodes >=
+                           phba->cfg_discovery_threads) {
+                               spin_lock_irq(phba->host->host_lock);
+                               phba->fc_flag |= FC_NLP_MORE;
+                               spin_unlock_irq(phba->host->host_lock);
+                               break;
                        }
                }
        }
@@ -2479,42 +2451,30 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
 }
 
 static int
-lpfc_rscn_recovery_check(struct lpfc_hba * phba)
+lpfc_rscn_recovery_check(struct lpfc_hba *phba)
 {
-       struct lpfc_nodelist *ndlp = NULL, *next_ndlp;
-       struct list_head *listp;
-       struct list_head *node_list[7];
-       int i;
+       struct lpfc_nodelist *ndlp = NULL;
 
        /* Look at all nodes effected by pending RSCNs and move
-        * them to NPR list.
+        * them to NPR state.
         */
-       node_list[0] = &phba->fc_npr_list;  /* MUST do this list first */
-       node_list[1] = &phba->fc_nlpmap_list;
-       node_list[2] = &phba->fc_nlpunmap_list;
-       node_list[3] = &phba->fc_prli_list;
-       node_list[4] = &phba->fc_reglogin_list;
-       node_list[5] = &phba->fc_adisc_list;
-       node_list[6] = &phba->fc_plogi_list;
-       for (i = 0; i < 7; i++) {
-               listp = node_list[i];
-               if (list_empty(listp))
-                       continue;
 
-               list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
-                       if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID)))
-                               continue;
+       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
+                   lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0)
+                       continue;
 
-                       lpfc_disc_state_machine(phba, ndlp, NULL,
+               lpfc_disc_state_machine(phba, ndlp, NULL,
                                        NLP_EVT_DEVICE_RECOVERY);
 
-                       /* Make sure NLP_DELAY_TMO is NOT running
-                        * after a device recovery event.
-                        */
-                       if (ndlp->nlp_flag & NLP_DELAY_TMO)
-                               lpfc_cancel_retry_delay_tmo(phba, ndlp);
-               }
+               /*
+                * Make sure NLP_DELAY_TMO is NOT running after a device
+                * recovery event.
+                */
+               if (ndlp->nlp_flag & NLP_DELAY_TMO)
+                       lpfc_cancel_retry_delay_tmo(phba, ndlp);
        }
+
        return 0;
 }
 
@@ -2639,8 +2599,8 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba)
 
        /* To process RSCN, first compare RSCN data with NameServer */
        phba->fc_ns_retry = 0;
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID);
-       if (ndlp) {
+       ndlp = lpfc_findnode_did(phba, NameServer_DID);
+       if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
                /* Good ndlp, issue CT Request to NameServer */
                if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
                        /* Wait for NameServer query cmpl before we can
@@ -2650,7 +2610,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba)
        } else {
                /* If login to NameServer does not exist, issue one */
                /* Good status, issue PLOGI to NameServer */
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
+               ndlp = lpfc_findnode_did(phba, NameServer_DID);
                if (ndlp) {
                        /* Wait for NameServer login cmpl before we can
                           continue */
@@ -2664,8 +2624,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba)
                        lpfc_nlp_init(phba, ndlp, NameServer_DID);
                        ndlp->nlp_type |= NLP_FABRIC;
                        ndlp->nlp_prev_state = ndlp->nlp_state;
-                       ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                        lpfc_issue_els_plogi(phba, NameServer_DID, 0);
                        /* Wait for NameServer login cmpl before we can
                           continue */
@@ -2734,8 +2693,9 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba,
                        mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
                        rc = lpfc_sli_issue_mbox
                                (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+                       lpfc_set_loopback_flag(phba);
                        if (rc == MBX_NOT_FINISHED) {
-                               mempool_free( mbox, phba->mbox_mem_pool);
+                               mempool_free(mbox, phba->mbox_mem_pool);
                        }
                        return 1;
                } else if (rc > 0) {    /* greater than */
@@ -2800,8 +2760,8 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba,
 }
 
 static int
-lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-                struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                struct lpfc_nodelist *ndlp)
 {
        struct ls_rjt stat;
 
@@ -2815,7 +2775,7 @@ lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 }
 
 static void
-lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        struct lpfc_sli *psli;
        struct lpfc_sli_ring *pring;
@@ -2838,14 +2798,15 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
        pmb->context2 = NULL;
 
        if (mb->mbxStatus) {
-               mempool_free( pmb, phba->mbox_mem_pool);
+               mempool_free(pmb, phba->mbox_mem_pool);
                return;
        }
 
        cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
-       mempool_free( pmb, phba->mbox_mem_pool);
+       mempool_free(pmb, phba->mbox_mem_pool);
        elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
                                                ndlp->nlp_DID, ELS_CMD_ACC);
+       lpfc_nlp_put(ndlp);
        if (!elsiocb)
                return;
 
@@ -2875,15 +2836,15 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        /* Xmit ELS RPS ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0118 Xmit ELS RPS ACC response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
+                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
        elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
        phba->fc_stat.elsXmitACC++;
+
        if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
                lpfc_els_free_iocb(phba, elsiocb);
        }
@@ -2923,13 +2884,14 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                        lpfc_read_lnk_stat(phba, mbox);
                        mbox->context1 =
                            (void *)((unsigned long)cmdiocb->iocb.ulpContext);
-                       mbox->context2 = ndlp;
+                       mbox->context2 = lpfc_nlp_get(ndlp);
                        mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
                        if (lpfc_sli_issue_mbox (phba, mbox,
                            (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
                                /* Mbox completion will send ELS Response */
                                return 0;
                        }
+                       lpfc_nlp_put(ndlp);
                        mempool_free(mbox, phba->mbox_mem_pool);
                }
        }
@@ -2984,10 +2946,9 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
 
        /* Xmit ELS RPL ACC response tag <ulpIoTag> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d:0120 Xmit ELS RPL ACC response tag x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       elsiocb->iocb.ulpIoTag,
+                       "%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
+                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+                       phba->brd_no, elsiocb->iotag,
                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
@@ -3091,8 +3052,8 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba,
                        /* Log back into the node before sending the FARP. */
                        if (fp->Rflags & FARP_REQUEST_PLOGI) {
                                ndlp->nlp_prev_state = ndlp->nlp_state;
-                               ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                               lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                               lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_PLOGI_ISSUE);
                                lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
                        }
 
@@ -3169,14 +3130,15 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                         */
 
                        list_for_each_entry_safe(ndlp, next_ndlp,
-                               &phba->fc_npr_list, nlp_listp) {
-
+                                                &phba->fc_nodes, nlp_listp) {
+                               if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                                       continue;
                                if (ndlp->nlp_type & NLP_FABRIC) {
                                        /*
                                         * Clean up old Fabric, Nameserver and
                                         * other NLP_FABRIC logins
                                         */
-                                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                                       lpfc_drop_node(phba, ndlp);
                                } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
                                        /* Fail outstanding I/O now since this
                                         * device is marked for PLOGI
@@ -3193,20 +3155,22 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                /* Discovery not needed,
                 * move the nodes to their original state.
                 */
-               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                       nlp_listp) {
+               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                               continue;
 
                        switch (ndlp->nlp_prev_state) {
                        case NLP_STE_UNMAPPED_NODE:
                                ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                               ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-                               lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+                               lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_UNMAPPED_NODE);
                                break;
 
                        case NLP_STE_MAPPED_NODE:
                                ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                               ndlp->nlp_state = NLP_STE_MAPPED_NODE;
-                               lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
+                               lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_MAPPED_NODE);
                                break;
 
                        default:
@@ -3246,9 +3210,8 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
        struct lpfc_iocbq *tmp_iocb, *piocb;
        IOCB_t *cmd = NULL;
        struct lpfc_dmabuf *pcmd;
-       struct list_head *dlp;
        uint32_t *elscmd;
-       uint32_t els_command;
+       uint32_t els_command=0;
        uint32_t timeout;
        uint32_t remote_ID;
 
@@ -3263,17 +3226,20 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
        timeout = (uint32_t)(phba->fc_ratov << 1);
 
        pring = &phba->sli.ring[LPFC_ELS_RING];
-       dlp = &pring->txcmplq;
 
        list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
                cmd = &piocb->iocb;
 
-               if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
+               if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
+                       (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
+                       (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
                        continue;
                }
                pcmd = (struct lpfc_dmabuf *) piocb->context2;
-               elscmd = (uint32_t *) (pcmd->virt);
-               els_command = *elscmd;
+               if (pcmd) {
+                       elscmd = (uint32_t *) (pcmd->virt);
+                       els_command = *elscmd;
+               }
 
                if ((els_command == ELS_CMD_FARP)
                    || (els_command == ELS_CMD_FARPR)) {
@@ -3289,19 +3255,10 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
                        continue;
                }
 
-               list_del(&piocb->list);
-               pring->txcmplq_cnt--;
-
                if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
                        struct lpfc_nodelist *ndlp;
-                       spin_unlock_irq(phba->host->host_lock);
-                       ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
-                       spin_lock_irq(phba->host->host_lock);
+                       ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
                        remote_ID = ndlp->nlp_DID;
-                       if (cmd->un.elsreq64.bdl.ulpIoTag32) {
-                               lpfc_sli_issue_abort_iotag32(phba,
-                                       pring, piocb);
-                       }
                } else {
                        remote_ID = cmd->un.elsreq64.remoteID;
                }
@@ -3313,17 +3270,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
                                phba->brd_no, els_command,
                                remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
 
-               /*
-                * The iocb has timed out; abort it.
-                */
-               if (piocb->iocb_cmpl) {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       spin_unlock_irq(phba->host->host_lock);
-                       (piocb->iocb_cmpl) (phba, piocb, piocb);
-                       spin_lock_irq(phba->host->host_lock);
-               } else
-                       lpfc_sli_release_iocbq(phba, piocb);
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
        }
        if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
                mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
@@ -3332,16 +3279,13 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
 }
 
 void
-lpfc_els_flush_cmd(struct lpfc_hba * phba)
+lpfc_els_flush_cmd(struct lpfc_hba *phba)
 {
-       struct lpfc_sli_ring *pring;
+       LIST_HEAD(completions);
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
        struct lpfc_iocbq *tmp_iocb, *piocb;
        IOCB_t *cmd = NULL;
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *elscmd;
-       uint32_t els_command;
 
-       pring = &phba->sli.ring[LPFC_ELS_RING];
        spin_lock_irq(phba->host->host_lock);
        list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
                cmd = &piocb->iocb;
@@ -3351,29 +3295,15 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
                }
 
                /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
-               if ((cmd->ulpCommand == CMD_QUE_RING_BUF_CN) ||
-                   (cmd->ulpCommand == CMD_QUE_RING_BUF64_CN) ||
-                   (cmd->ulpCommand == CMD_CLOSE_XRI_CN) ||
-                   (cmd->ulpCommand == CMD_ABORT_XRI_CN)) {
+               if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
+                   cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
+                   cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
+                   cmd->ulpCommand == CMD_ABORT_XRI_CN)
                        continue;
-               }
 
-               pcmd = (struct lpfc_dmabuf *) piocb->context2;
-               elscmd = (uint32_t *) (pcmd->virt);
-               els_command = *elscmd;
+               list_move_tail(&piocb->list, &completions);
+               pring->txq_cnt--;
 
-               list_del(&piocb->list);
-               pring->txcmplq_cnt--;
-
-               cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-               cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-
-               if (piocb->iocb_cmpl) {
-                       spin_unlock_irq(phba->host->host_lock);
-                       (piocb->iocb_cmpl) (phba, piocb, piocb);
-                       spin_lock_irq(phba->host->host_lock);
-               } else
-                       lpfc_sli_release_iocbq(phba, piocb);
        }
 
        list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
@@ -3382,24 +3312,24 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
                if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
                        continue;
                }
-               pcmd = (struct lpfc_dmabuf *) piocb->context2;
-               elscmd = (uint32_t *) (pcmd->virt);
-               els_command = *elscmd;
 
-               list_del(&piocb->list);
-               pring->txcmplq_cnt--;
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+       }
+       spin_unlock_irq(phba->host->host_lock);
 
-               cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-               cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+       while(!list_empty(&completions)) {
+               piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &piocb->iocb;
+               list_del(&piocb->list);
 
                if (piocb->iocb_cmpl) {
-                       spin_unlock_irq(phba->host->host_lock);
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
                        (piocb->iocb_cmpl) (phba, piocb, piocb);
-                       spin_lock_irq(phba->host->host_lock);
                } else
                        lpfc_sli_release_iocbq(phba, piocb);
        }
-       spin_unlock_irq(phba->host->host_lock);
+
        return;
 }
 
@@ -3468,7 +3398,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
        }
 
        did = icmd->un.rcvels.remoteID;
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
+       ndlp = lpfc_findnode_did(phba, did);
        if (!ndlp) {
                /* Cannot find existing Fabric ndlp, so allocate a new one */
                ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
@@ -3484,12 +3414,13 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
                if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
                        ndlp->nlp_type |= NLP_FABRIC;
                }
-               ndlp->nlp_state = NLP_STE_UNUSED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
        }
 
        phba->fc_stat.elsRcvFrame++;
-       elsiocb->context1 = ndlp;
+       if (elsiocb->context1)
+               lpfc_nlp_put(elsiocb->context1);
+       elsiocb->context1 = lpfc_nlp_get(ndlp);
        elsiocb->context2 = mp;
 
        if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
@@ -3513,9 +3444,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
        case ELS_CMD_FLOGI:
                phba->fc_stat.elsRcvFLOGI++;
                lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        case ELS_CMD_LOGO:
                phba->fc_stat.elsRcvLOGO++;
@@ -3536,9 +3466,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
        case ELS_CMD_RSCN:
                phba->fc_stat.elsRcvRSCN++;
                lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        case ELS_CMD_ADISC:
                phba->fc_stat.elsRcvADISC++;
@@ -3579,30 +3508,26 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
        case ELS_CMD_LIRR:
                phba->fc_stat.elsRcvLIRR++;
                lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        case ELS_CMD_RPS:
                phba->fc_stat.elsRcvRPS++;
                lpfc_els_rcv_rps(phba, elsiocb, ndlp);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        case ELS_CMD_RPL:
                phba->fc_stat.elsRcvRPL++;
                lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        case ELS_CMD_RNID:
                phba->fc_stat.elsRcvRNID++;
                lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        default:
                /* Unsupported ELS command, reject */
@@ -3612,9 +3537,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
                lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
                                "%d:0115 Unknown ELS command x%x received from "
                                "NPORT x%x\n", phba->brd_no, cmd, did);
-               if (newnode) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-               }
+               if (newnode)
+                       lpfc_drop_node(phba, ndlp);
                break;
        }
 
@@ -3627,6 +3551,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
                lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
        }
 
+       lpfc_nlp_put(elsiocb->context1);
+       elsiocb->context1 = NULL;
        if (elsiocb->context2) {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
index c39564e85e944f62ebed5d8b3d41a6f75daf4ff7..61caa8d379e2dc7a120481da5f8ad54f671289f5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -109,6 +109,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
                return;
        }
 
+       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+               return;
+
        name = (uint8_t *)&ndlp->nlp_portname;
        phba = ndlp->nlp_phba;
 
@@ -147,11 +150,17 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
                                ndlp->nlp_state, ndlp->nlp_rpi);
        }
 
-       ndlp->rport = NULL;
-       rdata->pnode = NULL;
-
-       if (!(phba->fc_flag & FC_UNLOADING))
+       if (!(phba->fc_flag & FC_UNLOADING) &&
+           !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+           !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
+           (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
                lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
+       else {
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
+               lpfc_nlp_put(ndlp);
+               put_device(&rport->dev);
+       }
 
        return;
 }
@@ -182,29 +191,35 @@ lpfc_work_list_done(struct lpfc_hba * phba)
                                *(int *)(evtp->evt_arg1)  = 0;
                        complete((struct completion *)(evtp->evt_arg2));
                        break;
-               case LPFC_EVT_OFFLINE:
+               case LPFC_EVT_OFFLINE_PREP:
                        if (phba->hba_state >= LPFC_LINK_DOWN)
-                               lpfc_offline(phba);
+                               lpfc_offline_prep(phba);
+                       *(int *)(evtp->evt_arg1) = 0;
+                       complete((struct completion *)(evtp->evt_arg2));
+                       break;
+               case LPFC_EVT_OFFLINE:
+                       lpfc_offline(phba);
                        lpfc_sli_brdrestart(phba);
                        *(int *)(evtp->evt_arg1) =
-                               lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY);
+                               lpfc_sli_brdready(phba, HS_FFRDY | HS_MBRDY);
+                       lpfc_unblock_mgmt_io(phba);
                        complete((struct completion *)(evtp->evt_arg2));
                        break;
                case LPFC_EVT_WARM_START:
-                       if (phba->hba_state >= LPFC_LINK_DOWN)
-                               lpfc_offline(phba);
+                       lpfc_offline(phba);
                        lpfc_reset_barrier(phba);
                        lpfc_sli_brdreset(phba);
                        lpfc_hba_down_post(phba);
                        *(int *)(evtp->evt_arg1) =
                                lpfc_sli_brdready(phba, HS_MBRDY);
+                       lpfc_unblock_mgmt_io(phba);
                        complete((struct completion *)(evtp->evt_arg2));
                        break;
                case LPFC_EVT_KILL:
-                       if (phba->hba_state >= LPFC_LINK_DOWN)
-                               lpfc_offline(phba);
+                       lpfc_offline(phba);
                        *(int *)(evtp->evt_arg1)
                                = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
+                       lpfc_unblock_mgmt_io(phba);
                        complete((struct completion *)(evtp->evt_arg2));
                        break;
                }
@@ -359,13 +374,12 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
 }
 
 int
-lpfc_linkdown(struct lpfc_hba * phba)
+lpfc_linkdown(struct lpfc_hba *phba)
 {
        struct lpfc_sli       *psli;
        struct lpfc_nodelist  *ndlp, *next_ndlp;
-       struct list_head *listp, *node_list[7];
-       LPFC_MBOXQ_t     *mb;
-       int               rc, i;
+       LPFC_MBOXQ_t          *mb;
+       int                   rc;
 
        psli = &phba->sli;
        /* sysfs or selective reset may call this routine to clean up */
@@ -397,31 +411,16 @@ lpfc_linkdown(struct lpfc_hba * phba)
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_cmd(phba);
 
-       /* Issue a LINK DOWN event to all nodes */
-       node_list[0] = &phba->fc_npr_list;  /* MUST do this list first */
-       node_list[1] = &phba->fc_nlpmap_list;
-       node_list[2] = &phba->fc_nlpunmap_list;
-       node_list[3] = &phba->fc_prli_list;
-       node_list[4] = &phba->fc_reglogin_list;
-       node_list[5] = &phba->fc_adisc_list;
-       node_list[6] = &phba->fc_plogi_list;
-       for (i = 0; i < 7; i++) {
-               listp = node_list[i];
-               if (list_empty(listp))
-                       continue;
-
-               list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
-
+       /*
+        * Issue a LINK DOWN event to all nodes.
+        */
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+                               /* free any ndlp's on unused list */
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+                       lpfc_drop_node(phba, ndlp);
+               else            /* otherwise, force node recovery. */
                        rc = lpfc_disc_state_machine(phba, ndlp, NULL,
-                                            NLP_EVT_DEVICE_RECOVERY);
-
-               }
-       }
-
-       /* free any ndlp's on unused list */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
-                               nlp_listp) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                                                    NLP_EVT_DEVICE_RECOVERY);
        }
 
        /* Setup myDID for link up if we are in pt2pt mode */
@@ -452,11 +451,9 @@ lpfc_linkdown(struct lpfc_hba * phba)
 }
 
 static int
-lpfc_linkup(struct lpfc_hba * phba)
+lpfc_linkup(struct lpfc_hba *phba)
 {
        struct lpfc_nodelist *ndlp, *next_ndlp;
-       struct list_head *listp, *node_list[7];
-       int i;
 
        fc_host_post_event(phba->host, fc_get_event_number(),
                        FCH_EVT_LINKUP, 0);
@@ -470,29 +467,20 @@ lpfc_linkup(struct lpfc_hba * phba)
        spin_unlock_irq(phba->host->host_lock);
 
 
-       node_list[0] = &phba->fc_plogi_list;
-       node_list[1] = &phba->fc_adisc_list;
-       node_list[2] = &phba->fc_reglogin_list;
-       node_list[3] = &phba->fc_prli_list;
-       node_list[4] = &phba->fc_nlpunmap_list;
-       node_list[5] = &phba->fc_nlpmap_list;
-       node_list[6] = &phba->fc_npr_list;
-       for (i = 0; i < 7; i++) {
-               listp = node_list[i];
-               if (list_empty(listp))
-                       continue;
-
-               list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
-                       if (phba->fc_flag & FC_LBIT) {
+       if (phba->fc_flag & FC_LBIT) {
+               list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+                       if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
                                if (ndlp->nlp_type & NLP_FABRIC) {
-                                       /* On Linkup its safe to clean up the
+                                       /*
+                                        * On Linkup its safe to clean up the
                                         * ndlp from Fabric connections.
                                         */
-                                       lpfc_nlp_list(phba, ndlp,
-                                                       NLP_UNUSED_LIST);
+                                       lpfc_nlp_set_state(phba, ndlp,
+                                                          NLP_STE_UNUSED_NODE);
                                } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
-                                       /* Fail outstanding IO now since device
-                                        * is marked for PLOGI.
+                                       /*
+                                        * Fail outstanding IO now since
+                                        * device is marked for PLOGI.
                                         */
                                        lpfc_unreg_rpi(phba, ndlp);
                                }
@@ -501,9 +489,10 @@ lpfc_linkup(struct lpfc_hba * phba)
        }
 
        /* free any ndlp's on unused list */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
-                               nlp_listp) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+                       lpfc_drop_node(phba, ndlp);
        }
 
        return 0;
@@ -734,6 +723,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
                case LA_4GHZ_LINK:
                        phba->fc_linkspeed = LA_4GHZ_LINK;
                        break;
+               case LA_8GHZ_LINK:
+                       phba->fc_linkspeed = LA_8GHZ_LINK;
+                       break;
                default:
                        phba->fc_linkspeed = LA_UNKNW_LINK;
                        break;
@@ -889,12 +881,21 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        if (la->attType == AT_LINK_UP) {
                phba->fc_stat.LinkUp++;
-               lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+               if (phba->fc_flag & FC_LOOPBACK_MODE) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+                               "%d:1306 Link Up Event in loop back mode "
+                               "x%x received Data: x%x x%x x%x x%x\n",
+                               phba->brd_no, la->eventTag, phba->fc_eventTag,
+                               la->granted_AL_PA, la->UlnkSpeed,
+                               phba->alpa_map[0]);
+               } else {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "%d:1303 Link Up Event x%x received "
                                "Data: x%x x%x x%x x%x\n",
                                phba->brd_no, la->eventTag, phba->fc_eventTag,
                                la->granted_AL_PA, la->UlnkSpeed,
                                phba->alpa_map[0]);
+               }
                lpfc_mbx_process_link_up(phba, la);
        } else {
                phba->fc_stat.LinkDown++;
@@ -940,6 +941,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        mempool_free( pmb, phba->mbox_mem_pool);
+       lpfc_nlp_put(ndlp);
 
        return;
 }
@@ -966,11 +968,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
        ndlp = (struct lpfc_nodelist *) pmb->context2;
        mp = (struct lpfc_dmabuf *) (pmb->context1);
 
+       pmb->context1 = NULL;
+       pmb->context2 = NULL;
+
        if (mb->mbxStatus) {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
-               mempool_free( pmb, phba->mbox_mem_pool);
-               mempool_free( ndlp, phba->nlp_mem_pool);
+               mempool_free(pmb, phba->mbox_mem_pool);
+               lpfc_nlp_put(ndlp);
 
                /* FLOGI failed, so just use loop map to make discovery list */
                lpfc_disc_list_loopmap(phba);
@@ -980,12 +985,11 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
                return;
        }
 
-       pmb->context1 = NULL;
-
        ndlp->nlp_rpi = mb->un.varWords[0];
        ndlp->nlp_type |= NLP_FABRIC;
-       ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+
+       lpfc_nlp_put(ndlp);     /* Drop the reference from the mbox */
 
        if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
                /* This NPort has been assigned an NPort_ID by the fabric as a
@@ -996,7 +1000,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
                 */
                lpfc_issue_els_scr(phba, SCR_DID, 0);
 
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
+               ndlp = lpfc_findnode_did(phba, NameServer_DID);
                if (!ndlp) {
                        /* Allocate a new node instance. If the pool is empty,
                         * start the discovery process and skip the Nameserver
@@ -1008,15 +1012,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
                                lpfc_disc_start(phba);
                                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                                kfree(mp);
-                               mempool_free( pmb, phba->mbox_mem_pool);
+                               mempool_free(pmb, phba->mbox_mem_pool);
                                return;
                        } else {
                                lpfc_nlp_init(phba, ndlp, NameServer_DID);
                                ndlp->nlp_type |= NLP_FABRIC;
                        }
                }
-               ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-               lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                lpfc_issue_els_plogi(phba, NameServer_DID, 0);
                if (phba->cfg_fdmi_on) {
                        ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
@@ -1032,7 +1035,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
-       mempool_free( pmb, phba->mbox_mem_pool);
+       mempool_free(pmb, phba->mbox_mem_pool);
        return;
 }
 
@@ -1057,10 +1060,11 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
        mp = (struct lpfc_dmabuf *) (pmb->context1);
 
        if (mb->mbxStatus) {
+               lpfc_nlp_put(ndlp);
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
-               mempool_free( pmb, phba->mbox_mem_pool);
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               mempool_free(pmb, phba->mbox_mem_pool);
+               lpfc_drop_node(phba, ndlp);
 
                /* RegLogin failed, so just use loop map to make discovery
                   list */
@@ -1075,8 +1079,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        ndlp->nlp_rpi = mb->un.varWords[0];
        ndlp->nlp_type |= NLP_FABRIC;
-       ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
 
        if (phba->hba_state < LPFC_HBA_READY) {
                /* Link up discovery requires Fabrib registration. */
@@ -1093,6 +1096,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
                lpfc_disc_start(phba);
        }
 
+       lpfc_nlp_put(ndlp);
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        mempool_free( pmb, phba->mbox_mem_pool);
@@ -1101,8 +1105,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 }
 
 static void
-lpfc_register_remote_port(struct lpfc_hba * phba,
-                           struct lpfc_nodelist * ndlp)
+lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        struct fc_rport *rport;
        struct lpfc_rport_data *rdata;
@@ -1114,8 +1117,19 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
        rport_ids.port_id = ndlp->nlp_DID;
        rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
+       /*
+        * We leave our node pointer in rport->dd_data when we unregister a
+        * FCP target port.  But fc_remote_port_add zeros the space to which
+        * rport->dd_data points.  So, if we're reusing a previously
+        * registered port, drop the reference that we took the last time we
+        * registered the port.
+        */
+       if (ndlp->rport && ndlp->rport->dd_data &&
+           *(struct lpfc_rport_data **) ndlp->rport->dd_data) {
+               lpfc_nlp_put(ndlp);
+       }
        ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
-       if (!rport) {
+       if (!rport || !get_device(&rport->dev)) {
                dev_printk(KERN_WARNING, &phba->pcidev->dev,
                           "Warning: fc_remote_port_add failed\n");
                return;
@@ -1125,7 +1139,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
        rport->maxframe_size = ndlp->nlp_maxframe;
        rport->supported_classes = ndlp->nlp_class_sup;
        rdata = rport->dd_data;
-       rdata->pnode = ndlp;
+       rdata->pnode = lpfc_nlp_get(ndlp);
 
        if (ndlp->nlp_type & NLP_FCP_TARGET)
                rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
@@ -1145,8 +1159,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
 }
 
 static void
-lpfc_unregister_remote_port(struct lpfc_hba * phba,
-                           struct lpfc_nodelist * ndlp)
+lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        struct fc_rport *rport = ndlp->rport;
        struct lpfc_rport_data *rdata = rport->dd_data;
@@ -1154,6 +1167,8 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
        if (rport->scsi_target_id == -1) {
                ndlp->rport = NULL;
                rdata->pnode = NULL;
+               lpfc_nlp_put(ndlp);
+               put_device(&rport->dev);
        }
 
        fc_remote_port_delete(rport);
@@ -1161,178 +1176,70 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
        return;
 }
 
-int
-lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
+static void
+lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
 {
-       enum { none, unmapped, mapped } rport_add = none, rport_del = none;
-       struct lpfc_sli      *psli;
-
-       psli = &phba->sli;
-       /* Sanity check to ensure we are not moving to / from the same list */
-       if ((nlp->nlp_flag & NLP_LIST_MASK) == list)
-               if (list != NLP_NO_LIST)
-                       return 0;
-
        spin_lock_irq(phba->host->host_lock);
-       switch (nlp->nlp_flag & NLP_LIST_MASK) {
-       case NLP_NO_LIST: /* Not on any list */
+       switch (state) {
+       case NLP_STE_UNUSED_NODE:
+               phba->fc_unused_cnt += count;
                break;
-       case NLP_UNUSED_LIST:
-               phba->fc_unused_cnt--;
-               list_del(&nlp->nlp_listp);
+       case NLP_STE_PLOGI_ISSUE:
+               phba->fc_plogi_cnt += count;
                break;
-       case NLP_PLOGI_LIST:
-               phba->fc_plogi_cnt--;
-               list_del(&nlp->nlp_listp);
+       case NLP_STE_ADISC_ISSUE:
+               phba->fc_adisc_cnt += count;
                break;
-       case NLP_ADISC_LIST:
-               phba->fc_adisc_cnt--;
-               list_del(&nlp->nlp_listp);
+       case NLP_STE_REG_LOGIN_ISSUE:
+               phba->fc_reglogin_cnt += count;
                break;
-       case NLP_REGLOGIN_LIST:
-               phba->fc_reglogin_cnt--;
-               list_del(&nlp->nlp_listp);
+       case NLP_STE_PRLI_ISSUE:
+               phba->fc_prli_cnt += count;
                break;
-       case NLP_PRLI_LIST:
-               phba->fc_prli_cnt--;
-               list_del(&nlp->nlp_listp);
+       case NLP_STE_UNMAPPED_NODE:
+               phba->fc_unmap_cnt += count;
                break;
-       case NLP_UNMAPPED_LIST:
-               phba->fc_unmap_cnt--;
-               list_del(&nlp->nlp_listp);
-               nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
-               nlp->nlp_type &= ~NLP_FC_NODE;
-               phba->nport_event_cnt++;
-               if (nlp->rport)
-                       rport_del = unmapped;
+       case NLP_STE_MAPPED_NODE:
+               phba->fc_map_cnt += count;
                break;
-       case NLP_MAPPED_LIST:
-               phba->fc_map_cnt--;
-               list_del(&nlp->nlp_listp);
-               phba->nport_event_cnt++;
-               if (nlp->rport)
-                       rport_del = mapped;
-               break;
-       case NLP_NPR_LIST:
-               phba->fc_npr_cnt--;
-               list_del(&nlp->nlp_listp);
-               /* Stop delay tmo if taking node off NPR list */
-               if ((nlp->nlp_flag & NLP_DELAY_TMO) &&
-                  (list != NLP_NPR_LIST)) {
-                       spin_unlock_irq(phba->host->host_lock);
-                       lpfc_cancel_retry_delay_tmo(phba, nlp);
-                       spin_lock_irq(phba->host->host_lock);
-               }
+       case NLP_STE_NPR_NODE:
+               phba->fc_npr_cnt += count;
                break;
        }
+       spin_unlock_irq(phba->host->host_lock);
+}
 
-       nlp->nlp_flag &= ~NLP_LIST_MASK;
-
-       /* Add NPort <did> to <num> list */
-       lpfc_printf_log(phba,
-                       KERN_INFO,
-                       LOG_NODE,
-                       "%d:0904 Add NPort x%x to %d list Data: x%x\n",
-                       phba->brd_no,
-                       nlp->nlp_DID, list, nlp->nlp_flag);
-
-       switch (list) {
-       case NLP_NO_LIST: /* No list, just remove it */
-               spin_unlock_irq(phba->host->host_lock);
-               lpfc_nlp_remove(phba, nlp);
-               spin_lock_irq(phba->host->host_lock);
-               /* as node removed - stop further transport calls */
-               rport_del = none;
-               break;
-       case NLP_UNUSED_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the unused list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list);
-               phba->fc_unused_cnt++;
-               break;
-       case NLP_PLOGI_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the plogi list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list);
-               phba->fc_plogi_cnt++;
-               break;
-       case NLP_ADISC_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the adisc list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list);
-               phba->fc_adisc_cnt++;
-               break;
-       case NLP_REGLOGIN_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the reglogin list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list);
-               phba->fc_reglogin_cnt++;
-               break;
-       case NLP_PRLI_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the prli list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list);
-               phba->fc_prli_cnt++;
-               break;
-       case NLP_UNMAPPED_LIST:
-               rport_add = unmapped;
-               /* ensure all vestiges of "mapped" significance are gone */
-               nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the unmap list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list);
-               phba->fc_unmap_cnt++;
-               phba->nport_event_cnt++;
-               nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
-               nlp->nlp_type |= NLP_FC_NODE;
-               break;
-       case NLP_MAPPED_LIST:
-               rport_add = mapped;
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the map list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list);
-               phba->fc_map_cnt++;
+static void
+lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+                      int old_state, int new_state)
+{
+       if (new_state == NLP_STE_UNMAPPED_NODE) {
+               ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
+               ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
+               ndlp->nlp_type |= NLP_FC_NODE;
+       }
+       if (new_state == NLP_STE_MAPPED_NODE)
+               ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
+       if (new_state == NLP_STE_NPR_NODE)
+               ndlp->nlp_flag &= ~NLP_RCV_PLOGI;
+
+       /* Transport interface */
+       if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
+                           old_state == NLP_STE_UNMAPPED_NODE)) {
                phba->nport_event_cnt++;
-               nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
-               break;
-       case NLP_NPR_LIST:
-               nlp->nlp_flag |= list;
-               /* Put it at the end of the npr list */
-               list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
-               phba->fc_npr_cnt++;
-
-               nlp->nlp_flag &= ~NLP_RCV_PLOGI;
-               break;
-       case NLP_JUST_DQ:
-               break;
+               lpfc_unregister_remote_port(phba, ndlp);
        }
 
-       spin_unlock_irq(phba->host->host_lock);
-
-       /*
-        * We make all the calls into the transport after we have
-        * moved the node between lists. This so that we don't
-        * release the lock while in-between lists.
-        */
-
-       /* Don't upcall midlayer if we're unloading */
-       if (!(phba->fc_flag & FC_UNLOADING)) {
-               /*
-                * We revalidate the rport pointer as the "add" function
-                * may have removed the remote port.
-                */
-               if ((rport_del != none) && nlp->rport)
-                       lpfc_unregister_remote_port(phba, nlp);
-
-               if (rport_add != none) {
+       if (new_state ==  NLP_STE_MAPPED_NODE ||
+           new_state == NLP_STE_UNMAPPED_NODE) {
+               phba->nport_event_cnt++;
                        /*
                         * Tell the fc transport about the port, if we haven't
                         * already. If we have, and it's a scsi entity, be
                         * sure to unblock any attached scsi devices
                         */
-                       if ((!nlp->rport) || (nlp->rport->port_state ==
-                                       FC_PORTSTATE_BLOCKED))
-                               lpfc_register_remote_port(phba, nlp);
+                       lpfc_register_remote_port(phba, ndlp);
+       }
 
                        /*
                         * if we added to Mapped list, but the remote port
@@ -1340,19 +1247,95 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
                         * our presentable range - move the node to the
                         * Unmapped List
                         */
-                       if ((rport_add == mapped) &&
-                           ((!nlp->rport) ||
-                            (nlp->rport->scsi_target_id == -1) ||
-                            (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) {
-                               nlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-                               spin_lock_irq(phba->host->host_lock);
-                               nlp->nlp_flag |= NLP_TGT_NO_SCSIID;
-                               spin_unlock_irq(phba->host->host_lock);
-                               lpfc_nlp_list(phba, nlp, NLP_UNMAPPED_LIST);
-                       }
-               }
+       if (new_state == NLP_STE_MAPPED_NODE &&
+           (!ndlp->rport ||
+            ndlp->rport->scsi_target_id == -1 ||
+            ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
+               spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
+               spin_unlock_irq(phba->host->host_lock);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
        }
-       return 0;
+}
+
+static char *
+lpfc_nlp_state_name(char *buffer, size_t size, int state)
+{
+       static char *states[] = {
+               [NLP_STE_UNUSED_NODE] = "UNUSED",
+               [NLP_STE_PLOGI_ISSUE] = "PLOGI",
+               [NLP_STE_ADISC_ISSUE] = "ADISC",
+               [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN",
+               [NLP_STE_PRLI_ISSUE] = "PRLI",
+               [NLP_STE_UNMAPPED_NODE] = "UNMAPPED",
+               [NLP_STE_MAPPED_NODE] = "MAPPED",
+               [NLP_STE_NPR_NODE] = "NPR",
+       };
+
+       if (state < ARRAY_SIZE(states) && states[state])
+               strlcpy(buffer, states[state], size);
+       else
+               snprintf(buffer, size, "unknown (%d)", state);
+       return buffer;
+}
+
+void
+lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
+{
+       int  old_state = ndlp->nlp_state;
+       char name1[16], name2[16];
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+                       "%d:0904 NPort state transition x%06x, %s -> %s\n",
+                       phba->brd_no,
+                       ndlp->nlp_DID,
+                       lpfc_nlp_state_name(name1, sizeof(name1), old_state),
+                       lpfc_nlp_state_name(name2, sizeof(name2), state));
+       if (old_state == NLP_STE_NPR_NODE &&
+           (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
+           state != NLP_STE_NPR_NODE)
+               lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (old_state == NLP_STE_UNMAPPED_NODE) {
+               ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
+               ndlp->nlp_type &= ~NLP_FC_NODE;
+       }
+
+       if (list_empty(&ndlp->nlp_listp)) {
+               spin_lock_irq(phba->host->host_lock);
+               list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
+               spin_unlock_irq(phba->host->host_lock);
+       } else if (old_state)
+               lpfc_nlp_counters(phba, old_state, -1);
+
+       ndlp->nlp_state = state;
+       lpfc_nlp_counters(phba, state, 1);
+       lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
+}
+
+void
+lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
+               lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
+               lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
+       spin_lock_irq(phba->host->host_lock);
+       list_del_init(&ndlp->nlp_listp);
+       spin_unlock_irq(phba->host->host_lock);
+       lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
+}
+
+void
+lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
+               lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
+               lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
+       spin_lock_irq(phba->host->host_lock);
+       list_del_init(&ndlp->nlp_listp);
+       spin_unlock_irq(phba->host->host_lock);
+       lpfc_nlp_put(ndlp);
 }
 
 /*
@@ -1464,6 +1447,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
 static int
 lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
+       LIST_HEAD(completions);
        struct lpfc_sli *psli;
        struct lpfc_sli_ring *pring;
        struct lpfc_iocbq *iocb, *next_iocb;
@@ -1492,29 +1476,29 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
                                     (phba, pring, iocb, ndlp))) {
                                        /* It matches, so deque and call compl
                                           with an error */
-                                       list_del(&iocb->list);
+                                       list_move_tail(&iocb->list,
+                                                      &completions);
                                        pring->txq_cnt--;
-                                       if (iocb->iocb_cmpl) {
-                                               icmd = &iocb->iocb;
-                                               icmd->ulpStatus =
-                                                   IOSTAT_LOCAL_REJECT;
-                                               icmd->un.ulpWord[4] =
-                                                   IOERR_SLI_ABORTED;
-                                               spin_unlock_irq(phba->host->
-                                                               host_lock);
-                                               (iocb->iocb_cmpl) (phba,
-                                                                  iocb, iocb);
-                                               spin_lock_irq(phba->host->
-                                                             host_lock);
-                                       } else
-                                               lpfc_sli_release_iocbq(phba,
-                                                                      iocb);
                                }
                        }
                        spin_unlock_irq(phba->host->host_lock);
 
                }
        }
+
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               list_del(&iocb->list);
+
+               if (iocb->iocb_cmpl) {
+                       icmd = &iocb->iocb;
+                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+               } else
+                       lpfc_sli_release_iocbq(phba, iocb);
+       }
+
        return 0;
 }
 
@@ -1554,7 +1538,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
  * so it can be freed.
  */
 static int
-lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
        LPFC_MBOXQ_t       *mb;
        LPFC_MBOXQ_t       *nextmb;
@@ -1567,17 +1551,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
                        phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
                        ndlp->nlp_state, ndlp->nlp_rpi);
 
-       lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
-
-       /*
-        * if unloading the driver - just leave the remote port in place.
-        * The driver unload will force the attached devices to detach
-        * and flush cache's w/o generating flush errors.
-        */
-       if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
-               lpfc_unregister_remote_port(phba, ndlp);
-               ndlp->nlp_sid = NLP_NO_SID;
-       }
+       lpfc_dequeue_node(phba, ndlp);
 
        /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
        if ((mb = phba->sli.mbox_active)) {
@@ -1599,11 +1573,12 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
                        }
                        list_del(&mb->list);
                        mempool_free(mb, phba->mbox_mem_pool);
+                       lpfc_nlp_put(ndlp);
                }
        }
        spin_unlock_irq(phba->host->host_lock);
 
-       lpfc_els_abort(phba,ndlp,0);
+       lpfc_els_abort(phba,ndlp);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~NLP_DELAY_TMO;
        spin_unlock_irq(phba->host->host_lock);
@@ -1624,27 +1599,27 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
  * If we are in the middle of using the nlp in the discovery state
  * machine, defer the free till we reach the end of the state machine.
  */
-int
-lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+static void
+lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
+       struct lpfc_rport_data *rdata;
 
        if (ndlp->nlp_flag & NLP_DELAY_TMO) {
                lpfc_cancel_retry_delay_tmo(phba, ndlp);
        }
 
-       if (ndlp->nlp_disc_refcnt) {
-               spin_lock_irq(phba->host->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_REMOVE;
-               spin_unlock_irq(phba->host->host_lock);
-       } else {
-               lpfc_freenode(phba, ndlp);
-               mempool_free( ndlp, phba->nlp_mem_pool);
+       lpfc_cleanup_node(phba, ndlp);
+
+       if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
+               put_device(&ndlp->rport->dev);
+               rdata = ndlp->rport->dd_data;
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
        }
-       return 0;
 }
 
 static int
-lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
+lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
 {
        D_ID mydid;
        D_ID ndlpdid;
@@ -1693,57 +1668,36 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
        return 0;
 }
 
-/* Search for a nodelist entry on a specific list */
+/* Search for a nodelist entry */
 struct lpfc_nodelist *
-lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
+lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
 {
        struct lpfc_nodelist *ndlp;
-       struct list_head *lists[]={&phba->fc_nlpunmap_list,
-                                  &phba->fc_nlpmap_list,
-                                  &phba->fc_plogi_list,
-                                  &phba->fc_adisc_list,
-                                  &phba->fc_reglogin_list,
-                                  &phba->fc_prli_list,
-                                  &phba->fc_npr_list,
-                                  &phba->fc_unused_list};
-       uint32_t search[]={NLP_SEARCH_UNMAPPED,
-                          NLP_SEARCH_MAPPED,
-                          NLP_SEARCH_PLOGI,
-                          NLP_SEARCH_ADISC,
-                          NLP_SEARCH_REGLOGIN,
-                          NLP_SEARCH_PRLI,
-                          NLP_SEARCH_NPR,
-                          NLP_SEARCH_UNUSED};
-       int i;
        uint32_t data1;
 
        spin_lock_irq(phba->host->host_lock);
-       for (i = 0; i < ARRAY_SIZE(lists); i++ ) {
-               if (!(order & search[i]))
-                       continue;
-               list_for_each_entry(ndlp, lists[i], nlp_listp) {
-                       if (lpfc_matchdid(phba, ndlp, did)) {
-                               data1 = (((uint32_t) ndlp->nlp_state << 24) |
-                                        ((uint32_t) ndlp->nlp_xri << 16) |
-                                        ((uint32_t) ndlp->nlp_type << 8) |
-                                        ((uint32_t) ndlp->nlp_rpi & 0xff));
-                               lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-                                               "%d:0929 FIND node DID "
-                                               " Data: x%p x%x x%x x%x\n",
-                                               phba->brd_no,
-                                               ndlp, ndlp->nlp_DID,
-                                               ndlp->nlp_flag, data1);
-                               spin_unlock_irq(phba->host->host_lock);
-                               return ndlp;
-                       }
+       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (lpfc_matchdid(phba, ndlp, did)) {
+                       data1 = (((uint32_t) ndlp->nlp_state << 24) |
+                                ((uint32_t) ndlp->nlp_xri << 16) |
+                                ((uint32_t) ndlp->nlp_type << 8) |
+                                ((uint32_t) ndlp->nlp_rpi & 0xff));
+                       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+                                       "%d:0929 FIND node DID "
+                                       " Data: x%p x%x x%x x%x\n",
+                                       phba->brd_no,
+                                       ndlp, ndlp->nlp_DID,
+                                       ndlp->nlp_flag, data1);
+                       spin_unlock_irq(phba->host->host_lock);
+                       return ndlp;
                }
        }
        spin_unlock_irq(phba->host->host_lock);
 
        /* FIND node did <did> NOT FOUND */
        lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-                       "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n",
-                       phba->brd_no, did, order);
+                       "%d:0932 FIND node did x%x NOT FOUND.\n",
+                       phba->brd_no, did);
        return NULL;
 }
 
@@ -1751,9 +1705,8 @@ struct lpfc_nodelist *
 lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
 {
        struct lpfc_nodelist *ndlp;
-       uint32_t flg;
 
-       ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
+       ndlp = lpfc_findnode_did(phba, did);
        if (!ndlp) {
                if ((phba->fc_flag & FC_RSCN_MODE) &&
                   ((lpfc_rscn_payload_check(phba, did) == 0)))
@@ -1763,8 +1716,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
                if (!ndlp)
                        return NULL;
                lpfc_nlp_init(phba, ndlp, did);
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                ndlp->nlp_flag |= NLP_NPR_2B_DISC;
                return ndlp;
        }
@@ -1780,11 +1732,10 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
                } else
                        ndlp = NULL;
        } else {
-               flg = ndlp->nlp_flag & NLP_LIST_MASK;
-               if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
+               if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
+                   ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
                        return NULL;
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                ndlp->nlp_flag |= NLP_NPR_2B_DISC;
        }
        return ndlp;
@@ -1842,8 +1793,9 @@ lpfc_disc_start(struct lpfc_hba * phba)
        struct lpfc_sli *psli;
        LPFC_MBOXQ_t *mbox;
        struct lpfc_nodelist *ndlp, *next_ndlp;
-       uint32_t did_changed, num_sent;
+       uint32_t num_sent;
        uint32_t clear_la_pending;
+       int did_changed;
        int rc;
 
        psli = &phba->sli;
@@ -1877,14 +1829,13 @@ lpfc_disc_start(struct lpfc_hba * phba)
                        phba->fc_plogi_cnt, phba->fc_adisc_cnt);
 
        /* If our did changed, we MUST do PLOGI */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                               nlp_listp) {
-               if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-                       if (did_changed) {
-                               spin_lock_irq(phba->host->host_lock);
-                               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-                               spin_unlock_irq(phba->host->host_lock);
-                       }
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+                   did_changed) {
+                       spin_lock_irq(phba->host->host_lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+                       spin_unlock_irq(phba->host->host_lock);
                }
        }
 
@@ -1944,11 +1895,11 @@ lpfc_disc_start(struct lpfc_hba * phba)
 static void
 lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
+       LIST_HEAD(completions);
        struct lpfc_sli *psli;
        IOCB_t     *icmd;
        struct lpfc_iocbq    *iocb, *next_iocb;
        struct lpfc_sli_ring *pring;
-       struct lpfc_dmabuf   *mp;
 
        psli = &phba->sli;
        pring = &psli->ring[LPFC_ELS_RING];
@@ -1956,6 +1907,7 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
        /* Error matching iocb on txq or txcmplq
         * First check the txq.
         */
+       spin_lock_irq(phba->host->host_lock);
        list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
                if (iocb->context1 != ndlp) {
                        continue;
@@ -1964,9 +1916,8 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
                if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
                    (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
 
-                       list_del(&iocb->list);
+                       list_move_tail(&iocb->list, &completions);
                        pring->txq_cnt--;
-                       lpfc_els_free_iocb(phba, iocb);
                }
        }
 
@@ -1978,43 +1929,22 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
                icmd = &iocb->iocb;
                if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
                    (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               }
+       }
+       spin_unlock_irq(phba->host->host_lock);
 
-                       iocb->iocb_cmpl = NULL;
-                       /* context2 = cmd, context2->next = rsp, context3 =
-                          bpl */
-                       if (iocb->context2) {
-                               /* Free the response IOCB before handling the
-                                  command. */
-
-                               mp = (struct lpfc_dmabuf *) (iocb->context2);
-                               mp = list_get_first(&mp->list,
-                                                   struct lpfc_dmabuf,
-                                                   list);
-                               if (mp) {
-                                       /* Delay before releasing rsp buffer to
-                                        * give UNREG mbox a chance to take
-                                        * effect.
-                                        */
-                                       list_add(&mp->list,
-                                               &phba->freebufList);
-                               }
-                               lpfc_mbuf_free(phba,
-                                              ((struct lpfc_dmabuf *)
-                                               iocb->context2)->virt,
-                                              ((struct lpfc_dmabuf *)
-                                               iocb->context2)->phys);
-                               kfree(iocb->context2);
-                       }
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               list_del(&iocb->list);
 
-                       if (iocb->context3) {
-                               lpfc_mbuf_free(phba,
-                                              ((struct lpfc_dmabuf *)
-                                               iocb->context3)->virt,
-                                              ((struct lpfc_dmabuf *)
-                                               iocb->context3)->phys);
-                               kfree(iocb->context3);
-                       }
-               }
+               if (iocb->iocb_cmpl) {
+                       icmd = &iocb->iocb;
+                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+               } else
+                       lpfc_sli_release_iocbq(phba, iocb);
        }
 
        return;
@@ -2025,21 +1955,16 @@ lpfc_disc_flush_list(struct lpfc_hba * phba)
 {
        struct lpfc_nodelist *ndlp, *next_ndlp;
 
-       if (phba->fc_plogi_cnt) {
-               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
-                                       nlp_listp) {
-                       lpfc_free_tx(phba, ndlp);
-                       lpfc_nlp_remove(phba, ndlp);
-               }
-       }
-       if (phba->fc_adisc_cnt) {
-               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
-                                       nlp_listp) {
-                       lpfc_free_tx(phba, ndlp);
-                       lpfc_nlp_remove(phba, ndlp);
+       if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
+               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
+                           ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
+                               lpfc_free_tx(phba, ndlp);
+                               lpfc_nlp_put(ndlp);
+                       }
                }
        }
-       return;
 }
 
 /*****************************************************************************/
@@ -2108,11 +2033,13 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
                                 phba->brd_no);
 
                /* Start discovery by sending FLOGI, clean up old rpis */
-               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                                       nlp_listp) {
+               list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                               continue;
                        if (ndlp->nlp_type & NLP_FABRIC) {
                                /* Clean up the ndlp on Fabric connections */
-                               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                               lpfc_drop_node(phba, ndlp);
                        } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
                                /* Fail outstanding IO now since device
                                 * is marked for PLOGI.
@@ -2153,9 +2080,9 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
                                "login\n", phba->brd_no);
 
                /* Next look for NameServer ndlp */
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
+               ndlp = lpfc_findnode_did(phba, NameServer_DID);
                if (ndlp)
-                       lpfc_nlp_remove(phba, ndlp);
+                       lpfc_nlp_put(ndlp);
                /* Start discovery */
                lpfc_disc_start(phba);
                break;
@@ -2168,9 +2095,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
                                phba->brd_no,
                                phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
 
-               ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED,
-                                                               NameServer_DID);
-               if (ndlp) {
+               ndlp = lpfc_findnode_did(phba, NameServer_DID);
+               if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
                        if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
                                /* Try it one more time */
                                rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
@@ -2220,6 +2146,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
                initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
                rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
                                         (MBX_NOWAIT | MBX_STOP_IOCB));
+               lpfc_set_loopback_flag(phba);
                if (rc == MBX_NOT_FINISHED)
                        mempool_free(initlinkmbox, phba->mbox_mem_pool);
 
@@ -2317,8 +2244,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        ndlp->nlp_rpi = mb->un.varWords[0];
        ndlp->nlp_type |= NLP_FABRIC;
-       ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
 
        /* Start issuing Fabric-Device Management Interface (FDMI)
         * command to 0xfffffa (FDMI well known port)
@@ -2333,87 +2259,100 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
                mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
        }
 
+                               /* Mailbox took a reference to the node */
+       lpfc_nlp_put(ndlp);
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
-       mempool_free( pmb, phba->mbox_mem_pool);
+       mempool_free(pmb, phba->mbox_mem_pool);
 
        return;
 }
 
+static int
+lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param)
+{
+       uint16_t *rpi = param;
+
+       return ndlp->nlp_rpi == *rpi;
+}
+
+static int
+lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param)
+{
+       return memcmp(&ndlp->nlp_portname, param,
+                     sizeof(ndlp->nlp_portname)) == 0;
+}
+
+/*
+ * Search node lists for a remote port matching filter criteria
+ * Caller needs to hold host_lock before calling this routine.
+ */
+struct lpfc_nodelist *
+__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+{
+       struct lpfc_nodelist *ndlp;
+
+       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
+                   filter(ndlp, param))
+                       return ndlp;
+       }
+       return NULL;
+}
+
 /*
- * This routine looks up the ndlp  lists
- * for the given RPI. If rpi found
- * it return the node list pointer
- * else return NULL.
+ * Search node lists for a remote port matching filter criteria
+ * This routine is used when the caller does NOT have host_lock.
  */
+struct lpfc_nodelist *
+lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+{
+       struct lpfc_nodelist *ndlp;
+
+       spin_lock_irq(phba->host->host_lock);
+       ndlp = __lpfc_find_node(phba, filter, param);
+       spin_unlock_irq(phba->host->host_lock);
+       return ndlp;
+}
+
+/*
+ * This routine looks up the ndlp lists for the given RPI. If rpi found it
+ * returns the node list pointer else return NULL.
+ */
+struct lpfc_nodelist *
+__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
+{
+       return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
+}
+
 struct lpfc_nodelist *
 lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
 {
        struct lpfc_nodelist *ndlp;
-       struct list_head * lists[]={&phba->fc_nlpunmap_list,
-                                   &phba->fc_nlpmap_list,
-                                   &phba->fc_plogi_list,
-                                   &phba->fc_adisc_list,
-                                   &phba->fc_reglogin_list};
-       int i;
 
        spin_lock_irq(phba->host->host_lock);
-       for (i = 0; i < ARRAY_SIZE(lists); i++ )
-               list_for_each_entry(ndlp, lists[i], nlp_listp)
-                       if (ndlp->nlp_rpi == rpi) {
-                               spin_unlock_irq(phba->host->host_lock);
-                               return ndlp;
-                       }
+       ndlp = __lpfc_findnode_rpi(phba, rpi);
        spin_unlock_irq(phba->host->host_lock);
-       return NULL;
+       return ndlp;
 }
 
 /*
- * This routine looks up the ndlp  lists
- * for the given WWPN. If WWPN found
- * it return the node list pointer
- * else return NULL.
+ * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
+ * returns the node list pointer else return NULL.
  */
 struct lpfc_nodelist *
-lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order,
-                  struct lpfc_name * wwpn)
+lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
 {
        struct lpfc_nodelist *ndlp;
-       struct list_head * lists[]={&phba->fc_nlpunmap_list,
-                                   &phba->fc_nlpmap_list,
-                                   &phba->fc_npr_list,
-                                   &phba->fc_plogi_list,
-                                   &phba->fc_adisc_list,
-                                   &phba->fc_reglogin_list,
-                                   &phba->fc_prli_list};
-       uint32_t search[]={NLP_SEARCH_UNMAPPED,
-                          NLP_SEARCH_MAPPED,
-                          NLP_SEARCH_NPR,
-                          NLP_SEARCH_PLOGI,
-                          NLP_SEARCH_ADISC,
-                          NLP_SEARCH_REGLOGIN,
-                          NLP_SEARCH_PRLI};
-       int i;
 
        spin_lock_irq(phba->host->host_lock);
-       for (i = 0; i < ARRAY_SIZE(lists); i++ ) {
-               if (!(order & search[i]))
-                       continue;
-               list_for_each_entry(ndlp, lists[i], nlp_listp) {
-                       if (memcmp(&ndlp->nlp_portname, wwpn,
-                                  sizeof(struct lpfc_name)) == 0) {
-                               spin_unlock_irq(phba->host->host_lock);
-                               return ndlp;
-                       }
-               }
-       }
+       ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
        spin_unlock_irq(phba->host->host_lock);
        return NULL;
 }
 
 void
-lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-                uint32_t did)
+lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
 {
        memset(ndlp, 0, sizeof (struct lpfc_nodelist));
        INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
@@ -2423,5 +2362,30 @@ lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
        ndlp->nlp_DID = did;
        ndlp->nlp_phba = phba;
        ndlp->nlp_sid = NLP_NO_SID;
+       INIT_LIST_HEAD(&ndlp->nlp_listp);
+       kref_init(&ndlp->kref);
        return;
 }
+
+void
+lpfc_nlp_release(struct kref *kref)
+{
+       struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
+                                                 kref);
+       lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
+       mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
+}
+
+struct lpfc_nodelist *
+lpfc_nlp_get(struct lpfc_nodelist *ndlp)
+{
+       if (ndlp)
+               kref_get(&ndlp->kref);
+       return ndlp;
+}
+
+int
+lpfc_nlp_put(struct lpfc_nodelist *ndlp)
+{
+       return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0;
+}
index f79cb61369065007a88ca4dccb6e50c2bb1ec174..2623a9bc7775f0f4fe8bd5026f8964303ad42ee2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -1078,6 +1078,8 @@ typedef struct {
 /* Start FireFly Register definitions */
 #define PCI_VENDOR_ID_EMULEX        0x10df
 #define PCI_DEVICE_ID_FIREFLY       0x1ae5
+#define PCI_DEVICE_ID_SAT_SMB       0xf011
+#define PCI_DEVICE_ID_SAT_MID       0xf015
 #define PCI_DEVICE_ID_RFLY          0xf095
 #define PCI_DEVICE_ID_PFLY          0xf098
 #define PCI_DEVICE_ID_LP101         0xf0a1
@@ -1089,6 +1091,9 @@ typedef struct {
 #define PCI_DEVICE_ID_NEPTUNE       0xf0f5
 #define PCI_DEVICE_ID_NEPTUNE_SCSP  0xf0f6
 #define PCI_DEVICE_ID_NEPTUNE_DCSP  0xf0f7
+#define PCI_DEVICE_ID_SAT           0xf100
+#define PCI_DEVICE_ID_SAT_SCSP      0xf111
+#define PCI_DEVICE_ID_SAT_DCSP      0xf112
 #define PCI_DEVICE_ID_SUPERFLY      0xf700
 #define PCI_DEVICE_ID_DRAGONFLY     0xf800
 #define PCI_DEVICE_ID_CENTAUR       0xf900
@@ -1098,6 +1103,7 @@ typedef struct {
 #define PCI_DEVICE_ID_LP10000S      0xfc00
 #define PCI_DEVICE_ID_LP11000S      0xfc10
 #define PCI_DEVICE_ID_LPE11000S     0xfc20
+#define PCI_DEVICE_ID_SAT_S         0xfc40
 #define PCI_DEVICE_ID_HELIOS        0xfd00
 #define PCI_DEVICE_ID_HELIOS_SCSP   0xfd11
 #define PCI_DEVICE_ID_HELIOS_DCSP   0xfd12
@@ -1118,6 +1124,7 @@ typedef struct {
 #define HELIOS_JEDEC_ID             0x0364
 #define ZEPHYR_JEDEC_ID             0x0577
 #define VIPER_JEDEC_ID              0x4838
+#define SATURN_JEDEC_ID             0x1004
 
 #define JEDEC_ID_MASK               0x0FFFF000
 #define JEDEC_ID_SHIFT              12
@@ -1565,7 +1572,7 @@ typedef struct {
 #define LINK_SPEED_1G   1       /* 1 Gigabaud */
 #define LINK_SPEED_2G   2       /* 2 Gigabaud */
 #define LINK_SPEED_4G   4       /* 4 Gigabaud */
-#define LINK_SPEED_8G   8       /* 4 Gigabaud */
+#define LINK_SPEED_8G   8       /* 8 Gigabaud */
 #define LINK_SPEED_10G   16      /* 10 Gigabaud */
 
 } INIT_LINK_VAR;
index dcf6106f557a0dac93efb20710dcbf9d1bec7bc7..dcb4ba0ecee1825067b2344562ab0e21d4df0601 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -386,12 +386,12 @@ lpfc_config_port_post(struct lpfc_hba * phba)
         * Setup the ring 0 (els)  timeout handler
         */
        timeout = phba->fc_ratov << 1;
-       phba->els_tmofunc.expires = jiffies + HZ * timeout;
-       add_timer(&phba->els_tmofunc);
+       mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
 
        lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
        pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
        rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+       lpfc_set_loopback_flag(phba);
        if (rc != MBX_SUCCESS) {
                lpfc_printf_log(phba,
                                KERN_ERR,
@@ -418,33 +418,6 @@ lpfc_config_port_post(struct lpfc_hba * phba)
        return (0);
 }
 
-static int
-lpfc_discovery_wait(struct lpfc_hba *phba)
-{
-       int i = 0;
-
-       while ((phba->hba_state != LPFC_HBA_READY) ||
-              (phba->num_disc_nodes) || (phba->fc_prli_sent) ||
-              ((phba->fc_map_cnt == 0) && (i<2)) ||
-              (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
-               /* Check every second for 30 retries. */
-               i++;
-               if (i > 30) {
-                       return -ETIMEDOUT;
-               }
-               if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
-                       /* The link is down.  Set linkdown timeout */
-                       return -ETIMEDOUT;
-               }
-
-               /* Delay for 1 second to give discovery time to complete. */
-               msleep(1000);
-
-       }
-
-       return 0;
-}
-
 /************************************************************************/
 /*                                                                      */
 /*    lpfc_hba_down_prep                                                */
@@ -550,12 +523,15 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
                 * There was a firmware error.  Take the hba offline and then
                 * attempt to restart it.
                 */
+               lpfc_offline_prep(phba);
                lpfc_offline(phba);
                lpfc_sli_brdrestart(phba);
                if (lpfc_online(phba) == 0) {   /* Initialize the HBA */
                        mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+                       lpfc_unblock_mgmt_io(phba);
                        return;
                }
+               lpfc_unblock_mgmt_io(phba);
        } else {
                /* The if clause above forces this code path when the status
                 * failure is a value other than FFER6.  Do not call the offline
@@ -573,7 +549,9 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
                                SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+               lpfc_offline_prep(phba);
                lpfc_offline(phba);
+               lpfc_unblock_mgmt_io(phba);
                phba->hba_state = LPFC_HBA_ERROR;
                lpfc_hba_down_post(phba);
        }
@@ -633,7 +611,7 @@ lpfc_handle_latt_free_mbuf:
 lpfc_handle_latt_free_mp:
        kfree(mp);
 lpfc_handle_latt_free_pmb:
-       kfree(pmb);
+       mempool_free(pmb, phba->mbox_mem_pool);
 lpfc_handle_latt_err_exit:
        /* Enable Link attention interrupts */
        spin_lock_irq(phba->host->host_lock);
@@ -925,6 +903,24 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
                m = (typeof(m)){"LPe11000-S", max_speed,
                        "PCIe"};
                break;
+       case PCI_DEVICE_ID_SAT:
+               m = (typeof(m)){"LPe12000", max_speed, "PCIe"};
+               break;
+       case PCI_DEVICE_ID_SAT_MID:
+               m = (typeof(m)){"LPe1250", max_speed, "PCIe"};
+               break;
+       case PCI_DEVICE_ID_SAT_SMB:
+               m = (typeof(m)){"LPe121", max_speed, "PCIe"};
+               break;
+       case PCI_DEVICE_ID_SAT_DCSP:
+               m = (typeof(m)){"LPe12002-SP", max_speed, "PCIe"};
+               break;
+       case PCI_DEVICE_ID_SAT_SCSP:
+               m = (typeof(m)){"LPe12000-SP", max_speed, "PCIe"};
+               break;
+       case PCI_DEVICE_ID_SAT_S:
+               m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
+               break;
        default:
                m = (typeof(m)){ NULL };
                break;
@@ -1174,69 +1170,17 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
 }
 
 static void
-lpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind)
+lpfc_cleanup(struct lpfc_hba * phba)
 {
        struct lpfc_nodelist *ndlp, *next_ndlp;
 
        /* clean up phba - lpfc specific */
        lpfc_can_disctmo(phba);
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+               lpfc_nlp_put(ndlp);
 
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list,
-                                nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
-
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
-                               nlp_listp) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       }
-
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
-
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
-
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
+       INIT_LIST_HEAD(&phba->fc_nodes);
 
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
-
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
-                               nlp_listp) {
-               lpfc_nlp_remove(phba, ndlp);
-       }
-
-       INIT_LIST_HEAD(&phba->fc_nlpmap_list);
-       INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
-       INIT_LIST_HEAD(&phba->fc_unused_list);
-       INIT_LIST_HEAD(&phba->fc_plogi_list);
-       INIT_LIST_HEAD(&phba->fc_adisc_list);
-       INIT_LIST_HEAD(&phba->fc_reglogin_list);
-       INIT_LIST_HEAD(&phba->fc_prli_list);
-       INIT_LIST_HEAD(&phba->fc_npr_list);
-
-       phba->fc_map_cnt   = 0;
-       phba->fc_unmap_cnt = 0;
-       phba->fc_plogi_cnt = 0;
-       phba->fc_adisc_cnt = 0;
-       phba->fc_reglogin_cnt = 0;
-       phba->fc_prli_cnt  = 0;
-       phba->fc_npr_cnt   = 0;
-       phba->fc_unused_cnt= 0;
        return;
 }
 
@@ -1262,21 +1206,6 @@ lpfc_stop_timer(struct lpfc_hba * phba)
 {
        struct lpfc_sli *psli = &phba->sli;
 
-       /* Instead of a timer, this has been converted to a
-        * deferred procedding list.
-        */
-       while (!list_empty(&phba->freebufList)) {
-
-               struct lpfc_dmabuf *mp = NULL;
-
-               list_remove_head((&phba->freebufList), mp,
-                                struct lpfc_dmabuf, list);
-               if (mp) {
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                       kfree(mp);
-               }
-       }
-
        del_timer_sync(&phba->fcp_poll_timer);
        del_timer_sync(&phba->fc_estabtmo);
        del_timer_sync(&phba->fc_disctmo);
@@ -1302,60 +1231,76 @@ lpfc_online(struct lpfc_hba * phba)
                       "%d:0458 Bring Adapter online\n",
                       phba->brd_no);
 
-       if (!lpfc_sli_queue_setup(phba))
+       lpfc_block_mgmt_io(phba);
+
+       if (!lpfc_sli_queue_setup(phba)) {
+               lpfc_unblock_mgmt_io(phba);
                return 1;
+       }
 
-       if (lpfc_sli_hba_setup(phba))   /* Initialize the HBA */
+       if (lpfc_sli_hba_setup(phba)) { /* Initialize the HBA */
+               lpfc_unblock_mgmt_io(phba);
                return 1;
+       }
 
        spin_lock_irq(phba->host->host_lock);
        phba->fc_flag &= ~FC_OFFLINE_MODE;
        spin_unlock_irq(phba->host->host_lock);
 
+       lpfc_unblock_mgmt_io(phba);
        return 0;
 }
 
-int
-lpfc_offline(struct lpfc_hba * phba)
+void
+lpfc_block_mgmt_io(struct lpfc_hba * phba)
 {
-       struct lpfc_sli_ring *pring;
-       struct lpfc_sli *psli;
        unsigned long iflag;
-       int i;
-       int cnt = 0;
 
-       if (!phba)
-               return 0;
+       spin_lock_irqsave(phba->host->host_lock, iflag);
+       phba->fc_flag |= FC_BLOCK_MGMT_IO;
+       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
+void
+lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
+{
+       unsigned long iflag;
+
+       spin_lock_irqsave(phba->host->host_lock, iflag);
+       phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
+       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
+void
+lpfc_offline_prep(struct lpfc_hba * phba)
+{
+       struct lpfc_nodelist  *ndlp, *next_ndlp;
 
        if (phba->fc_flag & FC_OFFLINE_MODE)
-               return 0;
+               return;
 
-       psli = &phba->sli;
+       lpfc_block_mgmt_io(phba);
 
        lpfc_linkdown(phba);
+
+       /* Issue an unreg_login to all nodes */
+       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
+                       lpfc_unreg_rpi(phba, ndlp);
+
        lpfc_sli_flush_mbox_queue(phba);
+}
 
-       for (i = 0; i < psli->num_rings; i++) {
-               pring = &psli->ring[i];
-               /* The linkdown event takes 30 seconds to timeout. */
-               while (pring->txcmplq_cnt) {
-                       mdelay(10);
-                       if (cnt++ > 3000) {
-                               lpfc_printf_log(phba,
-                                       KERN_WARNING, LOG_INIT,
-                                       "%d:0466 Outstanding IO when "
-                                       "bringing Adapter offline\n",
-                                       phba->brd_no);
-                               break;
-                       }
-               }
-       }
+void
+lpfc_offline(struct lpfc_hba * phba)
+{
+       unsigned long iflag;
 
+       if (phba->fc_flag & FC_OFFLINE_MODE)
+               return;
 
        /* stop all timers associated with this hba */
        lpfc_stop_timer(phba);
-       phba->work_hba_events = 0;
-       phba->work_ha = 0;
 
        lpfc_printf_log(phba,
                       KERN_WARNING,
@@ -1366,11 +1311,12 @@ lpfc_offline(struct lpfc_hba * phba)
        /* Bring down the SLI Layer and cleanup.  The HBA is offline
           now.  */
        lpfc_sli_hba_down(phba);
-       lpfc_cleanup(phba, 1);
+       lpfc_cleanup(phba);
        spin_lock_irqsave(phba->host->host_lock, iflag);
+       phba->work_hba_events = 0;
+       phba->work_ha = 0;
        phba->fc_flag |= FC_OFFLINE_MODE;
        spin_unlock_irqrestore(phba->host->host_lock, iflag);
-       return 0;
 }
 
 /******************************************************************************
@@ -1407,6 +1353,156 @@ lpfc_scsi_free(struct lpfc_hba * phba)
        return 0;
 }
 
+void lpfc_remove_device(struct lpfc_hba *phba)
+{
+       unsigned long iflag;
+
+       lpfc_free_sysfs_attr(phba);
+
+       spin_lock_irqsave(phba->host->host_lock, iflag);
+       phba->fc_flag |= FC_UNLOADING;
+
+       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+
+       fc_remove_host(phba->host);
+       scsi_remove_host(phba->host);
+
+       kthread_stop(phba->worker_thread);
+
+       /*
+        * Bring down the SLI Layer. This step disable all interrupts,
+        * clears the rings, discards all mailbox commands, and resets
+        * the HBA.
+        */
+       lpfc_sli_hba_down(phba);
+       lpfc_sli_brdrestart(phba);
+
+       /* Release the irq reservation */
+       free_irq(phba->pcidev->irq, phba);
+       pci_disable_msi(phba->pcidev);
+
+       lpfc_cleanup(phba);
+       lpfc_stop_timer(phba);
+       phba->work_hba_events = 0;
+
+       /*
+        * Call scsi_free before mem_free since scsi bufs are released to their
+        * corresponding pools here.
+        */
+       lpfc_scsi_free(phba);
+       lpfc_mem_free(phba);
+
+       /* Free resources associated with SLI2 interface */
+       dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
+                         phba->slim2p, phba->slim2p_mapping);
+
+       /* unmap adapter SLIM and Control Registers */
+       iounmap(phba->ctrl_regs_memmap_p);
+       iounmap(phba->slim_memmap_p);
+
+       pci_release_regions(phba->pcidev);
+       pci_disable_device(phba->pcidev);
+
+       idr_remove(&lpfc_hba_index, phba->brd_no);
+       scsi_host_put(phba->host);
+}
+
+void lpfc_scan_start(struct Scsi_Host *host)
+{
+       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+
+       if (lpfc_alloc_sysfs_attr(phba))
+               goto error;
+
+       phba->MBslimaddr = phba->slim_memmap_p;
+       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+
+       if (lpfc_sli_hba_setup(phba))
+               goto error;
+
+       /*
+        * hba setup may have changed the hba_queue_depth so we need to adjust
+        * the value of can_queue.
+        */
+       host->can_queue = phba->cfg_hba_queue_depth - 10;
+       return;
+
+error:
+       lpfc_remove_device(phba);
+}
+
+int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+
+       if (!phba->host)
+               return 1;
+       if (time >= 30 * HZ)
+               goto finished;
+
+       if (phba->hba_state != LPFC_HBA_READY)
+               return 0;
+       if (phba->num_disc_nodes || phba->fc_prli_sent)
+               return 0;
+       if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
+               return 0;
+       if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
+               return 0;
+       if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
+               return 0;
+
+finished:
+       if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+               spin_lock_irq(shost->host_lock);
+               lpfc_poll_start_timer(phba);
+               spin_unlock_irq(shost->host_lock);
+       }
+
+       /*
+        * set fixed host attributes
+        * Must done after lpfc_sli_hba_setup()
+        */
+
+       fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
+       fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
+       fc_host_supported_classes(shost) = FC_COS_CLASS3;
+
+       memset(fc_host_supported_fc4s(shost), 0,
+               sizeof(fc_host_supported_fc4s(shost)));
+       fc_host_supported_fc4s(shost)[2] = 1;
+       fc_host_supported_fc4s(shost)[7] = 1;
+
+       lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
+
+       fc_host_supported_speeds(shost) = 0;
+       if (phba->lmt & LMT_10Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
+       if (phba->lmt & LMT_4Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT;
+       if (phba->lmt & LMT_2Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT;
+       if (phba->lmt & LMT_1Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
+
+       fc_host_maxframe_size(shost) =
+               ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
+                (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
+
+       /* This value is also unchanging */
+       memset(fc_host_active_fc4s(shost), 0,
+               sizeof(fc_host_active_fc4s(shost)));
+       fc_host_active_fc4s(shost)[2] = 1;
+       fc_host_active_fc4s(shost)[7] = 1;
+
+       spin_lock_irq(shost->host_lock);
+       phba->fc_flag &= ~FC_LOADING;
+       spin_unlock_irq(shost->host_lock);
+
+       return 1;
+}
 
 static int __devinit
 lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
@@ -1445,9 +1541,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_put_host;
 
        host->unique_id = phba->brd_no;
-       INIT_LIST_HEAD(&phba->ctrspbuflist);
-       INIT_LIST_HEAD(&phba->rnidrspbuflist);
-       INIT_LIST_HEAD(&phba->freebufList);
 
        /* Initialize timers used by driver */
        init_timer(&phba->fc_estabtmo);
@@ -1482,16 +1575,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        host->max_lun = phba->cfg_max_luns;
        host->this_id = -1;
 
-       /* Initialize all internally managed lists. */
-       INIT_LIST_HEAD(&phba->fc_nlpmap_list);
-       INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
-       INIT_LIST_HEAD(&phba->fc_unused_list);
-       INIT_LIST_HEAD(&phba->fc_plogi_list);
-       INIT_LIST_HEAD(&phba->fc_adisc_list);
-       INIT_LIST_HEAD(&phba->fc_reglogin_list);
-       INIT_LIST_HEAD(&phba->fc_prli_list);
-       INIT_LIST_HEAD(&phba->fc_npr_list);
-
+       INIT_LIST_HEAD(&phba->fc_nodes);
 
        pci_set_master(pdev);
        retval = pci_set_mwi(pdev);
@@ -1609,13 +1693,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        host->transportt = lpfc_transport_template;
        pci_set_drvdata(pdev, host);
-       error = scsi_add_host(host, &pdev->dev);
-       if (error)
-               goto out_kthread_stop;
-
-       error = lpfc_alloc_sysfs_attr(phba);
-       if (error)
-               goto out_remove_host;
 
        if (phba->cfg_use_msi) {
                error = pci_enable_msi(phba->pcidev);
@@ -1631,73 +1708,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "%d:0451 Enable interrupt handler failed\n",
                        phba->brd_no);
-               goto out_free_sysfs_attr;
+               goto out_kthread_stop;
        }
-       phba->MBslimaddr = phba->slim_memmap_p;
-       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
-       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
-       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
 
-       error = lpfc_sli_hba_setup(phba);
-       if (error) {
-               error = -ENODEV;
+       error = scsi_add_host(host, &pdev->dev);
+       if (error)
                goto out_free_irq;
-       }
-
-       /*
-        * hba setup may have changed the hba_queue_depth so we need to adjust
-        * the value of can_queue.
-        */
-       host->can_queue = phba->cfg_hba_queue_depth - 10;
-
-       lpfc_discovery_wait(phba);
 
-       if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-               spin_lock_irq(phba->host->host_lock);
-               lpfc_poll_start_timer(phba);
-               spin_unlock_irq(phba->host->host_lock);
-       }
+       scsi_scan_host(host);
 
-       /*
-        * set fixed host attributes
-        * Must done after lpfc_sli_hba_setup()
-        */
-
-       fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn);
-       fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn);
-       fc_host_supported_classes(host) = FC_COS_CLASS3;
-
-       memset(fc_host_supported_fc4s(host), 0,
-               sizeof(fc_host_supported_fc4s(host)));
-       fc_host_supported_fc4s(host)[2] = 1;
-       fc_host_supported_fc4s(host)[7] = 1;
-
-       lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host));
-
-       fc_host_supported_speeds(host) = 0;
-       if (phba->lmt & LMT_10Gb)
-               fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;
-       if (phba->lmt & LMT_4Gb)
-               fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;
-       if (phba->lmt & LMT_2Gb)
-               fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT;
-       if (phba->lmt & LMT_1Gb)
-               fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT;
-
-       fc_host_maxframe_size(host) =
-               ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
-                (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
-
-       /* This value is also unchanging */
-       memset(fc_host_active_fc4s(host), 0,
-               sizeof(fc_host_active_fc4s(host)));
-       fc_host_active_fc4s(host)[2] = 1;
-       fc_host_active_fc4s(host)[7] = 1;
-
-       spin_lock_irq(phba->host->host_lock);
-       phba->fc_flag &= ~FC_LOADING;
-       spin_unlock_irq(phba->host->host_lock);
        return 0;
 
 out_free_irq:
@@ -1705,11 +1724,6 @@ out_free_irq:
        phba->work_hba_events = 0;
        free_irq(phba->pcidev->irq, phba);
        pci_disable_msi(phba->pcidev);
-out_free_sysfs_attr:
-       lpfc_free_sysfs_attr(phba);
-out_remove_host:
-       fc_remove_host(phba->host);
-       scsi_remove_host(phba->host);
 out_kthread_stop:
        kthread_stop(phba->worker_thread);
 out_free_iocbq:
@@ -1747,56 +1761,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host   *host = pci_get_drvdata(pdev);
        struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata;
-       unsigned long iflag;
-
-       lpfc_free_sysfs_attr(phba);
-
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->fc_flag |= FC_UNLOADING;
-
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
 
-       fc_remove_host(phba->host);
-       scsi_remove_host(phba->host);
-
-       kthread_stop(phba->worker_thread);
-
-       /*
-        * Bring down the SLI Layer. This step disable all interrupts,
-        * clears the rings, discards all mailbox commands, and resets
-        * the HBA.
-        */
-       lpfc_sli_hba_down(phba);
-       lpfc_sli_brdrestart(phba);
-
-       /* Release the irq reservation */
-       free_irq(phba->pcidev->irq, phba);
-       pci_disable_msi(phba->pcidev);
-
-       lpfc_cleanup(phba, 0);
-       lpfc_stop_timer(phba);
-       phba->work_hba_events = 0;
-
-       /*
-        * Call scsi_free before mem_free since scsi bufs are released to their
-        * corresponding pools here.
-        */
-       lpfc_scsi_free(phba);
-       lpfc_mem_free(phba);
-
-       /* Free resources associated with SLI2 interface */
-       dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
-                         phba->slim2p, phba->slim2p_mapping);
-
-       /* unmap adapter SLIM and Control Registers */
-       iounmap(phba->ctrl_regs_memmap_p);
-       iounmap(phba->slim_memmap_p);
-
-       pci_release_regions(phba->pcidev);
-       pci_disable_device(phba->pcidev);
-
-       idr_remove(&lpfc_hba_index, phba->brd_no);
-       scsi_host_put(phba->host);
+       lpfc_remove_device(phba);
 
        pci_set_drvdata(pdev, NULL);
 }
@@ -1941,6 +1907,18 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
                PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
+               PCI_ANY_ID, PCI_ANY_ID, },
        { 0 }
 };
 
index 4d016c2a1b26ebd14a8eb577d73c2c809bdd1337..8041c3f06f7b466483c4ec61d256adc49c2b6d6c 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -212,6 +212,7 @@ lpfc_init_link(struct lpfc_hba * phba,
                        case LINK_SPEED_1G:
                        case LINK_SPEED_2G:
                        case LINK_SPEED_4G:
+                       case LINK_SPEED_8G:
                                mb->un.varInitLnk.link_flags |=
                                                        FLAGS_LINK_SPEED;
                                mb->un.varInitLnk.link_speed = linkspeed;
index 0c7e731dc45a6cdba715693d4c72ae0526920a7b..b309841e3846a571aaadd44fe60c950587315203 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -168,14 +168,13 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
  * routine effectively results in a "software abort".
  */
 int
-lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-       int send_abts)
+lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
+       LIST_HEAD(completions);
        struct lpfc_sli *psli;
        struct lpfc_sli_ring *pring;
        struct lpfc_iocbq *iocb, *next_iocb;
-       IOCB_t *icmd;
-       int    found = 0;
+       IOCB_t *cmd;
 
        /* Abort outstanding I/O on NPort <nlp_DID> */
        lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
@@ -188,75 +187,39 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
        pring = &psli->ring[LPFC_ELS_RING];
 
        /* First check the txq */
-       do {
-               found = 0;
-               spin_lock_irq(phba->host->host_lock);
-               list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-                       /* Check to see if iocb matches the nport we are looking
-                          for */
-                       if ((lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))) {
-                               found = 1;
-                               /* It matches, so deque and call compl with an
-                                  error */
-                               list_del(&iocb->list);
-                               pring->txq_cnt--;
-                               if (iocb->iocb_cmpl) {
-                                       icmd = &iocb->iocb;
-                                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                                       spin_unlock_irq(phba->host->host_lock);
-                                       (iocb->iocb_cmpl) (phba, iocb, iocb);
-                                       spin_lock_irq(phba->host->host_lock);
-                               } else
-                                       lpfc_sli_release_iocbq(phba, iocb);
-                               break;
-                       }
+       spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
+               /* Check to see if iocb matches the nport we are looking
+                  for */
+               if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
+                       /* It matches, so deque and call compl with an
+                          error */
+                       list_move_tail(&iocb->list, &completions);
+                       pring->txq_cnt--;
                }
-               spin_unlock_irq(phba->host->host_lock);
-       } while (found);
+       }
 
-       /* Everything on txcmplq will be returned by firmware
-        * with a no rpi / linkdown / abort error.  For ring 0,
-        * ELS discovery, we want to get rid of it right here.
-        */
        /* Next check the txcmplq */
-       do {
-               found = 0;
-               spin_lock_irq(phba->host->host_lock);
-               list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
-                                        list) {
-                       /* Check to see if iocb matches the nport we are looking
-                          for */
-                       if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
-                               found = 1;
-                               /* It matches, so deque and call compl with an
-                                  error */
-                               list_del(&iocb->list);
-                               pring->txcmplq_cnt--;
-
-                               icmd = &iocb->iocb;
-                               /* If the driver is completing an ELS
-                                * command early, flush it out of the firmware.
-                                */
-                               if (send_abts &&
-                                  (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) &&
-                                  (icmd->un.elsreq64.bdl.ulpIoTag32)) {
-                                       lpfc_sli_issue_abort_iotag32(phba,
-                                                            pring, iocb);
-                               }
-                               if (iocb->iocb_cmpl) {
-                                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                                       spin_unlock_irq(phba->host->host_lock);
-                                       (iocb->iocb_cmpl) (phba, iocb, iocb);
-                                       spin_lock_irq(phba->host->host_lock);
-                               } else
-                                       lpfc_sli_release_iocbq(phba, iocb);
-                               break;
-                       }
-               }
-               spin_unlock_irq(phba->host->host_lock);
-       } while(found);
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
+               /* Check to see if iocb matches the nport we are looking
+                  for */
+               if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+       }
+       spin_unlock_irq(phba->host->host_lock);
+
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
+               list_del(&iocb->list);
+
+               if (iocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+               } else
+                       lpfc_sli_release_iocbq(phba, iocb);
+       }
 
        /* If we are delaying issuing an ELS command, cancel it */
        if (ndlp->nlp_flag & NLP_DELAY_TMO)
@@ -390,7 +353,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
         * queue this mbox command to be processed later.
         */
        mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
-       mbox->context2  = ndlp;
+       /*
+        * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
+        * command issued in lpfc_cmpl_els_acc().
+        */
        ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
 
        /*
@@ -404,7 +370,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
         */
        if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
                /* software abort outstanding PLOGI */
-               lpfc_els_abort(phba, ndlp, 1);
+               lpfc_els_abort(phba, ndlp);
        }
 
        lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
@@ -471,8 +437,7 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
        spin_unlock_irq(phba->host->host_lock);
        ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
        ndlp->nlp_prev_state = ndlp->nlp_state;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        return 0;
 }
 
@@ -502,12 +467,10 @@ lpfc_rcv_logo(struct lpfc_hba * phba,
 
                ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
                ndlp->nlp_prev_state = ndlp->nlp_state;
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        } else {
                ndlp->nlp_prev_state = ndlp->nlp_state;
-               ndlp->nlp_state = NLP_STE_UNUSED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
        }
 
        spin_lock_irq(phba->host->host_lock);
@@ -601,11 +564,10 @@ lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
 
        if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
                ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
-               ndlp->nlp_state = NLP_STE_UNUSED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
                return ndlp->nlp_state;
        }
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       lpfc_drop_node(phba, ndlp);
        return NLP_STE_FREED_NODE;
 }
 
@@ -614,7 +576,7 @@ lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
        lpfc_issue_els_logo(phba, ndlp, 0);
-       lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
        return ndlp->nlp_state;
 }
 
@@ -630,7 +592,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
        ndlp->nlp_flag |= NLP_LOGO_ACC;
        spin_unlock_irq(phba->host->host_lock);
        lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-       lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
 
        return ndlp->nlp_state;
 }
@@ -639,7 +601,7 @@ static uint32_t
 lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
                          struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       lpfc_drop_node(phba, ndlp);
        return NLP_STE_FREED_NODE;
 }
 
@@ -647,7 +609,7 @@ static uint32_t
 lpfc_device_rm_unused_node(struct lpfc_hba * phba,
                           struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       lpfc_drop_node(phba, ndlp);
        return NLP_STE_FREED_NODE;
 }
 
@@ -697,7 +659,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
@@ -712,7 +674,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        if (evt == NLP_EVT_RCV_LOGO) {
                lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
@@ -727,8 +689,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
        spin_unlock_irq(phba->host->host_lock);
        ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
        ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
 
        return ndlp->nlp_state;
 }
@@ -803,32 +764,26 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
                goto out;
 
        lpfc_unreg_rpi(phba, ndlp);
-       if (lpfc_reg_login
-           (phba, irsp->un.elsreq64.remoteID,
-            (uint8_t *) sp, mbox, 0) == 0) {
+       if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
+                          mbox, 0) == 0) {
                switch (ndlp->nlp_DID) {
                case NameServer_DID:
-                       mbox->mbox_cmpl =
-                               lpfc_mbx_cmpl_ns_reg_login;
+                       mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
                        break;
                case FDMI_DID:
-                       mbox->mbox_cmpl =
-                               lpfc_mbx_cmpl_fdmi_reg_login;
+                       mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
                        break;
                default:
-                       mbox->mbox_cmpl =
-                               lpfc_mbx_cmpl_reg_login;
+                       mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
                }
-               mbox->context2 = ndlp;
+               mbox->context2 = lpfc_nlp_get(ndlp);
                if (lpfc_sli_issue_mbox(phba, mbox,
                                        (MBX_NOWAIT | MBX_STOP_IOCB))
                    != MBX_NOT_FINISHED) {
-                       ndlp->nlp_state =
-                               NLP_STE_REG_LOGIN_ISSUE;
-                       lpfc_nlp_list(phba, ndlp,
-                                     NLP_REGLOGIN_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
                        return ndlp->nlp_state;
                }
+               lpfc_nlp_put(ndlp);
                mp = (struct lpfc_dmabuf *)mbox->context1;
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
@@ -841,7 +796,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
  out:
        /* Free this node since the driver cannot login or has the wrong
           sparm */
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       lpfc_drop_node(phba, ndlp);
        return NLP_STE_FREED_NODE;
 }
 
@@ -855,9 +810,9 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
        }
        else {
                /* software abort outstanding PLOGI */
-               lpfc_els_abort(phba, ndlp, 1);
+               lpfc_els_abort(phba, ndlp);
 
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
 }
@@ -868,11 +823,10 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
@@ -888,7 +842,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
        struct lpfc_iocbq *cmdiocb;
 
        /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
@@ -896,8 +850,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
                return ndlp->nlp_state;
        }
        ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-       ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-       lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
        lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
 
        return ndlp->nlp_state;
@@ -926,7 +879,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp, 0);
+       lpfc_els_abort(phba, ndlp);
 
        lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
@@ -987,20 +940,17 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
                memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
 
                ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                lpfc_unreg_rpi(phba, ndlp);
                return ndlp->nlp_state;
        }
 
        if (ndlp->nlp_type & NLP_FCP_TARGET) {
                ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-               ndlp->nlp_state = NLP_STE_MAPPED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
        } else {
                ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-               ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
        }
        return ndlp->nlp_state;
 }
@@ -1016,9 +966,9 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
        }
        else {
                /* software abort outstanding ADISC */
-               lpfc_els_abort(phba, ndlp, 1);
+               lpfc_els_abort(phba, ndlp);
 
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
 }
@@ -1029,11 +979,10 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        ndlp->nlp_flag |= NLP_NPR_ADISC;
@@ -1074,9 +1023,36 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
                             uint32_t evt)
 {
        struct lpfc_iocbq *cmdiocb;
+       LPFC_MBOXQ_t      *mb;
+       LPFC_MBOXQ_t      *nextmb;
+       struct lpfc_dmabuf *mp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
+       /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
+       if ((mb = phba->sli.mbox_active)) {
+               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+                       mb->context2 = NULL;
+                       mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+               }
+       }
+
+       spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
+               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+                       mp = (struct lpfc_dmabuf *) (mb->context1);
+                       if (mp) {
+                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+                               kfree(mp);
+                       }
+                       list_del(&mb->list);
+                       mempool_free(mb, phba->mbox_mem_pool);
+               }
+       }
+       spin_unlock_irq(phba->host->host_lock);
+
        lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
@@ -1133,8 +1109,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
                 */
                if (mb->mbxStatus == MBXERR_RPI_FULL) {
                        ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
-                       ndlp->nlp_state = NLP_STE_UNUSED_NODE;
-                       lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
                        return ndlp->nlp_state;
                }
 
@@ -1147,8 +1122,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
 
                lpfc_issue_els_logo(phba, ndlp, 0);
                ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-               ndlp->nlp_state = NLP_STE_NPR_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
                return ndlp->nlp_state;
        }
 
@@ -1157,13 +1131,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
        /* Only if we are not a fabric nport do we issue PRLI */
        if (!(ndlp->nlp_type & NLP_FABRIC)) {
                ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-               ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
-               lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
                lpfc_issue_els_prli(phba, ndlp, 0);
        } else {
                ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-               ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
        }
        return ndlp->nlp_state;
 }
@@ -1178,7 +1150,7 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
                return ndlp->nlp_state;
        }
        else {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
 }
@@ -1189,8 +1161,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
                               uint32_t evt)
 {
        ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
@@ -1230,7 +1201,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* Software abort outstanding PRLI before sending acc */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
@@ -1279,8 +1250,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
        irsp = &rspiocb->iocb;
        if (irsp->ulpStatus) {
                ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-               ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
-               lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
                return ndlp->nlp_state;
        }
 
@@ -1298,8 +1268,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
        }
 
        ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-       ndlp->nlp_state = NLP_STE_MAPPED_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
        return ndlp->nlp_state;
 }
 
@@ -1330,9 +1299,9 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
        }
        else {
                /* software abort outstanding PLOGI */
-               lpfc_els_abort(phba, ndlp, 1);
+               lpfc_els_abort(phba, ndlp);
 
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
 }
@@ -1359,11 +1328,10 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
                           struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
        /* software abort outstanding PRLI */
-       lpfc_els_abort(phba, ndlp, 1);
+       lpfc_els_abort(phba, ndlp);
 
        ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
@@ -1436,8 +1404,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
                           struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
        ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        lpfc_disc_set_adisc(phba, ndlp);
 
@@ -1518,8 +1485,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
-       ndlp->nlp_state = NLP_STE_NPR_NODE;
-       lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+       lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
        spin_lock_irq(phba->host->host_lock);
        ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
@@ -1551,8 +1517,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
        /* send PLOGI immediately, move to PLOGI issue state */
        if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
                ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-               ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-               lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+               lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
        }
 
@@ -1580,16 +1545,13 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
                        ndlp->nlp_flag &= ~NLP_NPR_ADISC;
                        spin_unlock_irq(phba->host->host_lock);
                        ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                       ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
                        lpfc_issue_els_adisc(phba, ndlp, 0);
                } else {
                        ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                       ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                        lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
                }
-
        }
        return ndlp->nlp_state;
 }
@@ -1627,13 +1589,11 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
                !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
                if (ndlp->nlp_flag & NLP_NPR_ADISC) {
                        ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                       ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
                        lpfc_issue_els_adisc(phba, ndlp, 0);
                } else {
                        ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-                       ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
-                       lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
+                       lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
                        lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
                }
        }
@@ -1682,7 +1642,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
 
        irsp = &rspiocb->iocb;
        if (irsp->ulpStatus) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
        return ndlp->nlp_state;
@@ -1700,7 +1660,7 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
 
        irsp = &rspiocb->iocb;
        if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
        return ndlp->nlp_state;
@@ -1728,7 +1688,7 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
 
        irsp = &rspiocb->iocb;
        if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
-               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               lpfc_drop_node(phba, ndlp);
                return NLP_STE_FREED_NODE;
        }
        return ndlp->nlp_state;
@@ -1749,7 +1709,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
                ndlp->nlp_rpi = mb->un.varWords[0];
        else {
                if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
-                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                       lpfc_drop_node(phba, ndlp);
                        return NLP_STE_FREED_NODE;
                }
        }
@@ -1765,7 +1725,7 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba,
                ndlp->nlp_flag |= NLP_NODEV_REMOVE;
                return ndlp->nlp_state;
        }
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+       lpfc_drop_node(phba, ndlp);
        return NLP_STE_FREED_NODE;
 }
 
@@ -1964,7 +1924,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba,
        uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
                         uint32_t);
 
-       ndlp->nlp_disc_refcnt++;
+       lpfc_nlp_get(ndlp);
        cur_state = ndlp->nlp_state;
 
        /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
@@ -1987,18 +1947,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba,
                       phba->brd_no,
                       rc, ndlp->nlp_DID, ndlp->nlp_flag);
 
-       ndlp->nlp_disc_refcnt--;
+       lpfc_nlp_put(ndlp);
 
-       /* Check to see if ndlp removal is deferred */
-       if ((ndlp->nlp_disc_refcnt == 0)
-           && (ndlp->nlp_flag & NLP_DELAY_REMOVE)) {
-               spin_lock_irq(phba->host->host_lock);
-               ndlp->nlp_flag &= ~NLP_DELAY_REMOVE;
-               spin_unlock_irq(phba->host->host_lock);
-               lpfc_nlp_remove(phba, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
-       if (rc == NLP_STE_FREED_NODE)
-               return NLP_STE_FREED_NODE;
        return rc;
 }
index c3e68e0d8f7445e426fa0ee28cc35ab5903c37cc..9a12d05e99e4d938460948186e8d0df9f7f9df5d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -146,6 +146,10 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
 
        spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
        list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+       if (lpfc_cmd) {
+               lpfc_cmd->seg_cnt = 0;
+               lpfc_cmd->nonsg_phys = 0;
+       }
        spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
        return  lpfc_cmd;
 }
@@ -288,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
 }
 
 static void
-lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
+lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
 {
        struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
        struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
        struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
        struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
-       uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
+       uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
        uint32_t resp_info = fcprsp->rspStatus2;
        uint32_t scsi_status = fcprsp->rspStatus3;
        uint32_t *lp;
@@ -355,6 +359,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
                                be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
                                fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
 
+               /*
+                * If there is an under run check if under run reported by
+                * storage array is same as the under run reported by HBA.
+                * If this is not same, there is a dropped frame.
+                */
+               if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
+                       fcpi_parm &&
+                       (cmnd->resid != fcpi_parm)) {
+                       lpfc_printf_log(phba, KERN_WARNING,
+                               LOG_FCP | LOG_FCP_ERROR,
+                               "%d:0735 FCP Read Check Error and Underrun "
+                               "Data: x%x x%x x%x x%x\n", phba->brd_no,
+                               be32_to_cpu(fcpcmd->fcpDl),
+                               cmnd->resid,
+                               fcpi_parm, cmnd->cmnd[0]);
+                       cmnd->resid = cmnd->request_bufflen;
+                       host_status = DID_ERROR;
+               }
                /*
                 * The cmnd->underflow is the minimum number of bytes that must
                 * be transfered for this command.  Provided a sense condition
@@ -435,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                switch (lpfc_cmd->status) {
                case IOSTAT_FCP_RSP_ERROR:
                        /* Call FCP RSP handler to determine result */
-                       lpfc_handle_fcp_err(lpfc_cmd);
+                       lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
                        break;
                case IOSTAT_NPORT_BSY:
                case IOSTAT_FABRIC_BSY:
@@ -466,10 +488,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 
        result = cmd->result;
        sdev = cmd->device;
+       lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
        cmd->scsi_done(cmd);
 
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
-               lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
                lpfc_release_scsi_buf(phba, lpfc_cmd);
                return;
        }
@@ -527,7 +549,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                }
        }
 
-       lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
        lpfc_release_scsi_buf(phba, lpfc_cmd);
 }
 
@@ -670,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
        return (1);
 }
 
+static void
+lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
+                       struct lpfc_iocbq *cmdiocbq,
+                       struct lpfc_iocbq *rspiocbq)
+{
+       struct lpfc_scsi_buf *lpfc_cmd =
+               (struct lpfc_scsi_buf *) cmdiocbq->context1;
+       if (lpfc_cmd)
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+       return;
+}
+
 static int
 lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
                    unsigned  tgt_id, unsigned int lun,
@@ -706,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
                                       &phba->sli.ring[phba->sli.fcp_ring],
                                       iocbq, iocbqrsp, lpfc_cmd->timeout);
        if (ret != IOCB_SUCCESS) {
+               if (ret == IOCB_TIMEDOUT)
+                       iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
                lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
-               ret = FAILED;
        } else {
                ret = SUCCESS;
                lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
@@ -974,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
 }
 
 static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
 {
        struct Scsi_Host *shost = cmnd->device->host;
        struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
@@ -984,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        struct lpfc_nodelist *pnode = rdata->pnode;
        uint32_t cmd_result = 0, cmd_status = 0;
        int ret = FAILED;
+       int iocb_status = IOCB_SUCCESS;
        int cnt, loopcnt;
 
        lpfc_block_error_handler(cmnd);
@@ -995,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
         */
        while ( 1 ) {
                if (!pnode)
-                       return FAILED;
+                       goto out;
 
                if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
                        spin_unlock_irq(phba->host->host_lock);
@@ -1013,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
                        }
                        pnode = rdata->pnode;
                        if (!pnode)
-                               return FAILED;
+                               goto out;
                }
                if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
                        break;
@@ -1028,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        lpfc_cmd->rdata = rdata;
 
        ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
-                                          FCP_LUN_RESET);
+                                          FCP_TARGET_RESET);
        if (!ret)
                goto out_free_scsi_buf;
 
@@ -1040,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
                goto out_free_scsi_buf;
 
        lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-                       "%d:0703 Issue LUN Reset to TGT %d LUN %d "
-                       "Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+                       "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
+                       "nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
                        cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
 
-       ret = lpfc_sli_issue_iocb_wait(phba,
+       iocb_status = lpfc_sli_issue_iocb_wait(phba,
                                       &phba->sli.ring[phba->sli.fcp_ring],
                                       iocbq, iocbqrsp, lpfc_cmd->timeout);
-       if (ret == IOCB_SUCCESS)
-               ret = SUCCESS;
 
+       if (iocb_status == IOCB_TIMEDOUT)
+               iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
+
+       if (iocb_status == IOCB_SUCCESS)
+               ret = SUCCESS;
+       else
+               ret = iocb_status;
 
        cmd_result = iocbqrsp->iocb.un.ulpWord[4];
        cmd_status = iocbqrsp->iocb.ulpStatus;
@@ -1087,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 
        if (cnt) {
                lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                       "%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
+                       "%d:0719 device reset I/O flush failure: cnt x%x\n",
                        phba->brd_no, cnt);
                ret = FAILED;
        }
 
 out_free_scsi_buf:
-       lpfc_release_scsi_buf(phba, lpfc_cmd);
-
+       if (iocb_status != IOCB_TIMEDOUT) {
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+       }
        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                       "%d:0713 SCSI layer issued LUN reset (%d, %d) "
-                       "Data: x%x x%x x%x\n",
-                       phba->brd_no, cmnd->device->id,cmnd->device->lun,
+                       "%d:0713 SCSI layer issued device reset (%d, %d) "
+                       "return x%x status x%x result x%x\n",
+                       phba->brd_no, cmnd->device->id, cmnd->device->lun,
                        ret, cmd_status, cmd_result);
 
 out:
@@ -1107,7 +1148,7 @@ out:
 }
 
 static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
 {
        struct Scsi_Host *shost = cmnd->device->host;
        struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
@@ -1134,10 +1175,12 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
         * fail, this routine returns failure to the midlayer.
         */
        for (i = 0; i < LPFC_MAX_TARGET; i++) {
-               /* Search the mapped list for this target ID */
+               /* Search for mapped node by target ID */
                match = 0;
-               list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
-                       if ((i == ndlp->nlp_sid) && ndlp->rport) {
+               list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+                       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
+                           i == ndlp->nlp_sid &&
+                           ndlp->rport) {
                                match = 1;
                                break;
                        }
@@ -1152,13 +1195,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
                                "%d:0700 Bus Reset on target %d failed\n",
                                phba->brd_no, i);
                        err_count++;
+                       break;
                }
        }
 
+       if (ret != IOCB_TIMEDOUT)
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+
        if (err_count == 0)
                ret = SUCCESS;
-
-       lpfc_release_scsi_buf(phba, lpfc_cmd);
+       else
+               ret = FAILED;
 
        /*
         * All outstanding txcmplq I/Os should have been aborted by
@@ -1299,11 +1346,13 @@ struct scsi_host_template lpfc_template = {
        .info                   = lpfc_info,
        .queuecommand           = lpfc_queuecommand,
        .eh_abort_handler       = lpfc_abort_handler,
-       .eh_device_reset_handler= lpfc_reset_lun_handler,
-       .eh_bus_reset_handler   = lpfc_reset_bus_handler,
+       .eh_device_reset_handler= lpfc_device_reset_handler,
+       .eh_bus_reset_handler   = lpfc_bus_reset_handler,
        .slave_alloc            = lpfc_slave_alloc,
        .slave_configure        = lpfc_slave_configure,
        .slave_destroy          = lpfc_slave_destroy,
+       .scan_finished          = lpfc_scan_finished,
+       .scan_start             = lpfc_scan_start,
        .this_id                = -1,
        .sg_tablesize           = LPFC_SG_SEG_CNT,
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
index 9fb6960a8adaca023b7faad67187f5c378c50e00..a1e721459e2b21a1734bff082c33e4f3c7df2bc7 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -528,6 +528,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
         * If pdone_q is empty, the driver thread gave up waiting and
         * continued running.
         */
+       pmboxq->mbox_flag |= LPFC_MBX_WAKE;
        pdone_q = (wait_queue_head_t *) pmboxq->context1;
        if (pdone_q)
                wake_up_interruptible(pdone_q);
@@ -538,11 +539,32 @@ void
 lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 {
        struct lpfc_dmabuf *mp;
+       uint16_t rpi;
+       int rc;
+
        mp = (struct lpfc_dmabuf *) (pmb->context1);
+
        if (mp) {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
        }
+
+       /*
+        * If a REG_LOGIN succeeded  after node is destroyed or node
+        * is in re-discovery driver need to cleanup the RPI.
+        */
+       if (!(phba->fc_flag & FC_UNLOADING) &&
+               (pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+               (!pmb->mb.mbxStatus)) {
+
+               rpi = pmb->mb.un.varWords[0];
+               lpfc_unreg_login(phba, rpi, pmb);
+               pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+               if (rc != MBX_NOT_FINISHED)
+                       return;
+       }
+
        mempool_free( pmb, phba->mbox_mem_pool);
        return;
 }
@@ -693,25 +715,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
                } else {
                        spin_unlock_irq(phba->host->host_lock);
                        /* Turn on IOCB processing */
-                       for (i = 0; i < phba->sli.num_rings; i++) {
+                       for (i = 0; i < phba->sli.num_rings; i++)
                                lpfc_sli_turn_on_ring(phba, i);
-                       }
-
-                       /* Free any lpfc_dmabuf's waiting for mbox cmd cmpls */
-                       while (!list_empty(&phba->freebufList)) {
-                               struct lpfc_dmabuf *mp;
-
-                               mp = NULL;
-                               list_remove_head((&phba->freebufList),
-                                                mp,
-                                                struct lpfc_dmabuf,
-                                                list);
-                               if (mp) {
-                                       lpfc_mbuf_free(phba, mp->virt,
-                                                      mp->phys);
-                                       kfree(mp);
-                               }
-                       }
                }
 
        } while (process_next);
@@ -833,6 +838,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
                         * All other are passed to the completion callback.
                         */
                        if (pring->ringno == LPFC_ELS_RING) {
+                               if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) {
+                                       cmdiocbp->iocb_flag &=
+                                               ~LPFC_DRIVER_ABORTED;
+                                       saveq->iocb.ulpStatus =
+                                               IOSTAT_LOCAL_REJECT;
+                                       saveq->iocb.un.ulpWord[4] =
+                                               IOERR_SLI_ABORTED;
+                               }
                                spin_unlock_irqrestore(phba->host->host_lock,
                                                       iflag);
                                (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
@@ -1464,8 +1477,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
 int
 lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
+       LIST_HEAD(completions);
        struct lpfc_iocbq *iocb, *next_iocb;
-       IOCB_t *icmd = NULL, *cmd = NULL;
+       IOCB_t *cmd = NULL;
        int errcnt;
 
        errcnt = 0;
@@ -1474,46 +1488,28 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
         * First do the txq.
         */
        spin_lock_irq(phba->host->host_lock);
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-               list_del_init(&iocb->list);
-               if (iocb->iocb_cmpl) {
-                       icmd = &iocb->iocb;
-                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       spin_unlock_irq(phba->host->host_lock);
-                       (iocb->iocb_cmpl) (phba, iocb, iocb);
-                       spin_lock_irq(phba->host->host_lock);
-               } else
-                       lpfc_sli_release_iocbq(phba, iocb);
-       }
+       list_splice_init(&pring->txq, &completions);
        pring->txq_cnt = 0;
-       INIT_LIST_HEAD(&(pring->txq));
 
        /* Next issue ABTS for everything on the txcmplq */
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
-               cmd = &iocb->iocb;
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
+               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
 
-               /*
-                * Imediate abort of IOCB, deque and call compl
-                */
+       spin_unlock_irq(phba->host->host_lock);
 
-               list_del_init(&iocb->list);
-               pring->txcmplq_cnt--;
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
+               list_del(&iocb->list);
 
                if (iocb->iocb_cmpl) {
                        cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
                        cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       spin_unlock_irq(phba->host->host_lock);
                        (iocb->iocb_cmpl) (phba, iocb, iocb);
-                       spin_lock_irq(phba->host->host_lock);
                } else
                        lpfc_sli_release_iocbq(phba, iocb);
        }
 
-       INIT_LIST_HEAD(&pring->txcmplq);
-       pring->txcmplq_cnt = 0;
-       spin_unlock_irq(phba->host->host_lock);
-
        return errcnt;
 }
 
@@ -1588,6 +1584,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
        hc_copy = readl(phba->HCregaddr);
        writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
+       phba->fc_flag |= FC_IGNORE_ERATT;
 
        if (readl(phba->HAregaddr) & HA_ERATT) {
                /* Clear Chip error bit */
@@ -1630,6 +1627,7 @@ clear_errat:
        }
 
 restore_hc:
+       phba->fc_flag &= ~FC_IGNORE_ERATT;
        writel(hc_copy, phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
 }
@@ -1665,6 +1663,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
        status &= ~HC_ERINT_ENA;
        writel(status, phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
+       phba->fc_flag |= FC_IGNORE_ERATT;
        spin_unlock_irq(phba->host->host_lock);
 
        lpfc_kill_board(phba, pmb);
@@ -1674,6 +1673,9 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
        if (retval != MBX_SUCCESS) {
                if (retval != MBX_BUSY)
                        mempool_free(pmb, phba->mbox_mem_pool);
+               spin_lock_irq(phba->host->host_lock);
+               phba->fc_flag &= ~FC_IGNORE_ERATT;
+               spin_unlock_irq(phba->host->host_lock);
                return 1;
        }
 
@@ -1700,6 +1702,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
        }
        spin_lock_irq(phba->host->host_lock);
        psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+       phba->fc_flag &= ~FC_IGNORE_ERATT;
        spin_unlock_irq(phba->host->host_lock);
 
        psli->mbox_active = NULL;
@@ -1985,42 +1988,6 @@ lpfc_sli_hba_setup_exit:
        return rc;
 }
 
-static void
-lpfc_mbox_abort(struct lpfc_hba * phba)
-{
-       LPFC_MBOXQ_t *pmbox;
-       MAILBOX_t *mb;
-
-       if (phba->sli.mbox_active) {
-               del_timer_sync(&phba->sli.mbox_tmo);
-               phba->work_hba_events &= ~WORKER_MBOX_TMO;
-               pmbox = phba->sli.mbox_active;
-               mb = &pmbox->mb;
-               phba->sli.mbox_active = NULL;
-               if (pmbox->mbox_cmpl) {
-                       mb->mbxStatus = MBX_NOT_FINISHED;
-                       (pmbox->mbox_cmpl) (phba, pmbox);
-               }
-               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-       }
-
-       /* Abort all the non active mailbox commands. */
-       spin_lock_irq(phba->host->host_lock);
-       pmbox = lpfc_mbox_get(phba);
-       while (pmbox) {
-               mb = &pmbox->mb;
-               if (pmbox->mbox_cmpl) {
-                       mb->mbxStatus = MBX_NOT_FINISHED;
-                       spin_unlock_irq(phba->host->host_lock);
-                       (pmbox->mbox_cmpl) (phba, pmbox);
-                       spin_lock_irq(phba->host->host_lock);
-               }
-               pmbox = lpfc_mbox_get(phba);
-       }
-       spin_unlock_irq(phba->host->host_lock);
-       return;
-}
-
 /*! lpfc_mbox_timeout
  *
  * \pre
@@ -2055,6 +2022,8 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
 {
        LPFC_MBOXQ_t *pmbox;
        MAILBOX_t *mb;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring;
 
        spin_lock_irq(phba->host->host_lock);
        if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
@@ -2062,8 +2031,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
                return;
        }
 
-       phba->work_hba_events &= ~WORKER_MBOX_TMO;
-
        pmbox = phba->sli.mbox_active;
        mb = &pmbox->mb;
 
@@ -2078,17 +2045,32 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
                phba->sli.sli_flag,
                phba->sli.mbox_active);
 
-       phba->sli.mbox_active = NULL;
-       if (pmbox->mbox_cmpl) {
-               mb->mbxStatus = MBX_NOT_FINISHED;
-               spin_unlock_irq(phba->host->host_lock);
-               (pmbox->mbox_cmpl) (phba, pmbox);
-               spin_lock_irq(phba->host->host_lock);
-       }
-       phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-
+       /* Setting state unknown so lpfc_sli_abort_iocb_ring
+        * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
+        * it to fail all oustanding SCSI IO.
+        */
+       phba->hba_state = LPFC_STATE_UNKNOWN;
+       phba->work_hba_events &= ~WORKER_MBOX_TMO;
+       phba->fc_flag |= FC_ESTABLISH_LINK;
+       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
        spin_unlock_irq(phba->host->host_lock);
-       lpfc_mbox_abort(phba);
+
+       pring = &psli->ring[psli->fcp_ring];
+       lpfc_sli_abort_iocb_ring(phba, pring);
+
+       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+                       "%d:0316 Resetting board due to mailbox timeout\n",
+                       phba->brd_no);
+       /*
+        * lpfc_offline calls lpfc_sli_hba_down which will clean up
+        * on oustanding mailbox commands.
+        */
+       lpfc_offline_prep(phba);
+       lpfc_offline(phba);
+       lpfc_sli_brdrestart(phba);
+       if (lpfc_online(phba) == 0)             /* Initialize the HBA */
+               mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+       lpfc_unblock_mgmt_io(phba);
        return;
 }
 
@@ -2320,9 +2302,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
                        spin_unlock_irqrestore(phba->host->host_lock,
                                               drvr_flag);
 
-                       /* Can be in interrupt context, do not sleep */
-                       /* (or might be called with interrupts disabled) */
-                       mdelay(1);
+                       msleep(1);
 
                        spin_lock_irqsave(phba->host->host_lock, drvr_flag);
 
@@ -2430,7 +2410,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 
        if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
                /*
-                * Only CREATE_XRI, CLOSE_XRI, ABORT_XRI, and QUE_RING_BUF
+                * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
                 * can be issued if the link is not up.
                 */
                switch (piocb->iocb.ulpCommand) {
@@ -2444,6 +2424,8 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                                piocb->iocb_cmpl = NULL;
                        /*FALLTHROUGH*/
                case CMD_CREATE_XRI_CR:
+               case CMD_CLOSE_XRI_CN:
+               case CMD_CLOSE_XRI_CX:
                        break;
                default:
                        goto iocb_busy;
@@ -2637,11 +2619,12 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
 int
 lpfc_sli_hba_down(struct lpfc_hba * phba)
 {
+       LIST_HEAD(completions);
        struct lpfc_sli *psli;
        struct lpfc_sli_ring *pring;
        LPFC_MBOXQ_t *pmb;
-       struct lpfc_iocbq *iocb, *next_iocb;
-       IOCB_t *icmd = NULL;
+       struct lpfc_iocbq *iocb;
+       IOCB_t *cmd = NULL;
        int i;
        unsigned long flags = 0;
 
@@ -2649,7 +2632,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
        lpfc_hba_down_prep(phba);
 
        spin_lock_irqsave(phba->host->host_lock, flags);
-
        for (i = 0; i < psli->num_rings; i++) {
                pring = &psli->ring[i];
                pring->flag |= LPFC_DEFERRED_RING_EVENT;
@@ -2658,28 +2640,25 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
                 * Error everything on the txq since these iocbs have not been
                 * given to the FW yet.
                 */
+               list_splice_init(&pring->txq, &completions);
                pring->txq_cnt = 0;
 
-               list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-                       list_del_init(&iocb->list);
-                       if (iocb->iocb_cmpl) {
-                               icmd = &iocb->iocb;
-                               icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                               icmd->un.ulpWord[4] = IOERR_SLI_DOWN;
-                               spin_unlock_irqrestore(phba->host->host_lock,
-                                                      flags);
-                               (iocb->iocb_cmpl) (phba, iocb, iocb);
-                               spin_lock_irqsave(phba->host->host_lock, flags);
-                       } else
-                               lpfc_sli_release_iocbq(phba, iocb);
-               }
+       }
+       spin_unlock_irqrestore(phba->host->host_lock, flags);
 
-               INIT_LIST_HEAD(&(pring->txq));
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
+               list_del(&iocb->list);
 
+               if (iocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+               } else
+                       lpfc_sli_release_iocbq(phba, iocb);
        }
 
-       spin_unlock_irqrestore(phba->host->host_lock, flags);
-
        /* Return any active mbox cmds */
        del_timer_sync(&psli->mbox_tmo);
        spin_lock_irqsave(phba->host->host_lock, flags);
@@ -2768,85 +2747,138 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 }
 
 static void
-lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-                          struct lpfc_iocbq * rspiocb)
+lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
+                       struct lpfc_iocbq * rspiocb)
 {
-       struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
-       /* Free the resources associated with the ELS_REQUEST64 IOCB the driver
-        * just aborted.
-        * In this case, context2  = cmd,  context2->next = rsp, context3 = bpl
-        */
-       if (cmdiocb->context2) {
-               buf_ptr1 = (struct lpfc_dmabuf *) cmdiocb->context2;
-
-               /* Free the response IOCB before completing the abort
-                  command.  */
-               buf_ptr = NULL;
-               list_remove_head((&buf_ptr1->list), buf_ptr,
-                                struct lpfc_dmabuf, list);
-               if (buf_ptr) {
-                       lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-                       kfree(buf_ptr);
-               }
-               lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
-               kfree(buf_ptr1);
-       }
+       IOCB_t *irsp;
+       uint16_t abort_iotag, abort_context;
+       struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+
+       abort_iocb = NULL;
+       irsp = &rspiocb->iocb;
+
+       spin_lock_irq(phba->host->host_lock);
 
-       if (cmdiocb->context3) {
-               buf_ptr = (struct lpfc_dmabuf *) cmdiocb->context3;
-               lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-               kfree(buf_ptr);
+       if (irsp->ulpStatus) {
+               abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
+               abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
+
+               if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
+                       abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
+
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "%d:0327 Cannot abort els iocb %p"
+                               " with tag %x context %x\n",
+                               phba->brd_no, abort_iocb,
+                               abort_iotag, abort_context);
+
+               /*
+                * make sure we have the right iocbq before taking it
+                * off the txcmplq and try to call completion routine.
+                */
+               if (abort_iocb &&
+                   abort_iocb->iocb.ulpContext == abort_context &&
+                   abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
+                       list_del(&abort_iocb->list);
+                       pring->txcmplq_cnt--;
+
+                       rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
+                       if (rsp_ab_iocb == NULL)
+                               lpfc_sli_release_iocbq(phba, abort_iocb);
+                       else {
+                               abort_iocb->iocb_flag &=
+                                       ~LPFC_DRIVER_ABORTED;
+                               rsp_ab_iocb->iocb.ulpStatus =
+                                       IOSTAT_LOCAL_REJECT;
+                               rsp_ab_iocb->iocb.un.ulpWord[4] =
+                                       IOERR_SLI_ABORTED;
+                               spin_unlock_irq(phba->host->host_lock);
+                               (abort_iocb->iocb_cmpl)
+                                       (phba, abort_iocb, rsp_ab_iocb);
+                               spin_lock_irq(phba->host->host_lock);
+                               lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
+                       }
+               }
        }
 
        lpfc_sli_release_iocbq(phba, cmdiocb);
+       spin_unlock_irq(phba->host->host_lock);
        return;
 }
 
 int
-lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
-                            struct lpfc_sli_ring * pring,
-                            struct lpfc_iocbq * cmdiocb)
+lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
+                          struct lpfc_sli_ring * pring,
+                          struct lpfc_iocbq * cmdiocb)
 {
        struct lpfc_iocbq *abtsiocbp;
        IOCB_t *icmd = NULL;
        IOCB_t *iabt = NULL;
+       int retval = IOCB_ERROR;
+
+       /* There are certain command types we don't want
+        * to abort.
+        */
+       icmd = &cmdiocb->iocb;
+       if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
+           (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
+               return 0;
+
+       /* If we're unloading, interrupts are disabled so we
+        * need to cleanup the iocb here.
+        */
+       if (phba->fc_flag & FC_UNLOADING)
+               goto abort_iotag_exit;
 
        /* issue ABTS for this IOCB based on iotag */
        abtsiocbp = lpfc_sli_get_iocbq(phba);
        if (abtsiocbp == NULL)
                return 0;
 
+       /* This signals the response to set the correct status
+        * before calling the completion handler.
+        */
+       cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
+
        iabt = &abtsiocbp->iocb;
-       icmd = &cmdiocb->iocb;
-       switch (icmd->ulpCommand) {
-       case CMD_ELS_REQUEST64_CR:
-               /* Even though we abort the ELS command, the firmware may access
-                * the BPL or other resources before it processes our
-                * ABORT_MXRI64. Thus we must delay reusing the cmdiocb
-                * resources till the actual abort request completes.
-                */
-               abtsiocbp->context1 = (void *)((unsigned long)icmd->ulpCommand);
-               abtsiocbp->context2 = cmdiocb->context2;
-               abtsiocbp->context3 = cmdiocb->context3;
-               cmdiocb->context2 = NULL;
-               cmdiocb->context3 = NULL;
-               abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl;
-               break;
-       default:
-               lpfc_sli_release_iocbq(phba, abtsiocbp);
-               return 0;
-       }
+       iabt->un.acxri.abortType = ABORT_TYPE_ABTS;
+       iabt->un.acxri.abortContextTag = icmd->ulpContext;
+       iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
+       iabt->ulpLe = 1;
+       iabt->ulpClass = icmd->ulpClass;
 
-       iabt->un.amxri.abortType = ABORT_TYPE_ABTS;
-       iabt->un.amxri.iotag32 = icmd->un.elsreq64.bdl.ulpIoTag32;
+       if (phba->hba_state >= LPFC_LINK_UP)
+               iabt->ulpCommand = CMD_ABORT_XRI_CN;
+       else
+               iabt->ulpCommand = CMD_CLOSE_XRI_CN;
 
-       iabt->ulpLe = 1;
-       iabt->ulpClass = CLASS3;
-       iabt->ulpCommand = CMD_ABORT_MXRI64_CN;
+       abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
 
-       if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) {
-               lpfc_sli_release_iocbq(phba, abtsiocbp);
-               return 0;
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "%d:0339 Abort xri x%x, original iotag x%x, abort "
+                       "cmd iotag x%x\n",
+                       phba->brd_no, iabt->un.acxri.abortContextTag,
+                       iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
+       retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
+
+abort_iotag_exit:
+
+       /* If we could not issue an abort dequeue the iocb and handle
+        * the completion here.
+        */
+       if (retval == IOCB_ERROR) {
+               list_del(&cmdiocb->list);
+               pring->txcmplq_cnt--;
+
+               if (cmdiocb->iocb_cmpl) {
+                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       spin_unlock_irq(phba->host->host_lock);
+                       (cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
+                       spin_lock_irq(phba->host->host_lock);
+               } else
+                       lpfc_sli_release_iocbq(phba, cmdiocb);
        }
 
        return 1;
@@ -2918,9 +2950,11 @@ void
 lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
                           struct lpfc_iocbq * rspiocb)
 {
-       spin_lock_irq(phba->host->host_lock);
+       unsigned long iflags;
+
+       spin_lock_irqsave(phba->host->host_lock, iflags);
        lpfc_sli_release_iocbq(phba, cmdiocb);
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irqrestore(phba->host->host_lock, iflags);
        return;
 }
 
@@ -3043,22 +3077,22 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
                                timeout_req);
                spin_lock_irq(phba->host->host_lock);
 
-               if (timeleft == 0) {
+               if (piocb->iocb_flag & LPFC_IO_WAKE) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                                       "%d:0331 IOCB wake signaled\n",
+                                       phba->brd_no);
+               } else if (timeleft == 0) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                        "%d:0338 IOCB wait timeout error - no "
                                        "wake response Data x%x\n",
                                        phba->brd_no, timeout);
                        retval = IOCB_TIMEDOUT;
-               } else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
+               } else {
                        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                        "%d:0330 IOCB wake NOT set, "
                                        "Data x%x x%lx\n", phba->brd_no,
                                        timeout, (timeleft / jiffies));
                        retval = IOCB_TIMEDOUT;
-               } else {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                                       "%d:0331 IOCB wake signaled\n",
-                                       phba->brd_no);
                }
        } else {
                lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -3087,8 +3121,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
                         uint32_t timeout)
 {
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
-       DECLARE_WAITQUEUE(wq_entry, current);
-       uint32_t timeleft = 0;
        int retval;
 
        /* The caller must leave context1 empty. */
@@ -3101,27 +3133,25 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
        /* setup context field to pass wait_queue pointer to wake function  */
        pmboxq->context1 = &done_q;
 
-       /* start to sleep before we wait, to avoid races */
-       set_current_state(TASK_INTERRUPTIBLE);
-       add_wait_queue(&done_q, &wq_entry);
-
        /* now issue the command */
        retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
 
        if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
-               timeleft = schedule_timeout(timeout * HZ);
+               wait_event_interruptible_timeout(done_q,
+                               pmboxq->mbox_flag & LPFC_MBX_WAKE,
+                               timeout * HZ);
+
                pmboxq->context1 = NULL;
-               /* if schedule_timeout returns 0, we timed out and were not
-                  woken up */
-               if ((timeleft == 0) || signal_pending(current))
-                       retval = MBX_TIMEOUT;
-               else
+               /*
+                * if LPFC_MBX_WAKE flag is set the mailbox is completed
+                * else do not free the resources.
+                */
+               if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
                        retval = MBX_SUCCESS;
+               else
+                       retval = MBX_TIMEOUT;
        }
 
-
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&done_q, &wq_entry);
        return retval;
 }
 
@@ -3184,6 +3214,11 @@ lpfc_intr_handler(int irq, void *dev_id)
         */
        spin_lock(phba->host->host_lock);
        ha_copy = readl(phba->HAregaddr);
+       /* If somebody is waiting to handle an eratt don't process it
+        * here.  The brdkill function will do this.
+        */
+       if (phba->fc_flag & FC_IGNORE_ERATT)
+               ha_copy &= ~HA_ERATT;
        writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
        readl(phba->HAregaddr); /* flush */
        spin_unlock(phba->host->host_lock);
index a43549959dc7bb45bd9ebabcd8121afdcf201a00..41c38d324ab005ce43efd90f27d7be2fd93c5db2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -39,9 +39,10 @@ struct lpfc_iocbq {
        IOCB_t iocb;            /* IOCB cmd */
        uint8_t retry;          /* retry counter for IOCB cmd - if needed */
        uint8_t iocb_flag;
-#define LPFC_IO_LIBDFC 1       /* libdfc iocb */
-#define LPFC_IO_WAKE   2       /* High Priority Queue signal flag */
-#define LPFC_IO_FCP    4       /* FCP command -- iocbq in scsi_buf */
+#define LPFC_IO_LIBDFC         1       /* libdfc iocb */
+#define LPFC_IO_WAKE           2       /* High Priority Queue signal flag */
+#define LPFC_IO_FCP            4       /* FCP command -- iocbq in scsi_buf */
+#define LPFC_DRIVER_ABORTED    8       /* driver aborted this request */
 
        uint8_t abort_count;
        uint8_t rsvd2;
@@ -67,6 +68,8 @@ struct lpfc_iocbq {
 #define IOCB_ERROR          2
 #define IOCB_TIMEDOUT       3
 
+#define LPFC_MBX_WAKE  1
+
 typedef struct lpfcMboxq {
        /* MBOXQs are used in single linked lists */
        struct list_head list;  /* ptr to next mailbox command */
@@ -75,6 +78,7 @@ typedef struct lpfcMboxq {
        void *context2;         /* caller context information */
 
        void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
+       uint8_t mbox_flag;
 
 } LPFC_MBOXQ_t;
 
index a61ef3d1e7f1b08090403de95e4547246c65420f..92a9107019d2c6de3b87a5ec7c899df256d6c063 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.11"
+#define LPFC_DRIVER_VERSION "8.1.12"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
 #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
                LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex.  All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2007 Emulex.  All rights reserved."
 
 #define DFC_API_VERSION "0.0.0"
index 753d88306cd16765b03984b636f5b6142a9cf43f..5806ede120a42182cb14e1efe01d375eb49a1f6b 100644 (file)
@@ -471,7 +471,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
                goto out_free;
        }
 
-               clkprop = get_property(node, "clock-frequency", &proplen);
+       clkprop = of_get_property(node, "clock-frequency", &proplen);
                if (clkprop == NULL || proplen != sizeof(int)) {
                        printk(KERN_ERR "%s: can't get clock frequency, "
                               "assuming 25MHz\n", node->full_name);
index 7fc6e06ea7e19e2780f8c1fd9b608115ab71f0a9..3cce75d70263a4fd5b315e53241548f3b23a8012 100644 (file)
@@ -1754,7 +1754,8 @@ __mega_busywait_mbox (adapter_t *adapter)
        for (counter = 0; counter < 10000; counter++) {
                if (!mbox->m_in.busy)
                        return 0;
-               udelay(100); yield();
+               udelay(100);
+               cond_resched();
        }
        return -1;              /* give up after 1 second */
 }
@@ -3177,7 +3178,10 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
 
        return len;
 }
-
+#else
+static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent)
+{
+}
 #endif
 
 
@@ -4342,7 +4346,7 @@ mega_support_cluster(adapter_t *adapter)
        return 0;
 }
 
-
+#ifdef CONFIG_PROC_FS
 /**
  * mega_adapinq()
  * @adapter - pointer to our soft state
@@ -4447,7 +4451,7 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
 
        return rval;
 }
-
+#endif
 
 /**
  * mega_internal_command()
@@ -4965,7 +4969,6 @@ megaraid_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
        adapter_t *adapter = (adapter_t *)host->hostdata;
-       char    buf[12] = { 0 };
 
        scsi_remove_host(host);
 
@@ -5011,8 +5014,11 @@ megaraid_remove_one(struct pci_dev *pdev)
                remove_proc_entry("raiddrives-30-39",
                                adapter->controller_proc_dir_entry);
 #endif
-               sprintf(buf, "hba%d", adapter->host->host_no);
-               remove_proc_entry(buf, mega_proc_dir_entry);
+               {
+                       char    buf[12] = { 0 };
+                       sprintf(buf, "hba%d", adapter->host->host_no);
+                       remove_proc_entry(buf, mega_proc_dir_entry);
+               }
        }
 #endif
 
index c6e74643abe29be7f7d52ad29b7fd8634c548c4d..ee70bd4ae4badc0f2f7a82eb0a523d5702c796f4 100644 (file)
@@ -1002,7 +1002,6 @@ static int megaraid_reset(Scsi_Cmnd *);
 static int megaraid_abort_and_reset(adapter_t *, Scsi_Cmnd *, int);
 static int megaraid_biosparam(struct scsi_device *, struct block_device *,
                sector_t, int []);
-static int mega_print_inquiry(char *, char *);
 
 static int mega_build_sglist (adapter_t *adapter, scb_t *scb,
                              u32 *buffer, u32 *length);
@@ -1024,6 +1023,7 @@ static int mega_init_scb (adapter_t *);
 static int mega_is_bios_enabled (adapter_t *);
 
 #ifdef CONFIG_PROC_FS
+static int mega_print_inquiry(char *, char *);
 static void mega_create_proc_entry(int, struct proc_dir_entry *);
 static int proc_read_config(char *, char **, off_t, int, int *, void *);
 static int proc_read_stat(char *, char **, off_t, int, int *, void *);
@@ -1040,10 +1040,10 @@ static int proc_rdrv_20(char *, char **, off_t, int, int *, void *);
 static int proc_rdrv_30(char *, char **, off_t, int, int *, void *);
 static int proc_rdrv_40(char *, char **, off_t, int, int *, void *);
 static int proc_rdrv(adapter_t *, char *, int, int);
-#endif
 
 static int mega_adapinq(adapter_t *, dma_addr_t);
 static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
+#endif
 
 static int mega_support_ext_cdb(adapter_t *);
 static mega_passthru* mega_prepare_passthru(adapter_t *, scb_t *,
index f33a678f0897d749788ec7e2ed35e742019f1c18..e075a52ac104e06fcf94bf1ca35a816d4bfdf079 100644 (file)
@@ -60,7 +60,7 @@ EXPORT_SYMBOL(mraid_mm_unregister_adp);
 EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
 
 static int majorno;
-static uint32_t drvr_ver       = 0x02200206;
+static uint32_t drvr_ver       = 0x02200207;
 
 static int adapters_count_g;
 static struct list_head adapters_list_g;
index 1fd3c7590d316bf93207a475dc0e32f0d009c3e2..e64d1a19d8d7e0f771fb235cc11bb7dbcdb42359 100644 (file)
@@ -185,7 +185,7 @@ struct mesh_state {
  * Driver is too messy, we need a few prototypes...
  */
 static void mesh_done(struct mesh_state *ms, int start_next);
-static void mesh_interrupt(int irq, void *dev_id);
+static void mesh_interrupt(struct mesh_state *ms);
 static void cmd_complete(struct mesh_state *ms);
 static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd);
 static void halt_dma(struct mesh_state *ms);
@@ -466,7 +466,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd)
                                dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x",
                                     MKWORD(mr->interrupt, mr->exception,
                                            mr->error, mr->fifo_count));
-                               mesh_interrupt(0, (void *)ms);
+                               mesh_interrupt(ms);
                                if (ms->phase != arbitrating)
                                        return;
                        }
@@ -504,7 +504,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd)
                dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x",
                     MKWORD(mr->interrupt, mr->exception,
                            mr->error, mr->fifo_count));
-               mesh_interrupt(0, (void *)ms);
+               mesh_interrupt(ms);
                if (ms->phase != arbitrating)
                        return;
                dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x",
@@ -1018,10 +1018,11 @@ static void handle_reset(struct mesh_state *ms)
 static irqreturn_t do_mesh_interrupt(int irq, void *dev_id)
 {
        unsigned long flags;
-       struct Scsi_Host *dev = ((struct mesh_state *)dev_id)->host;
+       struct mesh_state *ms = dev_id;
+       struct Scsi_Host *dev = ms->host;
        
        spin_lock_irqsave(dev->host_lock, flags);
-       mesh_interrupt(irq, dev_id);
+       mesh_interrupt(ms);
        spin_unlock_irqrestore(dev->host_lock, flags);
        return IRQ_HANDLED;
 }
@@ -1661,9 +1662,8 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
  * handler (do_mesh_interrupt) or by other functions in
  * exceptional circumstances
  */
-static void mesh_interrupt(int irq, void *dev_id)
+static void mesh_interrupt(struct mesh_state *ms)
 {
-       struct mesh_state *ms = (struct mesh_state *) dev_id;
        volatile struct mesh_regs __iomem *mr = ms->mesh;
        int intr;
 
@@ -1947,7 +1947,7 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
                ms->tgts[tgt].current_req = NULL;
                }
 
-       if ((cfp = get_property(mesh, "clock-frequency", NULL)))
+       if ((cfp = of_get_property(mesh, "clock-frequency", NULL)))
                        ms->clk_freq = *cfp;
        else {
                        printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n");
index 6777e8a69153a9a7c6eabc671ac4ea8a7ae2d642..54d8bdf86852b7541542298b05ce1f20b0c55c9e 100644 (file)
@@ -4293,7 +4293,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->devnum = devnum;    /* specifies microcode load address */
 
 #ifdef QLA_64BIT_PTR
-       if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
+       if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
                if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "scsi(%li): Unable to set a "
                               "suitable DMA mask - aborting\n", ha->host_no);
index 3e296ab845b653a454efc4f05a70f444eed4a67d..2a45aec4ff29e6499a36456d24f6f496caf9ff4a 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef CONFIG_SPARC
 #include <asm/prom.h>
-#include <asm/pbm.h>
 #endif
 
 /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
@@ -130,18 +129,17 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 int
 qla2100_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t w, mwi;
+       int ret;
+       uint16_t w;
        uint32_t d;
        unsigned long flags;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
        pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        /* Reset expansion ROM address decode enable */
@@ -166,22 +164,22 @@ qla2100_pci_config(scsi_qla_host_t *ha)
 int
 qla2300_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t        w, mwi;
+       int             ret;
+       uint16_t        w;
        uint32_t        d;
        unsigned long   flags = 0;
        uint32_t        cnt;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
 
        if (IS_QLA2322(ha) || IS_QLA6322(ha))
                w &= ~PCI_COMMAND_INTX_DISABLE;
+       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        /*
         * If this is a 2300 card and not 2312, reset the
@@ -210,7 +208,7 @@ qla2300_pci_config(scsi_qla_host_t *ha)
                ha->fb_rev = RD_FB_CMD_REG(ha, reg);
 
                if (ha->fb_rev == FPM_2300)
-                       w &= ~PCI_COMMAND_INVALIDATE;
+                       pci_clear_mwi(ha->pdev);
 
                /* Deselect FPM registers. */
                WRT_REG_WORD(&reg->ctrl_status, 0x0);
@@ -227,7 +225,6 @@ qla2300_pci_config(scsi_qla_host_t *ha)
 
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
        }
-       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
 
@@ -253,19 +250,18 @@ qla2300_pci_config(scsi_qla_host_t *ha)
 int
 qla24xx_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t w, mwi;
+       int ret;
+       uint16_t w;
        uint32_t d;
        unsigned long flags = 0;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        int pcix_cmd_reg, pcie_dctl_reg;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
        w &= ~PCI_COMMAND_INTX_DISABLE;
        pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
@@ -1400,9 +1396,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
 {
 #ifdef CONFIG_SPARC
        struct pci_dev *pdev = ha->pdev;
-       struct pcidev_cookie *pcp = pdev->sysdata;
-       struct device_node *dp = pcp->prom_node;
-       u8 *val;
+       struct device_node *dp = pci_device_to_OF_node(pdev);
+       const u8 *val;
        int len;
 
        val = of_get_property(dp, "port-wwn", &len);
@@ -3373,9 +3368,8 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *n
 {
 #ifdef CONFIG_SPARC
        struct pci_dev *pdev = ha->pdev;
-       struct pcidev_cookie *pcp = pdev->sysdata;
-       struct device_node *dp = pcp->prom_node;
-       u8 *val;
+       struct device_node *dp = pci_device_to_OF_node(pdev);
+       const u8 *val;
        int len;
 
        val = of_get_property(dp, "port-wwn", &len);
@@ -3931,6 +3925,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
 
        if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
                return;
+       if (!ha->fw_major_version)
+               return;
 
        ret = qla2x00_stop_firmware(ha);
        for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) {
index d4885616cd39c19077e72b2f083f563ec5cb2ad9..ca463469063d56358e2a1c91235f824175e2e738 100644 (file)
@@ -1726,6 +1726,17 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
        qla_printk(KERN_WARNING, ha,
            "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
 skip_msix:
+
+       if (!IS_QLA24XX(ha))
+               goto skip_msi;
+
+       ret = pci_enable_msi(ha->pdev);
+       if (!ret) {
+               DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
+               ha->flags.msi_enabled = 1;
+       }
+skip_msi:
+
        ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
            IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
        if (!ret) {
@@ -1746,6 +1757,8 @@ qla2x00_free_irqs(scsi_qla_host_t *ha)
 
        if (ha->flags.msix_enabled)
                qla24xx_disable_msix(ha);
-       else if (ha->flags.inta_enabled)
+       else if (ha->flags.inta_enabled) {
                free_irq(ha->host->irq, ha);
+               pci_disable_msi(ha->pdev);
+       }
 }
index b78919a318e2b2ee87dc9170c676e2f64de2b6a1..dd076da86a465d668d6b251512492176a65e81be 100644 (file)
@@ -36,7 +36,7 @@ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xlogintimeout,
                "Login timeout value in seconds.");
 
-int qlport_down_retry = 30;
+int qlport_down_retry;
 module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(qlport_down_retry,
                "Maximum number of command retries to a port that returns "
@@ -1577,9 +1577,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                goto probe_failed;
        }
 
-       if (qla2x00_initialize_adapter(ha) &&
-           !(ha->device_flags & DFLG_NO_CABLE)) {
-
+       if (qla2x00_initialize_adapter(ha)) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to initialize adapter\n");
 
index dc85495c337f856ecb220abd63166717308df227..c375a4efbc71b5cbe9372787db0bd9a14498e4b1 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k6"
+#define QLA2XXX_VERSION      "8.01.07-k7"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   1
index 7b4e077a39c18c770bbd42a80c7696ea83066e8e..6437d024b0dd725b84a58d097be601a154df6917 100644 (file)
@@ -8,6 +8,8 @@
 #include "ql4_def.h"
 #include <scsi/scsi_dbg.h>
 
+#if 0
+
 static void qla4xxx_print_srb_info(struct srb * srb)
 {
        printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
@@ -195,3 +197,5 @@ void qla4xxx_dump_buffer(void *b, uint32_t size)
        if (cnt % 16)
                printk(KERN_DEBUG "\n");
 }
+
+#endif  /*  0  */
index e021eb5db2b2c6c7eb858c2092ce7c56903a47fb..5b00cb04e7c07d82b946e7426d0e968348b735a0 100644 (file)
@@ -43,8 +43,6 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
                            uint16_t *tcp_source_port_num,
                            uint16_t *connection_id);
 
-struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha,
-                                    uint32_t fw_ddb_index);
 int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
                          dma_addr_t fw_ddb_entry_dma);
 
@@ -55,18 +53,11 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha);
 struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
 int qla4xxx_add_sess(struct ddb_entry *);
 void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
-int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
-                                  uint16_t fw_ddb_index,
-                                  uint16_t connection_id,
-                                  uint16_t option);
-int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
-                                uint16_t fw_ddb_index);
 int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha);
 int qla4xxx_get_fw_version(struct scsi_qla_host * ha);
 void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
                                       uint32_t intr_status);
 int qla4xxx_init_rings(struct scsi_qla_host * ha);
-void qla4xxx_dump_buffer(void *b, uint32_t size);
 struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
 void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
 int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
index b907b06d72ab4b30bd8541fa6fc1a4955b251284..6365df26861271a711d31d957b1bd9b1f52b7489 100644 (file)
@@ -7,9 +7,8 @@
 
 #include "ql4_def.h"
 
-/*
- * QLogic ISP4xxx Hardware Support Function Prototypes.
- */
+static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
+                                           uint32_t fw_ddb_index);
 
 static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
 {
@@ -48,7 +47,8 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
  * This routine deallocates and unlinks the specified ddb_entry from the
  * adapter's
  **/
-void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry)
+static void qla4xxx_free_ddb(struct scsi_qla_host *ha,
+                            struct ddb_entry *ddb_entry)
 {
        /* Remove device entry from list */
        list_del_init(&ddb_entry->list);
@@ -370,9 +370,9 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
  * must be initialized prior to        calling this routine
  *
  **/
-int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
-                            struct ddb_entry *ddb_entry,
-                            uint32_t fw_ddb_index)
+static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
+                                   struct ddb_entry *ddb_entry,
+                                   uint32_t fw_ddb_index)
 {
        struct dev_db_entry *fw_ddb_entry = NULL;
        dma_addr_t fw_ddb_entry_dma;
@@ -450,8 +450,8 @@ int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
  * This routine allocates a ddb_entry, ititializes some values, and
  * inserts it into the ddb list.
  **/
-struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
-                                    uint32_t fw_ddb_index)
+static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
+                                           uint32_t fw_ddb_index)
 {
        struct ddb_entry *ddb_entry;
 
index d41ce380eedcbd298185a15db290cb15c946b00a..a216a1781afbbc92a179595ad45893ae9f376903 100644 (file)
@@ -19,8 +19,8 @@
  *     - advances the request_in pointer
  *     - checks for queue full
  **/
-int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
-                       struct queue_entry **queue_entry)
+static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
+                              struct queue_entry **queue_entry)
 {
        uint16_t request_in;
        uint8_t status = QLA_SUCCESS;
@@ -62,8 +62,8 @@ int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
  *
  * This routine issues a marker IOCB.
  **/
-int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
-                            struct ddb_entry *ddb_entry, int lun)
+static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+                                   struct ddb_entry *ddb_entry, int lun)
 {
        struct marker_entry *marker_entry;
        unsigned long flags = 0;
@@ -96,7 +96,7 @@ exit_send_marker:
        return status;
 }
 
-struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
+static struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
        struct scsi_qla_host *ha)
 {
        struct continuation_t1_entry *cont_entry;
@@ -120,7 +120,7 @@ struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
        return cont_entry;
 }
 
-uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
+static uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
 {
        uint16_t iocbs;
 
@@ -133,9 +133,9 @@ uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
        return iocbs;
 }
 
-void qla4xxx_build_scsi_iocbs(struct srb *srb,
-                             struct command_t3_entry *cmd_entry,
-                             uint16_t tot_dsds)
+static void qla4xxx_build_scsi_iocbs(struct srb *srb,
+                                    struct command_t3_entry *cmd_entry,
+                                    uint16_t tot_dsds)
 {
        struct scsi_qla_host *ha;
        uint16_t avail_dsds;
index 7f28657eef3f1d60e74827d7084408299042eea3..f116ff9172374bc3a07a6f10e58cf18bf84d02d7 100644 (file)
@@ -20,9 +20,9 @@
  * If outCount is 0, this routine completes successfully WITHOUT waiting
  * for the mailbox command to complete.
  **/
-int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
-                           uint8_t outCount, uint32_t *mbx_cmd,
-                           uint32_t *mbx_sts)
+static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
+                                  uint8_t outCount, uint32_t *mbx_cmd,
+                                  uint32_t *mbx_sts)
 {
        int status = QLA_ERROR;
        uint8_t i;
@@ -170,6 +170,8 @@ mbox_exit:
 }
 
 
+#if 0
+
 /**
  * qla4xxx_issue_iocb - issue mailbox iocb command
  * @ha: adapter state pointer.
@@ -243,6 +245,8 @@ int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
        return QLA_SUCCESS;
 }
 
+#endif  /*  0  */
+
 /**
  * qla4xxx_initialize_fw_cb - initializes firmware control block.
  * @ha: Pointer to host adapter structure.
@@ -570,6 +574,7 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
        return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
 }
 
+#if 0
 int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
                                    uint16_t fw_ddb_index)
 {
@@ -594,6 +599,7 @@ int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
 
                return status;
 }
+#endif  /*  0  */
 
 /**
  * qla4xxx_get_crash_record - retrieves crash record.
@@ -649,6 +655,7 @@ exit_get_crash_record:
                                  crash_record, crash_record_dma);
 }
 
+#if 0
 /**
  * qla4xxx_get_conn_event_log - retrieves connection event log
  * @ha: Pointer to host adapter structure.
@@ -738,6 +745,7 @@ exit_get_event_log:
                dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
                                  event_log_dma);
 }
+#endif  /*  0  */
 
 /**
  * qla4xxx_reset_lun - issues LUN Reset
@@ -834,7 +842,8 @@ int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
        return QLA_SUCCESS;
 }
 
-int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
+static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
+                                  dma_addr_t dma_addr)
 {
        uint32_t mbox_cmd[MBOX_REG_COUNT];
        uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -855,7 +864,7 @@ int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
        return QLA_SUCCESS;
 }
 
-int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
+static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
 {
        uint32_t mbox_cmd[MBOX_REG_COUNT];
        uint32_t mbox_sts[MBOX_REG_COUNT];
index 0bfddf893ed0eba06e1362e0a4f06016eafcf86c..da21f5fbbf87cbb6f6c2c8502fbdd41a97551d59 100644 (file)
@@ -14,7 +14,7 @@
 /*
  * Driver version
  */
-char qla4xxx_version_str[40];
+static char qla4xxx_version_str[40];
 
 /*
  * SRB allocation cache
@@ -45,8 +45,7 @@ int ql4_mod_unload = 0;
 /*
  * SCSI host template entry points
  */
-
-void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
+static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
 
 /*
  * iSCSI template entry points
@@ -1352,7 +1351,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
  * At exit, the @ha's flags.enable_64bit_addressing set to indicated
  * supported addressing method.
  */
-void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
+static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
 {
        int retval;
 
@@ -1627,7 +1626,7 @@ static struct pci_device_id qla4xxx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
 
-struct pci_driver qla4xxx_pci_driver = {
+static struct pci_driver qla4xxx_pci_driver = {
        .name           = DRIVER_NAME,
        .id_table       = qla4xxx_pci_tbl,
        .probe          = qla4xxx_probe_adapter,
index 3e2930b7ee2397bef4207dbf545a75667907893c..06229f225ee9723fce6b21aedfc099c06aa7d32d 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
 
index 3963e7013bd90eca80df51c268427a4f3107af32..e8350c562d24c0a4598d7a4c0e4066c1b4911d35 100644 (file)
@@ -38,7 +38,6 @@
 #include "scsi_logging.h"
 
 #define SENSE_TIMEOUT          (10*HZ)
-#define START_UNIT_TIMEOUT     (30*HZ)
 
 /*
  * These should *probably* be handled by the host itself.
@@ -936,7 +935,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
 
                for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
                        rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
-                                               START_UNIT_TIMEOUT, 0);
+                                               scmd->device->timeout, 0);
 
                if (rtn == SUCCESS)
                        return 0;
index 61fbcdcbb009e93ae5d59ef11fb95d6a416cf82c..1f5a07bf2a7535e439300b4daa51f898983973ef 100644 (file)
@@ -173,7 +173,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
  * @retries:   number of times to retry request
  * @flags:     or into request flags;
  *
- * returns the req->errors value which is the the scsi_cmnd result
+ * returns the req->errors value which is the scsi_cmnd result
  * field.
  **/
 int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
index 14c4f065b2b8091c88c853bd7cbc732e027f160d..b4d1ece46f789d92e6cc94acdb38410625852233 100644 (file)
@@ -1718,31 +1718,12 @@ fc_starget_delete(struct work_struct *work)
        struct fc_rport *rport =
                container_of(work, struct fc_rport, stgt_delete_work);
        struct Scsi_Host *shost = rport_to_shost(rport);
-       unsigned long flags;
        struct fc_internal *i = to_fc_internal(shost->transportt);
 
-       /*
-        * Involve the LLDD if possible. All io on the rport is to
-        * be terminated, either as part of the dev_loss_tmo callback
-        * processing, or via the terminate_rport_io function.
-        */
-       if (i->f->dev_loss_tmo_callbk)
-               i->f->dev_loss_tmo_callbk(rport);
-       else if (i->f->terminate_rport_io)
+       /* Involve the LLDD if possible to terminate all io on the rport. */
+       if (i->f->terminate_rport_io)
                i->f->terminate_rport_io(rport);
 
-       spin_lock_irqsave(shost->host_lock, flags);
-       if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
-               spin_unlock_irqrestore(shost->host_lock, flags);
-               if (!cancel_delayed_work(&rport->fail_io_work))
-                       fc_flush_devloss(shost);
-               if (!cancel_delayed_work(&rport->dev_loss_work))
-                       fc_flush_devloss(shost);
-               spin_lock_irqsave(shost->host_lock, flags);
-               rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
-       }
-       spin_unlock_irqrestore(shost->host_lock, flags);
-
        scsi_remove_target(&rport->dev);
 }
 
@@ -1760,6 +1741,7 @@ fc_rport_final_delete(struct work_struct *work)
        struct device *dev = &rport->dev;
        struct Scsi_Host *shost = rport_to_shost(rport);
        struct fc_internal *i = to_fc_internal(shost->transportt);
+       unsigned long flags;
 
        /*
         * if a scan is pending, flush the SCSI Host work_q so that 
@@ -1768,13 +1750,37 @@ fc_rport_final_delete(struct work_struct *work)
        if (rport->flags & FC_RPORT_SCAN_PENDING)
                scsi_flush_work(shost);
 
+       /* involve the LLDD to terminate all pending i/o */
+       if (i->f->terminate_rport_io)
+               i->f->terminate_rport_io(rport);
+
+       /*
+        * Cancel any outstanding timers. These should really exist
+        * only when rmmod'ing the LLDD and we're asking for
+        * immediate termination of the rports
+        */
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
+               spin_unlock_irqrestore(shost->host_lock, flags);
+               if (!cancel_delayed_work(&rport->fail_io_work))
+                       fc_flush_devloss(shost);
+               if (!cancel_delayed_work(&rport->dev_loss_work))
+                       fc_flush_devloss(shost);
+               spin_lock_irqsave(shost->host_lock, flags);
+               rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+       }
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
        /* Delete SCSI target and sdevs */
        if (rport->scsi_target_id != -1)
                fc_starget_delete(&rport->stgt_delete_work);
-       else if (i->f->dev_loss_tmo_callbk)
+
+       /*
+        * Notify the driver that the rport is now dead. The LLDD will
+        * also guarantee that any communication to the rport is terminated
+        */
+       if (i->f->dev_loss_tmo_callbk)
                i->f->dev_loss_tmo_callbk(rport);
-       else if (i->f->terminate_rport_io)
-               i->f->terminate_rport_io(rport);
 
        transport_remove_device(dev);
        device_del(dev);
@@ -1963,8 +1969,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                        }
 
                        if (match) {
-                               struct delayed_work *work =
-                                                       &rport->dev_loss_work;
 
                                memcpy(&rport->node_name, &ids->node_name,
                                        sizeof(rport->node_name));
@@ -1982,46 +1986,61 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                                                fci->f->dd_fcrport_size);
 
                                /*
-                                * If we were blocked, we were a target.
-                                * If no longer a target, we leave the timer
-                                * running in case the port changes roles
-                                * prior to the timer expiring. If the timer
-                                * fires, the target will be torn down.
+                                * If we were not a target, cancel the
+                                * io terminate and rport timers, and
+                                * we're done.
+                                *
+                                * If we were a target, but our new role
+                                * doesn't indicate a target, leave the
+                                * timers running expecting the role to
+                                * change as the target fully logs in. If
+                                * it doesn't, the target will be torn down.
+                                *
+                                * If we were a target, and our role shows
+                                * we're still a target, cancel the timers
+                                * and kick off a scan.
                                 */
-                               if (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET))
-                                       return rport;
 
-                               /* restart the target */
+                               /* was a target, not in roles */
+                               if ((rport->scsi_target_id != -1) &&
+                                   (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
+                                       return rport;
 
                                /*
-                                * Stop the target timers first. Take no action
-                                * on the del_timer failure as the state
-                                * machine state change will validate the
-                                * transaction.
+                                * Stop the fail io and dev_loss timers.
+                                * If they flush, the port_state will
+                                * be checked and will NOOP the function.
                                 */
                                if (!cancel_delayed_work(&rport->fail_io_work))
                                        fc_flush_devloss(shost);
-                               if (!cancel_delayed_work(work))
+                               if (!cancel_delayed_work(&rport->dev_loss_work))
                                        fc_flush_devloss(shost);
 
                                spin_lock_irqsave(shost->host_lock, flags);
 
                                rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
 
-                               /* initiate a scan of the target */
-                               rport->flags |= FC_RPORT_SCAN_PENDING;
-                               scsi_queue_work(shost, &rport->scan_work);
-
-                               spin_unlock_irqrestore(shost->host_lock, flags);
-
-                               scsi_target_unblock(&rport->dev);
+                               /* if target, initiate a scan */
+                               if (rport->scsi_target_id != -1) {
+                                       rport->flags |= FC_RPORT_SCAN_PENDING;
+                                       scsi_queue_work(shost,
+                                                       &rport->scan_work);
+                                       spin_unlock_irqrestore(shost->host_lock,
+                                                       flags);
+                                       scsi_target_unblock(&rport->dev);
+                               } else
+                                       spin_unlock_irqrestore(shost->host_lock,
+                                                       flags);
 
                                return rport;
                        }
                }
        }
 
-       /* Search the bindings array */
+       /*
+        * Search the bindings array
+        * Note: if never a FCP target, you won't be on this list
+        */
        if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
 
                /* search for a matching consistent binding */
@@ -2158,15 +2177,24 @@ fc_remote_port_delete(struct fc_rport  *rport)
 
        spin_lock_irqsave(shost->host_lock, flags);
 
-       /* If no scsi target id mapping, delete it */
-       if (rport->scsi_target_id == -1) {
-               list_del(&rport->peers);
-               rport->port_state = FC_PORTSTATE_DELETED;
-               fc_queue_work(shost, &rport->rport_delete_work);
+       if (rport->port_state != FC_PORTSTATE_ONLINE) {
                spin_unlock_irqrestore(shost->host_lock, flags);
                return;
        }
 
+       /*
+        * In the past, we if this was not an FCP-Target, we would
+        * unconditionally just jump to deleting the rport.
+        * However, rports can be used as node containers by the LLDD,
+        * and its not appropriate to just terminate the rport at the
+        * first sign of a loss in connectivity. The LLDD may want to
+        * send ELS traffic to re-validate the login. If the rport is
+        * immediately deleted, it makes it inappropriate for a node
+        * container.
+        * So... we now unconditionally wait dev_loss_tmo before
+        * destroying an rport.
+        */
+
        rport->port_state = FC_PORTSTATE_BLOCKED;
 
        rport->flags |= FC_RPORT_DEVLOSS_PENDING;
@@ -2263,11 +2291,11 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
 EXPORT_SYMBOL(fc_remote_port_rolechg);
 
 /**
- * fc_timeout_deleted_rport - Timeout handler for a deleted remote port that
- *                       was a SCSI target (thus was blocked), and failed
- *                       to return in the alloted time.
+ * fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
+ *                     which we blocked, and has now failed to return
+ *                     in the allotted time.
  * 
- * @work:      rport target that failed to reappear in the alloted time.
+ * @work:      rport target that failed to reappear in the allotted time.
  **/
 static void
 fc_timeout_deleted_rport(struct work_struct *work)
@@ -2283,10 +2311,12 @@ fc_timeout_deleted_rport(struct work_struct *work)
        rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
 
        /*
-        * If the port is ONLINE, then it came back. Validate it's still an
-        * FCP target. If not, tear down the scsi_target on it.
+        * If the port is ONLINE, then it came back. If it was a SCSI
+        * target, validate it still is. If not, tear down the
+        * scsi_target on it.
         */
        if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+           (rport->scsi_target_id != -1) &&
            !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
                dev_printk(KERN_ERR, &rport->dev,
                        "blocked FC remote port time out: no longer"
@@ -2297,18 +2327,24 @@ fc_timeout_deleted_rport(struct work_struct *work)
                return;
        }
 
+       /* NOOP state - we're flushing workq's */
        if (rport->port_state != FC_PORTSTATE_BLOCKED) {
                spin_unlock_irqrestore(shost->host_lock, flags);
                dev_printk(KERN_ERR, &rport->dev,
-                       "blocked FC remote port time out: leaving target alone\n");
+                       "blocked FC remote port time out: leaving"
+                       " rport%s alone\n",
+                       (rport->scsi_target_id != -1) ?  " and starget" : "");
                return;
        }
 
-       if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) {
+       if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
+           (rport->scsi_target_id == -1)) {
                list_del(&rport->peers);
                rport->port_state = FC_PORTSTATE_DELETED;
                dev_printk(KERN_ERR, &rport->dev,
-                       "blocked FC remote port time out: removing target\n");
+                       "blocked FC remote port time out: removing"
+                       " rport%s\n",
+                       (rport->scsi_target_id != -1) ?  " and starget" : "");
                fc_queue_work(shost, &rport->rport_delete_work);
                spin_unlock_irqrestore(shost->host_lock, flags);
                return;
index 570977cf9efbf7966fa6c631804f3fb9b06a603d..0c691a60a756f6144d01706e566d7704a4e41075 100644 (file)
@@ -41,7 +41,6 @@ static int sg_version_num = 30534;    /* 2 digits for each component */
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/moduleparam.h>
 #include <linux/cdev.h>
 #include <linux/seq_file.h>
index 6bc505115841cd2ee5652e25a5354bd8ea6eab77..a7dfb65fb84277870d08899192dfbeac2823b8ce 100644 (file)
@@ -98,7 +98,7 @@ static int __init snirm710_probe(struct platform_device *dev)
        host->this_id = 7;
        host->base = base;
        host->irq = platform_get_irq(dev, 0);
-       if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) {
+       if(request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "snirm710", host)) {
                printk(KERN_ERR "snirm710: request_irq failed!\n");
                goto out_put_host;
        }
index 3158949ffa62206f98c0437462b83a3142f3f215..e7b85e832eb5990d76f45b4b30d255525dae030d 100644 (file)
@@ -351,6 +351,27 @@ static u8  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
  * (DCBs, SRBs, Queueing)
  *
  **********************************************************************/
+static void inline dc390_start_segment(struct dc390_srb* pSRB)
+{
+       struct scatterlist *psgl = pSRB->pSegmentList;
+
+       /* start new sg segment */
+       pSRB->SGBusAddr = sg_dma_address(psgl);
+       pSRB->SGToBeXferLen = sg_dma_len(psgl);
+}
+
+static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
+{
+       unsigned long xfer = pSRB->SGToBeXferLen - residue;
+
+       /* xfer more bytes transferred */
+       pSRB->SGBusAddr += xfer;
+       pSRB->TotalXferredLen += xfer;
+       pSRB->SGToBeXferLen = residue;
+
+       return xfer;
+}
+
 static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
 {
    struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
@@ -625,70 +646,6 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr
     return 0;
 }
 
-//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
-#define DMA_INT 0
-
-#if DMA_INT
-/* This is similar to AM53C974.c ... */
-static u8 
-dc390_dma_intr (struct dc390_acb* pACB)
-{
-  struct dc390_srb* pSRB;
-  u8 dstate;
-  DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev);
-  
-  DEBUG0(pci_read_config_word(pdev, PCI_STATUS, &pstate));
-  DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
-       { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
-         pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));});
-
-  dstate = DC390_read8 (DMA_Status); 
-
-  if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
-  else pSRB  = pACB->pActiveDCB->pActiveSRB;
-  
-  if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
-    {
-       printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
-       return dstate;
-    }
-  if (dstate & DMA_XFER_DONE)
-    {
-       u32 residual, xferCnt; int ctr = 6000000;
-       if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
-         {
-           do
-             {
-               DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n"));
-               dstate = DC390_read8 (DMA_Status);
-               residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
-                 DC390_read8 (CtcReg_High) << 16;
-               residual += DC390_read8 (Current_Fifo) & 0x1f;
-             } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
-           if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
-           /* residual =  ... */
-         }
-       else
-           residual = 0;
-       
-       /* ??? */
-       
-       xferCnt = pSRB->SGToBeXferLen - residual;
-       pSRB->SGBusAddr += xferCnt;
-       pSRB->TotalXferredLen += xferCnt;
-       pSRB->SGToBeXferLen = residual;
-# ifdef DC390_DEBUG0
-       printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n", 
-               (unsigned int)residual, (unsigned int)xferCnt);
-# endif
-       
-       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    }
-  dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
-  return dstate;
-}
-#endif
-
 
 static void __inline__
 dc390_InvalidCmd(struct dc390_acb* pACB)
@@ -708,9 +665,6 @@ DC390_Interrupt(void *dev_id)
     u8  phase;
     void   (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
     u8  istate, istatus;
-#if DMA_INT
-    u8  dstatus;
-#endif
 
     sstatus = DC390_read8 (Scsi_Status);
     if( !(sstatus & INTERRUPT) )
@@ -718,22 +672,9 @@ DC390_Interrupt(void *dev_id)
 
     DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
 
-#if DMA_INT
-    spin_lock_irq(pACB->pScsiHost->host_lock);
-    dstatus = dc390_dma_intr (pACB);
-    spin_unlock_irq(pACB->pScsiHost->host_lock);
-
-    DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus));
-    if (! (dstatus & SCSI_INTERRUPT))
-      {
-       DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"));
-       return IRQ_NONE;
-      }
-#else
     //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
     //dstatus = DC390_read8 (DMA_Status);
     //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-#endif
 
     spin_lock_irq(pACB->pScsiHost->host_lock);
 
@@ -821,11 +762,10 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
 }
 
 static void
-dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
 {
     u8   sstatus;
-    struct scatterlist *psgl;
-    u32    ResidCnt, xferCnt;
+    u32  ResidCnt;
     u8   dstate = 0;
 
     sstatus = *psstatus;
@@ -856,42 +796,35 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
            if( pSRB->SGIndex < pSRB->SGcount )
            {
                pSRB->pSegmentList++;
-               psgl = pSRB->pSegmentList;
 
-               pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
-               pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+               dc390_start_segment(pSRB);
            }
            else
                pSRB->SGToBeXferLen = 0;
        }
        else
        {
-           ResidCnt  = (u32) DC390_read8 (Current_Fifo) & 0x1f;
-           ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16;
-           ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; 
-           ResidCnt += (u32) DC390_read8 (CtcReg_Low);
-
-           xferCnt = pSRB->SGToBeXferLen - ResidCnt;
-           pSRB->SGBusAddr += xferCnt;
-           pSRB->TotalXferredLen += xferCnt;
-           pSRB->SGToBeXferLen = ResidCnt;
+           ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
+                   (((u32) DC390_read8 (CtcReg_High) << 16) |
+                    ((u32) DC390_read8 (CtcReg_Mid) << 8) |
+                    (u32) DC390_read8 (CtcReg_Low));
+
+           dc390_advance_segment(pSRB, ResidCnt);
        }
     }
     if ((*psstatus & 7) != SCSI_DATA_OUT)
     {
-           DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
+           DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
            DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
     }      
 }
 
 static void
-dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
 {
     u8   sstatus, residual, bval;
-    struct scatterlist *psgl;
-    u32    ResidCnt, i;
+    u32  ResidCnt, i;
     unsigned long   xferCnt;
-    u8      *ptr;
 
     sstatus = *psstatus;
 
@@ -922,19 +855,17 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
            DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
                + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8)               \
                + ((unsigned long) DC390_read8 (CtcReg_Low)));
-           DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen));
+           DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
 
-           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
+           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
 
            pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
            pSRB->SGIndex++;
            if( pSRB->SGIndex < pSRB->SGcount )
            {
                pSRB->pSegmentList++;
-               psgl = pSRB->pSegmentList;
 
-               pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
-               pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+               dc390_start_segment(pSRB);
            }
            else
                pSRB->SGToBeXferLen = 0;
@@ -973,47 +904,45 @@ din_1:
            }
            /* It seems a DMA Blast abort isn't that bad ... */
            if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
-           //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
-           dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
+           //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
+           dc390_laststatus &= ~0xff000000;
+           dc390_laststatus |= bval << 24;
 
            DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
-           ResidCnt = (u32) DC390_read8 (CtcReg_High);
-           ResidCnt <<= 8;
-           ResidCnt |= (u32) DC390_read8 (CtcReg_Mid);
-           ResidCnt <<= 8;
-           ResidCnt |= (u32) DC390_read8 (CtcReg_Low);
-
-           xferCnt = pSRB->SGToBeXferLen - ResidCnt;
-           pSRB->SGBusAddr += xferCnt;
-           pSRB->TotalXferredLen += xferCnt;
-           pSRB->SGToBeXferLen = ResidCnt;
-
-           if( residual )
-           {
-               static int feedback_requested;
+           ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
+                       ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
+                   (u32) DC390_read8 (CtcReg_Low);
+
+           xferCnt = dc390_advance_segment(pSRB, ResidCnt);
+
+           if (residual) {
+               size_t count = 1;
+               size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
+               unsigned long flags;
+               u8 *ptr;
+
                bval = DC390_read8 (ScsiFifo);      /* get one residual byte */
 
-               if (!feedback_requested) {
-                       feedback_requested = 1;
-                       printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
-                              "to help improve support for your system.\n", __FILE__);
+               local_irq_save(flags);
+               ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
+               if (likely(ptr)) {
+                       *(ptr + offset) = bval;
+                       scsi_kunmap_atomic_sg(ptr);
                }
+               local_irq_restore(flags);
+               WARN_ON(!ptr);
 
-               ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr );
-               *ptr = bval;
-               pSRB->SGBusAddr++; xferCnt++;
-               pSRB->TotalXferredLen++;
-               pSRB->SGToBeXferLen--;
+               /* 1 more byte read */
+               xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
            }
-           DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
+           DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
                           pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
-
        }
     }
     if ((*psstatus & 7) != SCSI_DATA_IN)
     {
            DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
+           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
     }
 }
 
@@ -1216,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
 
 
 /* handle RESTORE_PTR */
-/* I presume, this command is already mapped, so, have to remap. */
+/* This doesn't look very healthy... to-be-fixed */
 static void 
 dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
 {
@@ -1225,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
     pSRB->TotalXferredLen = 0;
     pSRB->SGIndex = 0;
     if (pcmd->use_sg) {
+       size_t saved;
        pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
        psgl = pSRB->pSegmentList;
        //dc390_pci_sync(pSRB);
@@ -1236,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
            if( pSRB->SGIndex < pSRB->SGcount )
            {
                pSRB->pSegmentList++;
-               psgl = pSRB->pSegmentList;
-               pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
-               pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+
+               dc390_start_segment(pSRB);
            }
            else
                pSRB->SGToBeXferLen = 0;
        }
-       pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
-       pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
+
+       saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
+       pSRB->SGToBeXferLen -= saved;
+       pSRB->SGBusAddr += saved;
        printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
                pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
 
@@ -1365,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
 static void
 dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
 {
-    struct scatterlist *psgl;
     unsigned long  lval;
     struct dc390_dcb*   pDCB = pACB->pActiveDCB;
 
@@ -1391,12 +1321,11 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
 
     if( pSRB->SGIndex < pSRB->SGcount )
     {
-       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
+       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
        if( !pSRB->SGToBeXferLen )
        {
-           psgl = pSRB->pSegmentList;
-           pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
-           pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+           dc390_start_segment(pSRB);
+
            DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
        }
        lval = pSRB->SGToBeXferLen;
@@ -1410,12 +1339,12 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
        DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
        DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
 
-       //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
+       //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
        pSRB->SRBState = SRB_DATA_XFER;
 
        DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
 
-       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
+       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
        //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
        //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
        //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
@@ -1436,8 +1365,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
        pSRB->SRBState |= SRB_XFERPAD;
        DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
 /*
-       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
-       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
+       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
+       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
 */
     }
 }
index 9b66fa8d38d948129df809016c0e81deb87cc900..c3d8c80cfb386182898fd966c4bd1b3d20685074 100644 (file)
 
 #define SEL_TIMEOUT            153     /* 250 ms selection timeout (@ 40 MHz) */
 
-#define pci_dma_lo32(a)                        (a & 0xffffffff)
-
-typedef u8             UCHAR;  /*  8 bits */
-typedef u16            USHORT; /* 16 bits */
-typedef u32            UINT;   /* 32 bits */
-typedef unsigned long  ULONG;  /* 32/64 bits */
-
-
 /*
 ;-----------------------------------------------------------------------
 ; SCSI Request Block
@@ -43,7 +35,9 @@ struct scatterlist    *pSegmentList;
 
 struct scatterlist Segmentx;   /* make a one entry of S/G list table */
 
-unsigned long  SGBusAddr;      /*;a segment starting address as seen by AM53C974A*/
+unsigned long  SGBusAddr;      /*;a segment starting address as seen by AM53C974A
+                                 in CPU endianness. We're only getting 32-bit bus
+                                 addresses by default */
 unsigned long  SGToBeXferLen;  /*; to be xfer length */
 unsigned long  TotalXferredLen;
 unsigned long  SavedTotXLen;
index c9832d963f1efaf715f78a54cbd7d14c8d3ad64c..48e259a0167d180c1f212d3d0f723133dc5ff797 100644 (file)
@@ -994,7 +994,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
         * be frobbing the chips IRQ enable register to see if it exists.
         */
        spin_lock_irqsave(&up->port.lock, flags);
-//     save_flags(flags); cli();
 
        up->capabilities = 0;
        up->bugs = 0;
@@ -1151,7 +1150,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 
  out:
        spin_unlock_irqrestore(&up->port.lock, flags);
-//     restore_flags(flags);
        DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
 }
 
index 924e9bd757f0fe486e71f11796567c3cbf542d6d..e8efe938c4e740a64da3bc68627cb9ad8ae2ecaf 100644 (file)
@@ -73,17 +73,21 @@ config SERIAL_8250_PCI
        depends on SERIAL_8250 && PCI
        default SERIAL_8250
        help
-         This builds standard PCI serial support. You may be able to
-         disable this feature if you only need legacy serial support.
-         Saves about 9K.
+         Say Y here if you have PCI serial ports.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_pci.
 
 config SERIAL_8250_PNP
        tristate "8250/16550 PNP device support" if EMBEDDED
        depends on SERIAL_8250 && PNP
        default SERIAL_8250
        help
-         This builds standard PNP serial support. You may be able to
-         disable this feature if you only need legacy serial support.
+         Say Y here if you have serial ports described by PNPBIOS or ACPI.
+         These are typically ports built into the system board.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_pnp.
 
 config SERIAL_8250_HP300
        tristate
index 7a3b97fdf8d18713509b8c8b9502ce4cb3072bca..f23972bc00c0e7a2552bc9015aebc4965462ee8c 100644 (file)
@@ -934,7 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SMC1_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SMC1].port.lock),
                },
                .flags = FLAG_SMC,
                .tx_nrfifos = TX_NUM_FIFO,
@@ -948,7 +948,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SMC2_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SMC2].port.lock),
                },
                .flags = FLAG_SMC,
                .tx_nrfifos = TX_NUM_FIFO,
@@ -965,7 +965,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SCC1_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC1].port.lock),
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
@@ -979,7 +979,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SCC2_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC2].port.lock),
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
@@ -993,7 +993,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SCC3_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC3].port.lock),
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
@@ -1007,7 +1007,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                        .irq            = SCC4_IRQ,
                        .ops            = &cpm_uart_pops,
                        .iotype         = UPIO_MEM,
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC4].port.lock),
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
index 246c5572667b141e139705f1718c84d4410ad3a6..6202995e8211557a3acc2f70a6fcf17204509f0d 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/kobject.h>
 #include <linux/firmware.h>
index 8be8da37f629b86418d6d9a4ee671cbc8c975878..b2d6f5b1a7c2c3c4fc21b4ecb8e4f31008f050a4 100644 (file)
@@ -581,8 +581,13 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
                return;
 
        /* Scrub off lower bits. They signify delta's, which I don't care about */
-       msignals &= 0xf0;
+       /* Keep DDCD and DDSR though */
+       msignals &= 0xf8;
 
+       if (msignals & UART_MSR_DDCD)
+               uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_DCD);
+       if (msignals & UART_MSR_DDSR)
+               uart_handle_cts_change(&ch->uart_port, msignals & UART_MSR_CTS);
        if (msignals & UART_MSR_DCD)
                ch->ch_mistat |= UART_MSR_DCD;
        else
index be22bbdbc8e5e3532cf385e7ea0a7bc2812a6926..281f23a371b2db831ea3e7d50b4a16a111e04d46 100644 (file)
@@ -448,6 +448,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
                        continue;
 
                brd->channels[i]->uart_port.irq = brd->irq;
+               brd->channels[i]->uart_port.uartclk = 14745600;
                brd->channels[i]->uart_port.type = PORT_JSM;
                brd->channels[i]->uart_port.iotype = UPIO_MEM;
                brd->channels[i]->uart_port.membase = brd->re_map_membase;
index 8d24cd521056793828df902ce864210653ca408d..35f8b86cc78fe3c9acb75626ff913b696d478b30 100644 (file)
@@ -257,9 +257,10 @@ mpc52xx_uart_shutdown(struct uart_port *port)
 {
        struct mpc52xx_psc __iomem *psc = PSC(port);
 
-       /* Shut down the port, interrupt and all */
+       /* Shut down the port.  Leave TX active if on a console port */
        out_8(&psc->command,MPC52xx_PSC_RST_RX);
-       out_8(&psc->command,MPC52xx_PSC_RST_TX);
+       if (!uart_console(port))
+               out_8(&psc->command,MPC52xx_PSC_RST_TX);
 
        port->read_status_mask = 0;
        out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
@@ -1069,7 +1070,7 @@ mpc52xx_uart_of_enumerate(void)
                        continue;
 
                /* Is a particular device number requested? */
-               devno = get_property(np, "port-number", NULL);
+               devno = of_get_property(np, "port-number", NULL);
                mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1);
        }
 
index 336d0f4580d9484f08955952efbb757e2d877769..7ffdaeaf0545e2201803322a1b6959bd73feb3d8 100644 (file)
@@ -29,8 +29,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
        int ret;
 
        memset(port, 0, sizeof *port);
-       spd = get_property(np, "current-speed", NULL);
-       clk = get_property(np, "clock-frequency", NULL);
+       spd = of_get_property(np, "current-speed", NULL);
+       clk = of_get_property(np, "clock-frequency", NULL);
        if (!clk) {
                dev_warn(&ofdev->dev, "no clock-frequency property set\n");
                return -ENODEV;
index be8d75721a85cfd8245b508ed3e3377afe14a140..0fa9f6761763023c45b60b7582fb4e70e2b807c7 100644 (file)
@@ -1450,14 +1450,14 @@ no_dma:
        /*
         * Detect port type
         */
-       if (device_is_compatible(np, "cobalt"))
+       if (of_device_is_compatible(np, "cobalt"))
                uap->flags |= PMACZILOG_FLAG_IS_INTMODEM;
-       conn = get_property(np, "AAPL,connector", &len);
+       conn = of_get_property(np, "AAPL,connector", &len);
        if (conn && (strcmp(conn, "infrared") == 0))
                uap->flags |= PMACZILOG_FLAG_IS_IRDA;
        uap->port_type = PMAC_SCC_ASYNC;
        /* 1999 Powerbook G3 has slot-names property instead */
-       slots = get_property(np, "slot-names", &len);
+       slots = of_get_property(np, "slot-names", &len);
        if (slots && slots->count > 0) {
                if (strcmp(slots->name, "IrDA") == 0)
                        uap->flags |= PMACZILOG_FLAG_IS_IRDA;
@@ -1471,7 +1471,7 @@ no_dma:
                        of_find_node_by_name(NULL, "i2c-modem");
                if (i2c_modem) {
                        const char* mid =
-                               get_property(i2c_modem, "modem-id", NULL);
+                               of_get_property(i2c_modem, "modem-id", NULL);
                        if (mid) switch(*mid) {
                        case 0x04 :
                        case 0x05 :
index 3ba9208ebd0c87de5c610a683b29cf2733a15a80..10bc0209cd661a7b68f7bb7853b0aa10f20751ef 100644 (file)
@@ -957,7 +957,7 @@ static struct uart_driver s3c24xx_uart_drv = {
 static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
        [0] = {
                .port = {
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
                        .iotype         = UPIO_MEM,
                        .irq            = IRQ_S3CUART_RX0,
                        .uartclk        = 0,
@@ -969,7 +969,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
        },
        [1] = {
                .port = {
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
                        .iotype         = UPIO_MEM,
                        .irq            = IRQ_S3CUART_RX1,
                        .uartclk        = 0,
@@ -983,7 +983,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
 
        [2] = {
                .port = {
-                       .lock           = SPIN_LOCK_UNLOCKED,
+                       .lock           = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
                        .iotype         = UPIO_MEM,
                        .irq            = IRQ_S3CUART_RX2,
                        .uartclk        = 0,
index 509ace7e6881a84cf88f0329247aea4a308add43..1deb5764326d089aabe09f4b54fae1290e72be2a 100644 (file)
  * published by the Free Software Foundation.
  *
  *  Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
- *
- *  Revision History:
- *     0.30    Initial revision. (Renamed from serial_txx927.c)
- *     0.31    Use save_flags instead of local_irq_save.
- *     0.32    Support SCLK.
- *     0.33    Switch TXX9_TTY_NAME by CONFIG_SERIAL_TXX9_STDSERIAL.
- *             Support TIOCSERGETLSR.
- *     0.34    Support slow baudrate.
- *     0.40    Merge codes from mainstream kernel (2.4.22).
- *     0.41    Fix console checking in rs_shutdown_port().
- *             Disable flow-control in serial_console_write().
- *     0.42    Fix minor compiler warning.
- *     1.00    Kernel 2.6.  Converted to new serial core (based on 8250.c).
- *     1.01    Set fifosize to make tx_empry called properly.
- *             Use standard uart_get_divisor.
- *     1.02    Cleanup. (import 8250.c changes)
- *     1.03    Fix low-latency mode. (import 8250.c changes)
- *     1.04    Remove usage of deprecated functions, cleanup.
- *     1.05    More strict check in verify_port.  Cleanup.
- *     1.06    Do not insert a char caused previous overrun.
- *             Fix some spin_locks.
- *             Do not call uart_add_one_port for absent ports.
- *     1.07    Use CONFIG_SERIAL_TXX9_NR_UARTS.  Cleanup.
- *     1.08    Use platform_device.
- *             Fix and cleanup suspend/resume/initialization codes.
  */
 
 #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -62,7 +37,7 @@
 
 #include <asm/io.h>
 
-static char *serial_version = "1.08";
+static char *serial_version = "1.09";
 static char *serial_name = "TX39/49 Serial driver";
 
 #define PASS_LIMIT     256
@@ -70,13 +45,14 @@ static char *serial_name = "TX39/49 Serial driver";
 #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
 /* "ttyS" is used for standard serial driver */
 #define TXX9_TTY_NAME "ttyTX"
-#define TXX9_TTY_MINOR_START   (64 + 64)       /* ttyTX0(128), ttyTX1(129) */
+#define TXX9_TTY_MINOR_START   196
+#define TXX9_TTY_MAJOR 204
 #else
 /* acts like standard serial driver */
 #define TXX9_TTY_NAME "ttyS"
 #define TXX9_TTY_MINOR_START   64
-#endif
 #define TXX9_TTY_MAJOR TTY_MAJOR
+#endif
 
 /* flag aliases */
 #define UPF_TXX9_HAVE_CTS_LINE UPF_BUGGY_UART
index 4a012d9acbfffb2832bb8d8ddb6e5b919b2dda3b..07c587ec71be17b42d7900d809199236ffe0f12a 100644 (file)
@@ -64,6 +64,17 @@ config SPI_BFIN
        help
          This is the SPI controller master driver for Blackfin 5xx processor.
 
+config SPI_AU1550
+       tristate "Au1550/Au12x0 SPI Controller"
+       depends on SPI_MASTER && (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
+       select SPI_BITBANG
+       help
+         If you say yes to this option, support will be included for the
+         Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
+
+         This driver can also be built as a module.  If so, the module
+         will be called au1550_spi.
+
 config SPI_BITBANG
        tristate "Bitbanging SPI master"
        depends on SPI_MASTER && EXPERIMENTAL
@@ -159,6 +170,15 @@ config SPI_AT25
          This driver can also be built as a module.  If so, the module
          will be called at25.
 
+config SPI_SPIDEV
+       tristate "User mode SPI device driver support"
+       depends on SPI_MASTER && EXPERIMENTAL
+       help
+         This supports user mode SPI protocol drivers.
+
+         Note that this application programming interface is EXPERIMENTAL
+         and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
index a95ade857a2f328eb859cd66c6f924ea73ec4d34..624b6363f490bf74e7575478e3e0c7732e198449 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_MASTER)              += spi.o
 obj-$(CONFIG_SPI_ATMEL)                        += atmel_spi.o
 obj-$(CONFIG_SPI_BFIN)                 += spi_bfin5xx.o
 obj-$(CONFIG_SPI_BITBANG)              += spi_bitbang.o
+obj-$(CONFIG_SPI_AU1550)               += au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi_butterfly.o
 obj-$(CONFIG_SPI_IMX)                  += spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)               += pxa2xx_spi.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_SPI_S3C24XX)             += spi_s3c24xx.o
 
 # SPI protocol drivers (device/link on bus)
 obj-$(CONFIG_SPI_AT25)         += at25.o
+obj-$(CONFIG_SPI_SPIDEV)       += spidev.o
 #      ... add above this line ...
 
 # SPI slave controller drivers (upstream link)
index 66e7bc985797a0d8acce875c3281e744f7db9849..1d8a2f6bb8ebada212ad8d9617825bd9b96958ab 100644 (file)
 #include <asm/io.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
-
-#ifdef CONFIG_ARCH_AT91
 #include <asm/arch/cpu.h>
-#endif
 
 #include "atmel_spi.h"
 
@@ -552,10 +549,8 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
                goto out_free_buffer;
        as->irq = irq;
        as->clk = clk;
-#ifdef CONFIG_ARCH_AT91
        if (!cpu_is_at91rm9200())
                as->new_1 = 1;
-#endif
 
        ret = request_irq(irq, atmel_spi_interrupt, 0,
                        pdev->dev.bus_id, master);
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
new file mode 100644 (file)
index 0000000..ae2b1af
--- /dev/null
@@ -0,0 +1,974 @@
+/*
+ * au1550_spi.c - au1550 psc spi controller driver
+ * may work also with au1200, au1210, au1250
+ * will not work on au1000, au1100 and au1500 (no full spi controller there)
+ *
+ * Copyright (c) 2006 ATRON electronic GmbH
+ * Author: Jan Nikitenko <jan.nikitenko@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#include <asm/mach-au1x00/au1550_spi.h>
+
+static unsigned usedma = 1;
+module_param(usedma, uint, 0644);
+
+/*
+#define AU1550_SPI_DEBUG_LOOPBACK
+*/
+
+
+#define AU1550_SPI_DBDMA_DESCRIPTORS 1
+#define AU1550_SPI_DMA_RXTMP_MINSIZE 2048U
+
+struct au1550_spi {
+       struct spi_bitbang bitbang;
+
+       volatile psc_spi_t __iomem *regs;
+       int irq;
+       unsigned freq_max;
+       unsigned freq_min;
+
+       unsigned len;
+       unsigned tx_count;
+       unsigned rx_count;
+       const u8 *tx;
+       u8 *rx;
+
+       void (*rx_word)(struct au1550_spi *hw);
+       void (*tx_word)(struct au1550_spi *hw);
+       int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
+       irqreturn_t (*irq_callback)(struct au1550_spi *hw);
+
+       struct completion master_done;
+
+       unsigned usedma;
+       u32 dma_tx_id;
+       u32 dma_rx_id;
+       u32 dma_tx_ch;
+       u32 dma_rx_ch;
+
+       u8 *dma_rx_tmpbuf;
+       unsigned dma_rx_tmpbuf_size;
+       u32 dma_rx_tmpbuf_addr;
+
+       struct spi_master *master;
+       struct device *dev;
+       struct au1550_spi_info *pdata;
+};
+
+
+/* we use an 8-bit memory device for dma transfers to/from spi fifo */
+static dbdev_tab_t au1550_spi_mem_dbdev =
+{
+       .dev_id                 = DBDMA_MEM_CHAN,
+       .dev_flags              = DEV_FLAGS_ANYUSE|DEV_FLAGS_SYNC,
+       .dev_tsize              = 0,
+       .dev_devwidth           = 8,
+       .dev_physaddr           = 0x00000000,
+       .dev_intlevel           = 0,
+       .dev_intpolarity        = 0
+};
+
+static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
+
+
+/**
+ *  compute BRG and DIV bits to setup spi clock based on main input clock rate
+ *  that was specified in platform data structure
+ *  according to au1550 datasheet:
+ *    psc_tempclk = psc_mainclk / (2 << DIV)
+ *    spiclk = psc_tempclk / (2 * (BRG + 1))
+ *    BRG valid range is 4..63
+ *    DIV valid range is 0..3
+ */
+static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned speed_hz)
+{
+       u32 mainclk_hz = hw->pdata->mainclk_hz;
+       u32 div, brg;
+
+       for (div = 0; div < 4; div++) {
+               brg = mainclk_hz / speed_hz / (4 << div);
+               /* now we have BRG+1 in brg, so count with that */
+               if (brg < (4 + 1)) {
+                       brg = (4 + 1);  /* speed_hz too big */
+                       break;          /* set lowest brg (div is == 0) */
+               }
+               if (brg <= (63 + 1))
+                       break;          /* we have valid brg and div */
+       }
+       if (div == 4) {
+               div = 3;                /* speed_hz too small */
+               brg = (63 + 1);         /* set highest brg and div */
+       }
+       brg--;
+       return PSC_SPICFG_SET_BAUD(brg) | PSC_SPICFG_SET_DIV(div);
+}
+
+static inline void au1550_spi_mask_ack_all(struct au1550_spi *hw)
+{
+       hw->regs->psc_spimsk =
+                 PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
+               | PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
+               | PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
+       au_sync();
+
+       hw->regs->psc_spievent =
+                 PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
+               | PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
+               | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
+       au_sync();
+}
+
+static void au1550_spi_reset_fifos(struct au1550_spi *hw)
+{
+       u32 pcr;
+
+       hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
+       au_sync();
+       do {
+               pcr = hw->regs->psc_spipcr;
+               au_sync();
+       } while (pcr != 0);
+}
+
+/*
+ * dma transfers are used for the most common spi word size of 8-bits
+ * we cannot easily change already set up dma channels' width, so if we wanted
+ * dma support for more than 8-bit words (up to 24 bits), we would need to
+ * setup dma channels from scratch on each spi transfer, based on bits_per_word
+ * instead we have pre set up 8 bit dma channels supporting spi 4 to 8 bits
+ * transfers, and 9 to 24 bits spi transfers will be done in pio irq based mode
+ * callbacks to handle dma or pio are set up in au1550_spi_bits_handlers_set()
+ */
+static void au1550_spi_chipsel(struct spi_device *spi, int value)
+{
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+       unsigned cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+       u32 cfg, stat;
+
+       switch (value) {
+       case BITBANG_CS_INACTIVE:
+               if (hw->pdata->deactivate_cs)
+                       hw->pdata->deactivate_cs(hw->pdata, spi->chip_select,
+                                       cspol);
+               break;
+
+       case BITBANG_CS_ACTIVE:
+               au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
+
+               cfg = hw->regs->psc_spicfg;
+               au_sync();
+               hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
+               au_sync();
+
+               if (spi->mode & SPI_CPOL)
+                       cfg |= PSC_SPICFG_BI;
+               else
+                       cfg &= ~PSC_SPICFG_BI;
+               if (spi->mode & SPI_CPHA)
+                       cfg &= ~PSC_SPICFG_CDE;
+               else
+                       cfg |= PSC_SPICFG_CDE;
+
+               if (spi->mode & SPI_LSB_FIRST)
+                       cfg |= PSC_SPICFG_MLF;
+               else
+                       cfg &= ~PSC_SPICFG_MLF;
+
+               if (hw->usedma && spi->bits_per_word <= 8)
+                       cfg &= ~PSC_SPICFG_DD_DISABLE;
+               else
+                       cfg |= PSC_SPICFG_DD_DISABLE;
+               cfg = PSC_SPICFG_CLR_LEN(cfg);
+               cfg |= PSC_SPICFG_SET_LEN(spi->bits_per_word);
+
+               cfg = PSC_SPICFG_CLR_BAUD(cfg);
+               cfg &= ~PSC_SPICFG_SET_DIV(3);
+               cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
+
+               hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
+               au_sync();
+               do {
+                       stat = hw->regs->psc_spistat;
+                       au_sync();
+               } while ((stat & PSC_SPISTAT_DR) == 0);
+
+               if (hw->pdata->activate_cs)
+                       hw->pdata->activate_cs(hw->pdata, spi->chip_select,
+                                       cspol);
+               break;
+       }
+}
+
+static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+       unsigned bpw, hz;
+       u32 cfg, stat;
+
+       bpw = t ? t->bits_per_word : spi->bits_per_word;
+       hz = t ? t->speed_hz : spi->max_speed_hz;
+
+       if (bpw < 4 || bpw > 24) {
+               dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n",
+                       bpw);
+               return -EINVAL;
+       }
+       if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
+               dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n",
+                       hz);
+               return -EINVAL;
+       }
+
+       au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
+
+       cfg = hw->regs->psc_spicfg;
+       au_sync();
+       hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
+       au_sync();
+
+       if (hw->usedma && bpw <= 8)
+               cfg &= ~PSC_SPICFG_DD_DISABLE;
+       else
+               cfg |= PSC_SPICFG_DD_DISABLE;
+       cfg = PSC_SPICFG_CLR_LEN(cfg);
+       cfg |= PSC_SPICFG_SET_LEN(bpw);
+
+       cfg = PSC_SPICFG_CLR_BAUD(cfg);
+       cfg &= ~PSC_SPICFG_SET_DIV(3);
+       cfg |= au1550_spi_baudcfg(hw, hz);
+
+       hw->regs->psc_spicfg = cfg;
+       au_sync();
+
+       if (cfg & PSC_SPICFG_DE_ENABLE) {
+               do {
+                       stat = hw->regs->psc_spistat;
+                       au_sync();
+               } while ((stat & PSC_SPISTAT_DR) == 0);
+       }
+
+       au1550_spi_reset_fifos(hw);
+       au1550_spi_mask_ack_all(hw);
+       return 0;
+}
+
+static int au1550_spi_setup(struct spi_device *spi)
+{
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+
+       if (spi->bits_per_word == 0)
+               spi->bits_per_word = 8;
+       if (spi->bits_per_word < 4 || spi->bits_per_word > 24) {
+               dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n",
+                       spi->bits_per_word);
+               return -EINVAL;
+       }
+
+       if (spi->max_speed_hz == 0)
+               spi->max_speed_hz = hw->freq_max;
+       if (spi->max_speed_hz > hw->freq_max
+                       || spi->max_speed_hz < hw->freq_min)
+               return -EINVAL;
+       /*
+        * NOTE: cannot change speed and other hw settings immediately,
+        *       otherwise sharing of spi bus is not possible,
+        *       so do not call setupxfer(spi, NULL) here
+        */
+       return 0;
+}
+
+/*
+ * for dma spi transfers, we have to setup rx channel, otherwise there is
+ * no reliable way how to recognize that spi transfer is done
+ * dma complete callbacks are called before real spi transfer is finished
+ * and if only tx dma channel is set up (and rx fifo overflow event masked)
+ * spi master done event irq is not generated unless rx fifo is empty (emptied)
+ * so we need rx tmp buffer to use for rx dma if user does not provide one
+ */
+static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size)
+{
+       hw->dma_rx_tmpbuf = kmalloc(size, GFP_KERNEL);
+       if (!hw->dma_rx_tmpbuf)
+               return -ENOMEM;
+       hw->dma_rx_tmpbuf_size = size;
+       hw->dma_rx_tmpbuf_addr = dma_map_single(hw->dev, hw->dma_rx_tmpbuf,
+                       size, DMA_FROM_DEVICE);
+       if (dma_mapping_error(hw->dma_rx_tmpbuf_addr)) {
+               kfree(hw->dma_rx_tmpbuf);
+               hw->dma_rx_tmpbuf = 0;
+               hw->dma_rx_tmpbuf_size = 0;
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw)
+{
+       dma_unmap_single(hw->dev, hw->dma_rx_tmpbuf_addr,
+                       hw->dma_rx_tmpbuf_size, DMA_FROM_DEVICE);
+       kfree(hw->dma_rx_tmpbuf);
+       hw->dma_rx_tmpbuf = 0;
+       hw->dma_rx_tmpbuf_size = 0;
+}
+
+static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+       dma_addr_t dma_tx_addr;
+       dma_addr_t dma_rx_addr;
+       u32 res;
+
+       hw->len = t->len;
+       hw->tx_count = 0;
+       hw->rx_count = 0;
+
+       hw->tx = t->tx_buf;
+       hw->rx = t->rx_buf;
+       dma_tx_addr = t->tx_dma;
+       dma_rx_addr = t->rx_dma;
+
+       /*
+        * check if buffers are already dma mapped, map them otherwise
+        * use rx buffer in place of tx if tx buffer was not provided
+        * use temp rx buffer (preallocated or realloc to fit) for rx dma
+        */
+       if (t->rx_buf) {
+               if (t->rx_dma == 0) {   /* if DMA_ADDR_INVALID, map it */
+                       dma_rx_addr = dma_map_single(hw->dev,
+                                       (void *)t->rx_buf,
+                                       t->len, DMA_FROM_DEVICE);
+                       if (dma_mapping_error(dma_rx_addr))
+                               dev_err(hw->dev, "rx dma map error\n");
+               }
+       } else {
+               if (t->len > hw->dma_rx_tmpbuf_size) {
+                       int ret;
+
+                       au1550_spi_dma_rxtmp_free(hw);
+                       ret = au1550_spi_dma_rxtmp_alloc(hw, max(t->len,
+                                       AU1550_SPI_DMA_RXTMP_MINSIZE));
+                       if (ret < 0)
+                               return ret;
+               }
+               hw->rx = hw->dma_rx_tmpbuf;
+               dma_rx_addr = hw->dma_rx_tmpbuf_addr;
+               dma_sync_single_for_device(hw->dev, dma_rx_addr,
+                       t->len, DMA_FROM_DEVICE);
+       }
+       if (t->tx_buf) {
+               if (t->tx_dma == 0) {   /* if DMA_ADDR_INVALID, map it */
+                       dma_tx_addr = dma_map_single(hw->dev,
+                                       (void *)t->tx_buf,
+                                       t->len, DMA_TO_DEVICE);
+                       if (dma_mapping_error(dma_tx_addr))
+                               dev_err(hw->dev, "tx dma map error\n");
+               }
+       } else {
+               dma_sync_single_for_device(hw->dev, dma_rx_addr,
+                               t->len, DMA_BIDIRECTIONAL);
+               hw->tx = hw->rx;
+       }
+
+       /* put buffers on the ring */
+       res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, hw->rx, t->len);
+       if (!res)
+               dev_err(hw->dev, "rx dma put dest error\n");
+
+       res = au1xxx_dbdma_put_source(hw->dma_tx_ch, (void *)hw->tx, t->len);
+       if (!res)
+               dev_err(hw->dev, "tx dma put source error\n");
+
+       au1xxx_dbdma_start(hw->dma_rx_ch);
+       au1xxx_dbdma_start(hw->dma_tx_ch);
+
+       /* by default enable nearly all events interrupt */
+       hw->regs->psc_spimsk = PSC_SPIMSK_SD;
+       au_sync();
+
+       /* start the transfer */
+       hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+       au_sync();
+
+       wait_for_completion(&hw->master_done);
+
+       au1xxx_dbdma_stop(hw->dma_tx_ch);
+       au1xxx_dbdma_stop(hw->dma_rx_ch);
+
+       if (!t->rx_buf) {
+               /* using the temporal preallocated and premapped buffer */
+               dma_sync_single_for_cpu(hw->dev, dma_rx_addr, t->len,
+                       DMA_FROM_DEVICE);
+       }
+       /* unmap buffers if mapped above */
+       if (t->rx_buf && t->rx_dma == 0 )
+               dma_unmap_single(hw->dev, dma_rx_addr, t->len,
+                       DMA_FROM_DEVICE);
+       if (t->tx_buf && t->tx_dma == 0 )
+               dma_unmap_single(hw->dev, dma_tx_addr, t->len,
+                       DMA_TO_DEVICE);
+
+       return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
+}
+
+static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
+{
+       u32 stat, evnt;
+
+       stat = hw->regs->psc_spistat;
+       evnt = hw->regs->psc_spievent;
+       au_sync();
+       if ((stat & PSC_SPISTAT_DI) == 0) {
+               dev_err(hw->dev, "Unexpected IRQ!\n");
+               return IRQ_NONE;
+       }
+
+       if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
+                               | PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
+                               | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+                       != 0) {
+               /*
+                * due to an spi error we consider transfer as done,
+                * so mask all events until before next transfer start
+                * and stop the possibly running dma immediatelly
+                */
+               au1550_spi_mask_ack_all(hw);
+               au1xxx_dbdma_stop(hw->dma_rx_ch);
+               au1xxx_dbdma_stop(hw->dma_tx_ch);
+
+               /* get number of transfered bytes */
+               hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch);
+               hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch);
+
+               au1xxx_dbdma_reset(hw->dma_rx_ch);
+               au1xxx_dbdma_reset(hw->dma_tx_ch);
+               au1550_spi_reset_fifos(hw);
+
+               dev_err(hw->dev,
+                       "Unexpected SPI error: event=0x%x stat=0x%x!\n",
+                       evnt, stat);
+
+               complete(&hw->master_done);
+               return IRQ_HANDLED;
+       }
+
+       if ((evnt & PSC_SPIEVNT_MD) != 0) {
+               /* transfer completed successfully */
+               au1550_spi_mask_ack_all(hw);
+               hw->rx_count = hw->len;
+               hw->tx_count = hw->len;
+               complete(&hw->master_done);
+       }
+       return IRQ_HANDLED;
+}
+
+
+/* routines to handle different word sizes in pio mode */
+#define AU1550_SPI_RX_WORD(size, mask)                                 \
+static void au1550_spi_rx_word_##size(struct au1550_spi *hw)           \
+{                                                                      \
+       u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);             \
+       au_sync();                                                      \
+       if (hw->rx) {                                                   \
+               *(u##size *)hw->rx = (u##size)fifoword;                 \
+               hw->rx += (size) / 8;                                   \
+       }                                                               \
+       hw->rx_count += (size) / 8;                                     \
+}
+
+#define AU1550_SPI_TX_WORD(size, mask)                                 \
+static void au1550_spi_tx_word_##size(struct au1550_spi *hw)           \
+{                                                                      \
+       u32 fifoword = 0;                                               \
+       if (hw->tx) {                                                   \
+               fifoword = *(u##size *)hw->tx & (u32)(mask);            \
+               hw->tx += (size) / 8;                                   \
+       }                                                               \
+       hw->tx_count += (size) / 8;                                     \
+       if (hw->tx_count >= hw->len)                                    \
+               fifoword |= PSC_SPITXRX_LC;                             \
+       hw->regs->psc_spitxrx = fifoword;                               \
+       au_sync();                                                      \
+}
+
+AU1550_SPI_RX_WORD(8,0xff)
+AU1550_SPI_RX_WORD(16,0xffff)
+AU1550_SPI_RX_WORD(32,0xffffff)
+AU1550_SPI_TX_WORD(8,0xff)
+AU1550_SPI_TX_WORD(16,0xffff)
+AU1550_SPI_TX_WORD(32,0xffffff)
+
+static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
+{
+       u32 stat, mask;
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+
+       hw->tx = t->tx_buf;
+       hw->rx = t->rx_buf;
+       hw->len = t->len;
+       hw->tx_count = 0;
+       hw->rx_count = 0;
+
+       /* by default enable nearly all events after filling tx fifo */
+       mask = PSC_SPIMSK_SD;
+
+       /* fill the transmit FIFO */
+       while (hw->tx_count < hw->len) {
+
+               hw->tx_word(hw);
+
+               if (hw->tx_count >= hw->len) {
+                       /* mask tx fifo request interrupt as we are done */
+                       mask |= PSC_SPIMSK_TR;
+               }
+
+               stat = hw->regs->psc_spistat;
+               au_sync();
+               if (stat & PSC_SPISTAT_TF)
+                       break;
+       }
+
+       /* enable event interrupts */
+       hw->regs->psc_spimsk = mask;
+       au_sync();
+
+       /* start the transfer */
+       hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+       au_sync();
+
+       wait_for_completion(&hw->master_done);
+
+       return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
+}
+
+static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
+{
+       int busy;
+       u32 stat, evnt;
+
+       stat = hw->regs->psc_spistat;
+       evnt = hw->regs->psc_spievent;
+       au_sync();
+       if ((stat & PSC_SPISTAT_DI) == 0) {
+               dev_err(hw->dev, "Unexpected IRQ!\n");
+               return IRQ_NONE;
+       }
+
+       if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
+                               | PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
+                               | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+                       != 0) {
+               dev_err(hw->dev,
+                       "Unexpected SPI error: event=0x%x stat=0x%x!\n",
+                       evnt, stat);
+               /*
+                * due to an error we consider transfer as done,
+                * so mask all events until before next transfer start
+                */
+               au1550_spi_mask_ack_all(hw);
+               au1550_spi_reset_fifos(hw);
+               complete(&hw->master_done);
+               return IRQ_HANDLED;
+       }
+
+       /*
+        * while there is something to read from rx fifo
+        * or there is a space to write to tx fifo:
+        */
+       do {
+               busy = 0;
+               stat = hw->regs->psc_spistat;
+               au_sync();
+
+               if ((stat & PSC_SPISTAT_RE) == 0 && hw->rx_count < hw->len) {
+                       hw->rx_word(hw);
+                       /* ack the receive request event */
+                       hw->regs->psc_spievent = PSC_SPIEVNT_RR;
+                       au_sync();
+                       busy = 1;
+               }
+
+               if ((stat & PSC_SPISTAT_TF) == 0 && hw->tx_count < hw->len) {
+                       hw->tx_word(hw);
+                       /* ack the transmit request event */
+                       hw->regs->psc_spievent = PSC_SPIEVNT_TR;
+                       au_sync();
+                       busy = 1;
+               }
+       } while (busy);
+
+       evnt = hw->regs->psc_spievent;
+       au_sync();
+
+       if (hw->rx_count >= hw->len || (evnt & PSC_SPIEVNT_MD) != 0) {
+               /* transfer completed successfully */
+               au1550_spi_mask_ack_all(hw);
+               complete(&hw->master_done);
+       }
+       return IRQ_HANDLED;
+}
+
+static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+       return hw->txrx_bufs(spi, t);
+}
+
+static irqreturn_t au1550_spi_irq(int irq, void *dev, struct pt_regs *regs)
+{
+       struct au1550_spi *hw = dev;
+       return hw->irq_callback(hw);
+}
+
+static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
+{
+       if (bpw <= 8) {
+               if (hw->usedma) {
+                       hw->txrx_bufs = &au1550_spi_dma_txrxb;
+                       hw->irq_callback = &au1550_spi_dma_irq_callback;
+               } else {
+                       hw->rx_word = &au1550_spi_rx_word_8;
+                       hw->tx_word = &au1550_spi_tx_word_8;
+                       hw->txrx_bufs = &au1550_spi_pio_txrxb;
+                       hw->irq_callback = &au1550_spi_pio_irq_callback;
+               }
+       } else if (bpw <= 16) {
+               hw->rx_word = &au1550_spi_rx_word_16;
+               hw->tx_word = &au1550_spi_tx_word_16;
+               hw->txrx_bufs = &au1550_spi_pio_txrxb;
+               hw->irq_callback = &au1550_spi_pio_irq_callback;
+       } else {
+               hw->rx_word = &au1550_spi_rx_word_32;
+               hw->tx_word = &au1550_spi_tx_word_32;
+               hw->txrx_bufs = &au1550_spi_pio_txrxb;
+               hw->irq_callback = &au1550_spi_pio_irq_callback;
+       }
+}
+
+static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
+{
+       u32 stat, cfg;
+
+       /* set up the PSC for SPI mode */
+       hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
+       au_sync();
+       hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
+       au_sync();
+
+       hw->regs->psc_spicfg = 0;
+       au_sync();
+
+       hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
+       au_sync();
+
+       do {
+               stat = hw->regs->psc_spistat;
+               au_sync();
+       } while ((stat & PSC_SPISTAT_SR) == 0);
+
+
+       cfg = hw->usedma ? 0 : PSC_SPICFG_DD_DISABLE;
+       cfg |= PSC_SPICFG_SET_LEN(8);
+       cfg |= PSC_SPICFG_RT_FIFO8 | PSC_SPICFG_TT_FIFO8;
+       /* use minimal allowed brg and div values as initial setting: */
+       cfg |= PSC_SPICFG_SET_BAUD(4) | PSC_SPICFG_SET_DIV(0);
+
+#ifdef AU1550_SPI_DEBUG_LOOPBACK
+       cfg |= PSC_SPICFG_LB;
+#endif
+
+       hw->regs->psc_spicfg = cfg;
+       au_sync();
+
+       au1550_spi_mask_ack_all(hw);
+
+       hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
+       au_sync();
+
+       do {
+               stat = hw->regs->psc_spistat;
+               au_sync();
+       } while ((stat & PSC_SPISTAT_DR) == 0);
+}
+
+
+static int __init au1550_spi_probe(struct platform_device *pdev)
+{
+       struct au1550_spi *hw;
+       struct spi_master *master;
+       int err = 0;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
+       if (master == NULL) {
+               dev_err(&pdev->dev, "No memory for spi_master\n");
+               err = -ENOMEM;
+               goto err_nomem;
+       }
+
+       hw = spi_master_get_devdata(master);
+
+       hw->master = spi_master_get(master);
+       hw->pdata = pdev->dev.platform_data;
+       hw->dev = &pdev->dev;
+
+       if (hw->pdata == NULL) {
+               dev_err(&pdev->dev, "No platform data supplied\n");
+               err = -ENOENT;
+               goto err_no_pdata;
+       }
+
+       platform_set_drvdata(pdev, hw);
+
+       init_completion(&hw->master_done);
+
+       hw->bitbang.master = hw->master;
+       hw->bitbang.setup_transfer = au1550_spi_setupxfer;
+       hw->bitbang.chipselect = au1550_spi_chipsel;
+       hw->bitbang.master->setup = au1550_spi_setup;
+       hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
+
+       switch (hw->pdata->bus_num) {
+       case 0:
+               hw->irq = AU1550_PSC0_INT;
+               hw->regs = (volatile psc_spi_t *)PSC0_BASE_ADDR;
+               hw->dma_rx_id = DSCR_CMD0_PSC0_RX;
+               hw->dma_tx_id = DSCR_CMD0_PSC0_TX;
+               break;
+       case 1:
+               hw->irq = AU1550_PSC1_INT;
+               hw->regs = (volatile psc_spi_t *)PSC1_BASE_ADDR;
+               hw->dma_rx_id = DSCR_CMD0_PSC1_RX;
+               hw->dma_tx_id = DSCR_CMD0_PSC1_TX;
+               break;
+       case 2:
+               hw->irq = AU1550_PSC2_INT;
+               hw->regs = (volatile psc_spi_t *)PSC2_BASE_ADDR;
+               hw->dma_rx_id = DSCR_CMD0_PSC2_RX;
+               hw->dma_tx_id = DSCR_CMD0_PSC2_TX;
+               break;
+       case 3:
+               hw->irq = AU1550_PSC3_INT;
+               hw->regs = (volatile psc_spi_t *)PSC3_BASE_ADDR;
+               hw->dma_rx_id = DSCR_CMD0_PSC3_RX;
+               hw->dma_tx_id = DSCR_CMD0_PSC3_TX;
+               break;
+       default:
+               dev_err(&pdev->dev, "Wrong bus_num of SPI\n");
+               err = -ENOENT;
+               goto err_no_pdata;
+       }
+
+       if (request_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t),
+                       pdev->name) == NULL) {
+               dev_err(&pdev->dev, "Cannot reserve iomem region\n");
+               err = -ENXIO;
+               goto err_no_iores;
+       }
+
+
+       if (usedma) {
+               if (pdev->dev.dma_mask == NULL)
+                       dev_warn(&pdev->dev, "no dma mask\n");
+               else
+                       hw->usedma = 1;
+       }
+
+       if (hw->usedma) {
+               /*
+                * create memory device with 8 bits dev_devwidth
+                * needed for proper byte ordering to spi fifo
+                */
+               int memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
+               if (!memid) {
+                       dev_err(&pdev->dev,
+                               "Cannot create dma 8 bit mem device\n");
+                       err = -ENXIO;
+                       goto err_dma_add_dev;
+               }
+
+               hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(memid,
+                       hw->dma_tx_id, NULL, (void *)hw);
+               if (hw->dma_tx_ch == 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot allocate tx dma channel\n");
+                       err = -ENXIO;
+                       goto err_no_txdma;
+               }
+               au1xxx_dbdma_set_devwidth(hw->dma_tx_ch, 8);
+               if (au1xxx_dbdma_ring_alloc(hw->dma_tx_ch,
+                       AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot allocate tx dma descriptors\n");
+                       err = -ENXIO;
+                       goto err_no_txdma_descr;
+               }
+
+
+               hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
+                       memid, NULL, (void *)hw);
+               if (hw->dma_rx_ch == 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot allocate rx dma channel\n");
+                       err = -ENXIO;
+                       goto err_no_rxdma;
+               }
+               au1xxx_dbdma_set_devwidth(hw->dma_rx_ch, 8);
+               if (au1xxx_dbdma_ring_alloc(hw->dma_rx_ch,
+                       AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot allocate rx dma descriptors\n");
+                       err = -ENXIO;
+                       goto err_no_rxdma_descr;
+               }
+
+               err = au1550_spi_dma_rxtmp_alloc(hw,
+                       AU1550_SPI_DMA_RXTMP_MINSIZE);
+               if (err < 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot allocate initial rx dma tmp buffer\n");
+                       goto err_dma_rxtmp_alloc;
+               }
+       }
+
+       au1550_spi_bits_handlers_set(hw, 8);
+
+       err = request_irq(hw->irq, au1550_spi_irq, 0, pdev->name, hw);
+       if (err) {
+               dev_err(&pdev->dev, "Cannot claim IRQ\n");
+               goto err_no_irq;
+       }
+
+       master->bus_num = hw->pdata->bus_num;
+       master->num_chipselect = hw->pdata->num_chipselect;
+
+       /*
+        *  precompute valid range for spi freq - from au1550 datasheet:
+        *    psc_tempclk = psc_mainclk / (2 << DIV)
+        *    spiclk = psc_tempclk / (2 * (BRG + 1))
+        *    BRG valid range is 4..63
+        *    DIV valid range is 0..3
+        *  round the min and max frequencies to values that would still
+        *  produce valid brg and div
+        */
+       {
+               int min_div = (2 << 0) * (2 * (4 + 1));
+               int max_div = (2 << 3) * (2 * (63 + 1));
+               hw->freq_max = hw->pdata->mainclk_hz / min_div;
+               hw->freq_min = hw->pdata->mainclk_hz / (max_div + 1) + 1;
+       }
+
+       au1550_spi_setup_psc_as_spi(hw);
+
+       err = spi_bitbang_start(&hw->bitbang);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to register SPI master\n");
+               goto err_register;
+       }
+
+       dev_info(&pdev->dev,
+               "spi master registered: bus_num=%d num_chipselect=%d\n",
+               master->bus_num, master->num_chipselect);
+
+       return 0;
+
+err_register:
+       free_irq(hw->irq, hw);
+
+err_no_irq:
+       au1550_spi_dma_rxtmp_free(hw);
+
+err_dma_rxtmp_alloc:
+err_no_rxdma_descr:
+       if (hw->usedma)
+               au1xxx_dbdma_chan_free(hw->dma_rx_ch);
+
+err_no_rxdma:
+err_no_txdma_descr:
+       if (hw->usedma)
+               au1xxx_dbdma_chan_free(hw->dma_tx_ch);
+
+err_no_txdma:
+err_dma_add_dev:
+       release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+
+err_no_iores:
+err_no_pdata:
+       spi_master_put(hw->master);
+
+err_nomem:
+       return err;
+}
+
+static int __exit au1550_spi_remove(struct platform_device *pdev)
+{
+       struct au1550_spi *hw = platform_get_drvdata(pdev);
+
+       dev_info(&pdev->dev, "spi master remove: bus_num=%d\n",
+               hw->master->bus_num);
+
+       spi_bitbang_stop(&hw->bitbang);
+       free_irq(hw->irq, hw);
+       release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+
+       if (hw->usedma) {
+               au1550_spi_dma_rxtmp_free(hw);
+               au1xxx_dbdma_chan_free(hw->dma_rx_ch);
+               au1xxx_dbdma_chan_free(hw->dma_tx_ch);
+       }
+
+       platform_set_drvdata(pdev, NULL);
+
+       spi_master_put(hw->master);
+       return 0;
+}
+
+static struct platform_driver au1550_spi_drv = {
+       .remove = __exit_p(au1550_spi_remove),
+       .driver = {
+               .name = "au1550-spi",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init au1550_spi_init(void)
+{
+       return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
+}
+module_init(au1550_spi_init);
+
+static void __exit au1550_spi_exit(void)
+{
+       platform_driver_unregister(&au1550_spi_drv);
+}
+module_exit(au1550_spi_exit);
+
+MODULE_DESCRIPTION("Au1550 PSC SPI Driver");
+MODULE_AUTHOR("Jan Nikitenko <jan.nikitenko@gmail.com>");
+MODULE_LICENSE("GPL");
index 6657331eed9360b6323267261a9e7d080965a2e7..c3219b29b5ac70b87190c36b195c4a6139dc385b 100644 (file)
@@ -152,6 +152,11 @@ static void spi_drv_shutdown(struct device *dev)
        sdrv->shutdown(to_spi_device(dev));
 }
 
+/**
+ * spi_register_driver - register a SPI driver
+ * @sdrv: the driver to register
+ * Context: can sleep
+ */
 int spi_register_driver(struct spi_driver *sdrv)
 {
        sdrv->driver.bus = &spi_bus_type;
@@ -183,7 +188,13 @@ static LIST_HEAD(board_list);
 static DECLARE_MUTEX(board_lock);
 
 
-/* On typical mainboards, this is purely internal; and it's not needed
+/**
+ * spi_new_device - instantiate one new SPI device
+ * @master: Controller to which device is connected
+ * @chip: Describes the SPI device
+ * Context: can sleep
+ *
+ * On typical mainboards, this is purely internal; and it's not needed
  * after board init creates the hard-wired devices.  Some development
  * platforms may not be able to use spi_register_board_info though, and
  * this is exported so that for example a USB or parport based adapter
@@ -251,7 +262,12 @@ fail:
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
-/*
+/**
+ * spi_register_board_info - register SPI devices for a given board
+ * @info: array of chip descriptors
+ * @n: how many descriptors are provided
+ * Context: can sleep
+ *
  * Board-specific early init code calls this (probably during arch_initcall)
  * with segments of the SPI device table.  Any device nodes are created later,
  * after the relevant parent SPI controller (bus_num) is defined.  We keep
@@ -337,9 +353,10 @@ static struct class spi_master_class = {
 /**
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
- * @size: how much driver-private data to preallocate; the pointer to this
+ * @size: how much zeroed driver-private data to allocate; the pointer to this
  *     memory is in the class_data field of the returned class_device,
  *     accessible with spi_master_get_devdata().
+ * Context: can sleep
  *
  * This call is used only by SPI master controller drivers, which are the
  * only ones directly touching chip registers.  It's how they allocate
@@ -375,6 +392,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
 /**
  * spi_register_master - register SPI master controller
  * @master: initialized master, originally from spi_alloc_master()
+ * Context: can sleep
  *
  * SPI master controllers connect to their drivers using some non-SPI bus,
  * such as the platform bus.  The final stage of probe() in that code
@@ -437,6 +455,7 @@ static int __unregister(struct device *dev, void *unused)
 /**
  * spi_unregister_master - unregister SPI master controller
  * @master: the master being unregistered
+ * Context: can sleep
  *
  * This call is used only by SPI master controller drivers, which are the
  * only ones directly touching chip registers.
@@ -455,6 +474,7 @@ EXPORT_SYMBOL_GPL(spi_unregister_master);
 /**
  * spi_busnum_to_master - look up master associated with bus_num
  * @bus_num: the master's bus number
+ * Context: can sleep
  *
  * This call may be used with devices that are registered after
  * arch init time.  It returns a refcounted pointer to the relevant
@@ -492,6 +512,7 @@ static void spi_complete(void *arg)
  * spi_sync - blocking/synchronous SPI data transfers
  * @spi: device with which data will be exchanged
  * @message: describes the data transfers
+ * Context: can sleep
  *
  * This call may only be used from a context that may sleep.  The sleep
  * is non-interruptible, and has no timeout.  Low-overhead controller
@@ -508,7 +529,7 @@ static void spi_complete(void *arg)
  *
  * The return value is a negative error code if the message could not be
  * submitted, else zero.  When the value is zero, then message->status is
- * also defined:  it's the completion code for the transfer, either zero
+ * also defined;  it's the completion code for the transfer, either zero
  * or a negative error code from the controller driver.
  */
 int spi_sync(struct spi_device *spi, struct spi_message *message)
@@ -538,6 +559,7 @@ static u8   *buf;
  * @n_tx: size of txbuf, in bytes
  * @rxbuf: buffer into which data will be read
  * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
+ * Context: can sleep
  *
  * This performs a half duplex MicroWire style transaction with the
  * device, sending txbuf and then reading rxbuf.  The return value
@@ -545,7 +567,8 @@ static u8   *buf;
  * This call may only be used from a context that may sleep.
  *
  * Parameters to this routine are always copied using a small buffer;
- * performance-sensitive or bulk transfer code should instead use
+ * portable code should never use this for more than 32 bytes.
+ * Performance-sensitive or bulk transfer code should instead use
  * spi_{async,sync}() calls with dma-safe buffers.
  */
 int spi_write_then_read(struct spi_device *spi,
index 312987a0321072aa2c9974c8b476ffc97416b7bb..0ee2b2090252999f7df59f8704ff5e2bcea2ce9a 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
 #include <linux/parport.h>
 
 #include <linux/sched.h>
@@ -40,8 +40,6 @@
  * and use this custom parallel port cable.
  */
 
-#undef HAVE_USI        /* nyet */
-
 
 /* DATA output bits (pins 2..9 == D0..D7) */
 #define        butterfly_nreset (1 << 1)               /* pin 3 */
 #define        spi_sck_bit     (1 << 0)                /* pin 2 */
 #define        spi_mosi_bit    (1 << 7)                /* pin 9 */
 
-#define        usi_sck_bit     (1 << 3)                /* pin 5 */
-#define        usi_mosi_bit    (1 << 4)                /* pin 6 */
-
 #define        vcc_bits        ((1 << 6) | (1 << 5))   /* pins 7, 8 */
 
 /* STATUS input bits */
 #define        spi_miso_bit    PARPORT_STATUS_BUSY     /* pin 11 */
 
-#define        usi_miso_bit    PARPORT_STATUS_PAPEROUT /* pin 12 */
-
 /* CONTROL output bits */
 #define        spi_cs_bit      PARPORT_CONTROL_SELECT  /* pin 17 */
-/* USI uses no chipselect */
 
 
 
@@ -70,15 +62,6 @@ static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
        return spi->controller_data;
 }
 
-static inline int is_usidev(struct spi_device *spi)
-{
-#ifdef HAVE_USI
-       return spi->chip_select != 1;
-#else
-       return 0;
-#endif
-}
-
 
 struct butterfly {
        /* REVISIT ... for now, this must be first */
@@ -97,23 +80,13 @@ struct butterfly {
 
 /*----------------------------------------------------------------------*/
 
-/*
- * these routines may be slower than necessary because they're hiding
- * the fact that there are two different SPI busses on this cable: one
- * to the DataFlash chip (or AVR SPI controller), the other to the
- * AVR USI controller.
- */
-
 static inline void
 setsck(struct spi_device *spi, int is_on)
 {
        struct butterfly        *pp = spidev_to_pp(spi);
        u8                      bit, byte = pp->lastbyte;
 
-       if (is_usidev(spi))
-               bit = usi_sck_bit;
-       else
-               bit = spi_sck_bit;
+       bit = spi_sck_bit;
 
        if (is_on)
                byte |= bit;
@@ -129,10 +102,7 @@ setmosi(struct spi_device *spi, int is_on)
        struct butterfly        *pp = spidev_to_pp(spi);
        u8                      bit, byte = pp->lastbyte;
 
-       if (is_usidev(spi))
-               bit = usi_mosi_bit;
-       else
-               bit = spi_mosi_bit;
+       bit = spi_mosi_bit;
 
        if (is_on)
                byte |= bit;
@@ -148,10 +118,7 @@ static inline int getmiso(struct spi_device *spi)
        int                     value;
        u8                      bit;
 
-       if (is_usidev(spi))
-               bit = usi_miso_bit;
-       else
-               bit = spi_miso_bit;
+       bit = spi_miso_bit;
 
        /* only STATUS_BUSY is NOT negated */
        value = !(parport_read_status(pp->port) & bit);
@@ -166,10 +133,6 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
        if (value != BITBANG_CS_INACTIVE)
                setsck(spi, spi->mode & SPI_CPOL);
 
-       /* no chipselect on this USI link config */
-       if (is_usidev(spi))
-               return;
-
        /* here, value == "activate or not";
         * most PARPORT_CONTROL_* bits are negated, so we must
         * morph it to value == "bit value to write in control register"
@@ -237,24 +200,16 @@ static void butterfly_attach(struct parport *p)
        int                     status;
        struct butterfly        *pp;
        struct spi_master       *master;
-       struct platform_device  *pdev;
+       struct device           *dev = p->physport->dev;
 
-       if (butterfly)
+       if (butterfly || !dev)
                return;
 
        /* REVISIT:  this just _assumes_ a butterfly is there ... no probe,
         * and no way to be selective about what it binds to.
         */
 
-       /* FIXME where should master->cdev.dev come from?
-        * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc
-        * setting up a platform device like this is an ugly kluge...
-        */
-       pdev = platform_device_register_simple("butterfly", -1, NULL, 0);
-       if (IS_ERR(pdev))
-               return;
-
-       master = spi_alloc_master(&pdev->dev, sizeof *pp);
+       master = spi_alloc_master(dev, sizeof *pp);
        if (!master) {
                status = -ENOMEM;
                goto done;
@@ -300,7 +255,7 @@ static void butterfly_attach(struct parport *p)
        parport_frob_control(pp->port, spi_cs_bit, 0);
 
        /* stabilize power with chip in reset (nRESET), and
-        * both spi_sck_bit and usi_sck_bit clear (CPOL=0)
+        * spi_sck_bit clear (CPOL=0)
         */
        pp->lastbyte |= vcc_bits;
        parport_write_data(pp->port, pp->lastbyte);
@@ -334,23 +289,6 @@ static void butterfly_attach(struct parport *p)
                pr_debug("%s: dataflash at %s\n", p->name,
                                pp->dataflash->dev.bus_id);
 
-#ifdef HAVE_USI
-       /* Bus 2 is only for talking to the AVR, and it can work no
-        * matter who masters bus 1; needs appropriate AVR firmware.
-        */
-       pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
-       strcpy(pp->info[1].modalias, "butterfly");
-       // pp->info[1].platform_data = ... TBD ... ;
-       pp->info[1].chip_select = 2,
-       pp->info[1].controller_data = pp;
-       pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]);
-       if (pp->butterfly)
-               pr_debug("%s: butterfly at %s\n", p->name,
-                               pp->butterfly->dev.bus_id);
-
-       /* FIXME setup ACK for the IRQ line ...  */
-#endif
-
        // dev_info(_what?_, ...)
        pr_info("%s: AVR Butterfly\n", p->name);
        butterfly = pp;
@@ -366,14 +304,12 @@ clean1:
 clean0:
        (void) spi_master_put(pp->bitbang.master);
 done:
-       platform_device_unregister(pdev);
        pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
 }
 
 static void butterfly_detach(struct parport *p)
 {
        struct butterfly        *pp;
-       struct platform_device  *pdev;
        int                     status;
 
        /* FIXME this global is ugly ... but, how to quickly get from
@@ -386,7 +322,6 @@ static void butterfly_detach(struct parport *p)
        butterfly = NULL;
 
        /* stop() unregisters child devices too */
-       pdev = to_platform_device(pp->bitbang.master->cdev.dev);
        status = spi_bitbang_stop(&pp->bitbang);
 
        /* turn off VCC */
@@ -397,8 +332,6 @@ static void butterfly_detach(struct parport *p)
        parport_unregister_device(pp->pd);
 
        (void) spi_master_put(pp->bitbang.master);
-
-       platform_device_unregister(pdev);
 }
 
 static struct parport_driver butterfly_driver = {
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
new file mode 100644 (file)
index 0000000..c0a6dce
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+ * spidev.c -- simple synchronous userspace interface to SPI devices
+ *
+ * Copyright (C) 2006 SWAPP
+ *     Andrea Paterniani <a.paterniani@swapp-eng.it>
+ * Copyright (C) 2007 David Brownell (simplification, cleanup)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spidev.h>
+
+#include <asm/uaccess.h>
+
+
+/*
+ * This supports acccess to SPI devices using normal userspace I/O calls.
+ * Note that while traditional UNIX/POSIX I/O semantics are half duplex,
+ * and often mask message boundaries, full SPI support requires full duplex
+ * transfers.  There are several kinds of of internal message boundaries to
+ * handle chipselect management and other protocol options.
+ *
+ * SPI has a character major number assigned.  We allocate minor numbers
+ * dynamically using a bitmask.  You must use hotplug tools, such as udev
+ * (or mdev with busybox) to create and destroy the /dev/spidevB.C device
+ * nodes, since there is no fixed association of minor numbers with any
+ * particular SPI bus or device.
+ */
+#define SPIDEV_MAJOR                   153     /* assigned */
+#define N_SPI_MINORS                   32      /* ... up to 256 */
+
+static unsigned long   minors[N_SPI_MINORS / BITS_PER_LONG];
+
+
+/* Bit masks for spi_device.mode management */
+#define SPI_MODE_MASK                  (SPI_CPHA | SPI_CPOL)
+
+
+struct spidev_data {
+       struct device           dev;
+       struct spi_device       *spi;
+       struct list_head        device_entry;
+
+       struct mutex            buf_lock;
+       unsigned                users;
+       u8                      *buffer;
+};
+
+static LIST_HEAD(device_list);
+static DEFINE_MUTEX(device_list_lock);
+
+static unsigned bufsiz = 4096;
+module_param(bufsiz, uint, S_IRUGO);
+MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
+
+/*-------------------------------------------------------------------------*/
+
+/* Read-only message with current device setup */
+static ssize_t
+spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+       struct spidev_data      *spidev;
+       struct spi_device       *spi;
+       ssize_t                 status = 0;
+
+       /* chipselect only toggles at start or end of operation */
+       if (count > bufsiz)
+               return -EMSGSIZE;
+
+       spidev = filp->private_data;
+       spi = spidev->spi;
+
+       mutex_lock(&spidev->buf_lock);
+       status = spi_read(spi, spidev->buffer, count);
+       if (status == 0) {
+               unsigned long   missing;
+
+               missing = copy_to_user(buf, spidev->buffer, count);
+               if (count && missing == count)
+                       status = -EFAULT;
+               else
+                       status = count - missing;
+       }
+       mutex_unlock(&spidev->buf_lock);
+
+       return status;
+}
+
+/* Write-only message with current device setup */
+static ssize_t
+spidev_write(struct file *filp, const char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       struct spidev_data      *spidev;
+       struct spi_device       *spi;
+       ssize_t                 status = 0;
+       unsigned long           missing;
+
+       /* chipselect only toggles at start or end of operation */
+       if (count > bufsiz)
+               return -EMSGSIZE;
+
+       spidev = filp->private_data;
+       spi = spidev->spi;
+
+       mutex_lock(&spidev->buf_lock);
+       missing = copy_from_user(spidev->buffer, buf, count);
+       if (missing == 0) {
+               status = spi_write(spi, spidev->buffer, count);
+               if (status == 0)
+                       status = count;
+       } else
+               status = -EFAULT;
+       mutex_unlock(&spidev->buf_lock);
+
+       return status;
+}
+
+static int spidev_message(struct spidev_data *spidev,
+               struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
+{
+       struct spi_message      msg;
+       struct spi_transfer     *k_xfers;
+       struct spi_transfer     *k_tmp;
+       struct spi_ioc_transfer *u_tmp;
+       struct spi_device       *spi = spidev->spi;
+       unsigned                n, total;
+       u8                      *buf;
+       int                     status = -EFAULT;
+
+       spi_message_init(&msg);
+       k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
+       if (k_xfers == NULL)
+               return -ENOMEM;
+
+       /* Construct spi_message, copying any tx data to bounce buffer.
+        * We walk the array of user-provided transfers, using each one
+        * to initialize a kernel version of the same transfer.
+        */
+       mutex_lock(&spidev->buf_lock);
+       buf = spidev->buffer;
+       total = 0;
+       for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
+                       n;
+                       n--, k_tmp++, u_tmp++) {
+               k_tmp->len = u_tmp->len;
+
+               if (u_tmp->rx_buf) {
+                       k_tmp->rx_buf = buf;
+                       if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len))
+                               goto done;
+               }
+               if (u_tmp->tx_buf) {
+                       k_tmp->tx_buf = buf;
+                       if (copy_from_user(buf, (const u8 __user *)u_tmp->tx_buf,
+                                       u_tmp->len))
+                               goto done;
+               }
+
+               total += k_tmp->len;
+               if (total > bufsiz) {
+                       status = -EMSGSIZE;
+                       goto done;
+               }
+               buf += k_tmp->len;
+
+               k_tmp->cs_change = !!u_tmp->cs_change;
+               k_tmp->bits_per_word = u_tmp->bits_per_word;
+               k_tmp->delay_usecs = u_tmp->delay_usecs;
+               k_tmp->speed_hz = u_tmp->speed_hz;
+#ifdef VERBOSE
+               dev_dbg(&spi->dev,
+                       "  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
+                       u_tmp->len,
+                       u_tmp->rx_buf ? "rx " : "",
+                       u_tmp->tx_buf ? "tx " : "",
+                       u_tmp->cs_change ? "cs " : "",
+                       u_tmp->bits_per_word ? : spi->bits_per_word,
+                       u_tmp->delay_usecs,
+                       u_tmp->speed_hz ? : spi->max_speed_hz);
+#endif
+               spi_message_add_tail(k_tmp, &msg);
+       }
+
+       status = spi_sync(spi, &msg);
+       if (status < 0)
+               goto done;
+
+       /* copy any rx data out of bounce buffer */
+       buf = spidev->buffer;
+       for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
+               if (u_tmp->rx_buf) {
+                       if (__copy_to_user((u8 __user *)u_tmp->rx_buf, buf,
+                                       u_tmp->len)) {
+                               status = -EFAULT;
+                               goto done;
+                       }
+               }
+               buf += u_tmp->len;
+       }
+       status = total;
+
+done:
+       mutex_unlock(&spidev->buf_lock);
+       kfree(k_xfers);
+       return status;
+}
+
+static int
+spidev_ioctl(struct inode *inode, struct file *filp,
+               unsigned int cmd, unsigned long arg)
+{
+       int                     err = 0;
+       int                     retval = 0;
+       struct spidev_data      *spidev;
+       struct spi_device       *spi;
+       u32                     tmp;
+       unsigned                n_ioc;
+       struct spi_ioc_transfer *ioc;
+
+       /* Check type and command number */
+       if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
+               return -ENOTTY;
+
+       /* Check access direction once here; don't repeat below.
+        * IOC_DIR is from the user perspective, while access_ok is
+        * from the kernel perspective; so they look reversed.
+        */
+       if (_IOC_DIR(cmd) & _IOC_READ)
+               err = !access_ok(VERIFY_WRITE,
+                               (void __user *)arg, _IOC_SIZE(cmd));
+       if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
+               err = !access_ok(VERIFY_READ,
+                               (void __user *)arg, _IOC_SIZE(cmd));
+       if (err)
+               return -EFAULT;
+
+       spidev = filp->private_data;
+       spi = spidev->spi;
+
+       switch (cmd) {
+       /* read requests */
+       case SPI_IOC_RD_MODE:
+               retval = __put_user(spi->mode & SPI_MODE_MASK,
+                                       (__u8 __user *)arg);
+               break;
+       case SPI_IOC_RD_LSB_FIRST:
+               retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
+                                       (__u8 __user *)arg);
+               break;
+       case SPI_IOC_RD_BITS_PER_WORD:
+               retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
+               break;
+       case SPI_IOC_RD_MAX_SPEED_HZ:
+               retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
+               break;
+
+       /* write requests */
+       case SPI_IOC_WR_MODE:
+               retval = __get_user(tmp, (u8 __user *)arg);
+               if (retval == 0) {
+                       u8      save = spi->mode;
+
+                       if (tmp & ~SPI_MODE_MASK) {
+                               retval = -EINVAL;
+                               break;
+                       }
+
+                       tmp |= spi->mode & ~SPI_MODE_MASK;
+                       spi->mode = (u8)tmp;
+                       retval = spi_setup(spi);
+                       if (retval < 0)
+                               spi->mode = save;
+                       else
+                               dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
+               }
+               break;
+       case SPI_IOC_WR_LSB_FIRST:
+               retval = __get_user(tmp, (__u8 __user *)arg);
+               if (retval == 0) {
+                       u8      save = spi->mode;
+
+                       if (tmp)
+                               spi->mode |= SPI_LSB_FIRST;
+                       else
+                               spi->mode &= ~SPI_LSB_FIRST;
+                       retval = spi_setup(spi);
+                       if (retval < 0)
+                               spi->mode = save;
+                       else
+                               dev_dbg(&spi->dev, "%csb first\n",
+                                               tmp ? 'l' : 'm');
+               }
+               break;
+       case SPI_IOC_WR_BITS_PER_WORD:
+               retval = __get_user(tmp, (__u8 __user *)arg);
+               if (retval == 0) {
+                       u8      save = spi->bits_per_word;
+
+                       spi->bits_per_word = tmp;
+                       retval = spi_setup(spi);
+                       if (retval < 0)
+                               spi->bits_per_word = save;
+                       else
+                               dev_dbg(&spi->dev, "%d bits per word\n", tmp);
+               }
+               break;
+       case SPI_IOC_WR_MAX_SPEED_HZ:
+               retval = __get_user(tmp, (__u32 __user *)arg);
+               if (retval == 0) {
+                       u32     save = spi->max_speed_hz;
+
+                       spi->max_speed_hz = tmp;
+                       retval = spi_setup(spi);
+                       if (retval < 0)
+                               spi->max_speed_hz = save;
+                       else
+                               dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
+               }
+               break;
+
+       default:
+               /* segmented and/or full-duplex I/O request */
+               if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
+                               || _IOC_DIR(cmd) != _IOC_WRITE)
+                       return -ENOTTY;
+
+               tmp = _IOC_SIZE(cmd);
+               if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
+                       retval = -EINVAL;
+                       break;
+               }
+               n_ioc = tmp / sizeof(struct spi_ioc_transfer);
+               if (n_ioc == 0)
+                       break;
+
+               /* copy into scratch area */
+               ioc = kmalloc(tmp, GFP_KERNEL);
+               if (!ioc) {
+                       retval = -ENOMEM;
+                       break;
+               }
+               if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
+                       retval = -EFAULT;
+                       break;
+               }
+
+               /* translate to spi_message, execute */
+               retval = spidev_message(spidev, ioc, n_ioc);
+               kfree(ioc);
+               break;
+       }
+       return retval;
+}
+
+static int spidev_open(struct inode *inode, struct file *filp)
+{
+       struct spidev_data      *spidev;
+       int                     status = -ENXIO;
+
+       mutex_lock(&device_list_lock);
+
+       list_for_each_entry(spidev, &device_list, device_entry) {
+               if (spidev->dev.devt == inode->i_rdev) {
+                       status = 0;
+                       break;
+               }
+       }
+       if (status == 0) {
+               if (!spidev->buffer) {
+                       spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
+                       if (!spidev->buffer) {
+                               dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
+                               status = -ENOMEM;
+                       }
+               }
+               if (status == 0) {
+                       spidev->users++;
+                       filp->private_data = spidev;
+                       nonseekable_open(inode, filp);
+               }
+       } else
+               pr_debug("spidev: nothing for minor %d\n", iminor(inode));
+
+       mutex_unlock(&device_list_lock);
+       return status;
+}
+
+static int spidev_release(struct inode *inode, struct file *filp)
+{
+       struct spidev_data      *spidev;
+       int                     status = 0;
+
+       mutex_lock(&device_list_lock);
+       spidev = filp->private_data;
+       filp->private_data = NULL;
+       spidev->users--;
+       if (!spidev->users) {
+               kfree(spidev->buffer);
+               spidev->buffer = NULL;
+       }
+       mutex_unlock(&device_list_lock);
+
+       return status;
+}
+
+static struct file_operations spidev_fops = {
+       .owner =        THIS_MODULE,
+       /* REVISIT switch to aio primitives, so that userspace
+        * gets more complete API coverage.  It'll simplify things
+        * too, except for the locking.
+        */
+       .write =        spidev_write,
+       .read =         spidev_read,
+       .ioctl =        spidev_ioctl,
+       .open =         spidev_open,
+       .release =      spidev_release,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* The main reason to have this class is to make mdev/udev create the
+ * /dev/spidevB.C character device nodes exposing our userspace API.
+ * It also simplifies memory management.
+ */
+
+static void spidev_classdev_release(struct device *dev)
+{
+       struct spidev_data      *spidev;
+
+       spidev = container_of(dev, struct spidev_data, dev);
+       kfree(spidev);
+}
+
+static struct class spidev_class = {
+       .name           = "spidev",
+       .owner          = THIS_MODULE,
+       .dev_release    = spidev_classdev_release,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int spidev_probe(struct spi_device *spi)
+{
+       struct spidev_data      *spidev;
+       int                     status;
+       unsigned long           minor;
+
+       /* Allocate driver data */
+       spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
+       if (!spidev)
+               return -ENOMEM;
+
+       /* Initialize the driver data */
+       spidev->spi = spi;
+       mutex_init(&spidev->buf_lock);
+
+       INIT_LIST_HEAD(&spidev->device_entry);
+
+       /* If we can allocate a minor number, hook up this device.
+        * Reusing minors is fine so long as udev or mdev is working.
+        */
+       mutex_lock(&device_list_lock);
+       minor = find_first_zero_bit(minors, ARRAY_SIZE(minors));
+       if (minor < N_SPI_MINORS) {
+               spidev->dev.parent = &spi->dev;
+               spidev->dev.class = &spidev_class;
+               spidev->dev.devt = MKDEV(SPIDEV_MAJOR, minor);
+               snprintf(spidev->dev.bus_id, sizeof spidev->dev.bus_id,
+                               "spidev%d.%d",
+                               spi->master->bus_num, spi->chip_select);
+               status = device_register(&spidev->dev);
+       } else {
+               dev_dbg(&spi->dev, "no minor number available!\n");
+               status = -ENODEV;
+       }
+       if (status == 0) {
+               set_bit(minor, minors);
+               dev_set_drvdata(&spi->dev, spidev);
+               list_add(&spidev->device_entry, &device_list);
+       }
+       mutex_unlock(&device_list_lock);
+
+       if (status != 0)
+               kfree(spidev);
+
+       return status;
+}
+
+static int spidev_remove(struct spi_device *spi)
+{
+       struct spidev_data      *spidev = dev_get_drvdata(&spi->dev);
+
+       mutex_lock(&device_list_lock);
+
+       list_del(&spidev->device_entry);
+       dev_set_drvdata(&spi->dev, NULL);
+       clear_bit(MINOR(spidev->dev.devt), minors);
+       device_unregister(&spidev->dev);
+
+       mutex_unlock(&device_list_lock);
+
+       return 0;
+}
+
+static struct spi_driver spidev_spi = {
+       .driver = {
+               .name =         "spidev",
+               .owner =        THIS_MODULE,
+       },
+       .probe =        spidev_probe,
+       .remove =       __devexit_p(spidev_remove),
+
+       /* NOTE:  suspend/resume methods are not necessary here.
+        * We don't do anything except pass the requests to/from
+        * the underlying controller.  The refrigerator handles
+        * most issues; the controller driver handles the rest.
+        */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init spidev_init(void)
+{
+       int status;
+
+       /* Claim our 256 reserved device numbers.  Then register a class
+        * that will key udev/mdev to add/remove /dev nodes.  Last, register
+        * the driver which manages those device numbers.
+        */
+       BUILD_BUG_ON(N_SPI_MINORS > 256);
+       status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
+       if (status < 0)
+               return status;
+
+       status = class_register(&spidev_class);
+       if (status < 0) {
+               unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+               return status;
+       }
+
+       status = spi_register_driver(&spidev_spi);
+       if (status < 0) {
+               class_unregister(&spidev_class);
+               unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+       }
+       return status;
+}
+module_init(spidev_init);
+
+static void __exit spidev_exit(void)
+{
+       spi_unregister_driver(&spidev_spi);
+       class_unregister(&spidev_class);
+       unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+}
+module_exit(spidev_exit);
+
+MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
+MODULE_DESCRIPTION("User mode SPI device interface");
+MODULE_LICENSE("GPL");
index 71cb64e41a1bb6721e47c63de681af7baa0655cf..c7b0a357b04a68f309cf0ef783c1d7406e99014b 100644 (file)
@@ -7692,7 +7692,7 @@ static int __init ixj_probe_pci(int *cnt)
        IXJ *j = NULL;
 
        for (i = 0; i < IXJMAX - *cnt; i++) {
-               pci = pci_find_device(PCI_VENDOR_ID_QUICKNET,
+               pci = pci_get_device(PCI_VENDOR_ID_QUICKNET,
                                      PCI_DEVICE_ID_QUICKNET_XJ, pci);
                if (!pci)
                        break;
@@ -7712,6 +7712,7 @@ static int __init ixj_probe_pci(int *cnt)
                        printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase);
                ++*cnt;
        }
+       pci_dev_put(pci);
        return probe;
 }
 
index 9980a4ddfed934617a7726c6c612a24edebb4d27..b847bbc8b0e1a5730bb493ed5644d2a2a278cfe0 100644 (file)
@@ -85,8 +85,6 @@ source "drivers/usb/class/Kconfig"
 
 source "drivers/usb/storage/Kconfig"
 
-source "drivers/usb/input/Kconfig"
-
 source "drivers/usb/image/Kconfig"
 
 source "drivers/usb/net/Kconfig"
index f5de58a63f2bfdac82319fad26e6d616a77c441a..0ef090b1b37c31f761520c1c25fbfad7ac68e0b7 100644 (file)
@@ -23,15 +23,6 @@ obj-$(CONFIG_USB_PRINTER)    += class/
 obj-$(CONFIG_USB_STORAGE)      += storage/
 obj-$(CONFIG_USB)              += storage/
 
-obj-$(CONFIG_USB_ACECAD)       += input/
-obj-$(CONFIG_USB_AIPTEK)       += input/
-obj-$(CONFIG_USB_ATI_REMOTE)   += input/
-obj-$(CONFIG_USB_KBTAB)                += input/
-obj-$(CONFIG_USB_MTOUCH)       += input/
-obj-$(CONFIG_USB_POWERMATE)    += input/
-obj-$(CONFIG_USB_WACOM)                += input/
-obj-$(CONFIG_USB_XPAD)         += input/
-
 obj-$(CONFIG_USB_CATC)         += net/
 obj-$(CONFIG_USB_KAWETH)       += net/
 obj-$(CONFIG_USB_PEGASUS)      += net/
index b3f779f5933a6872bcd691f69d69f7d283b1da66..11e9b15ca45a35fb7c37e84fef91e07c54b2b507 100644 (file)
@@ -77,7 +77,6 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
@@ -1034,7 +1033,7 @@ static int usbatm_do_heavy_init(void *arg)
 
 static int usbatm_heavy_init(struct usbatm_data *instance)
 {
-       int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
+       int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
 
        if (ret < 0) {
                usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
index 14de3b1b6a20699194c60b9cb21c60e1e3aedde3..0081c1d12687de6f8813efb11e0f338c7d7d28a5 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
index 6584cf00f7f31ba7b5bca03023753299ad5733f9..15e740e3a5c47c41bb09340aac5811be1241e09f 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/init.h>
index bde29ab2b5042192115a220b8eeda0982749b2f3..f6b74a678de51f853e639c3fa7bcca80146021fd 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/ioctl.h>
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
index cddfc62c46114bb375094007a62f521d66f123bc..cd4f11157280de78cd5e73e82f043bde7d247182 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/usb.h>
 #include <linux/namei.h>
 #include <linux/usbdevice_fs.h>
-#include <linux/smp_lock.h>
 #include <linux/parser.h>
 #include <linux/notifier.h>
 #include <asm/byteorder.h>
index dfd1b5c87ca3ff69a0404920f1adcbc731d42729..18ddc5e67e39099bc9634e9e4def4232cfc4fdef 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
index 2a6e3163d944765b9addcca1d8520c066327c7f0..ba163f35bf21efd984431d3c3626ed85bab61989 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
index 7d7909cf25583802d2e5a390507fc2d06fb71b24..fcb5526cb085d68658bc936fd93650af9a3e33c4 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 1dd8b57f4420cc7e13db3062c94d5803b60f9083..325bf7cfb83ffd04d76ab3cccf2d984f2618db8c 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 65c91d3735de9ca439b5b36d5c71877aac7e25f4..ae931af05cef303521fbad67bfa858829c1fc359 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 49d737725f7068df54cc8b4022aa3a06c650708d..52779c52b56d97231aecfc5703e062ff68c8c64e 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index e552668d36b323a3ad06941cefe1c66a196b8353..f847c3414be31ac372d42e91ed20451675b6dab1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 8c85e33f74a4b2f5c4cbba4aa7a0ea9630408635..7078374d0b79d0ba36b5b6b297a05e412bf4302b 100644 (file)
@@ -67,7 +67,6 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index c7458f7e56cc51013895b0f53c1ada648cd6b27f..099aff64f5361de4cb87c25bb37e8f45d3afbd98 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 93107453f12408ea4b27ed9d002c2fae5f498474..37b83ba099695d7cc5dc51fb6ebb94ee8e26c8ec 100644 (file)
@@ -97,7 +97,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
        dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
                __LINE__, dev->m_region->lpar_addr);
 
-       result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
+       result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
 
        if (result) {
                dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
@@ -155,7 +155,7 @@ fail_add_hcd:
 fail_ioremap:
        usb_put_hcd(hcd);
 fail_create_hcd:
-       ps3_free_io_irq(virq);
+       ps3_io_irq_destroy(virq);
 fail_irq:
        ps3_free_mmio_region(dev->m_region);
 fail_mmio:
index e8bbe8bc259819c57512bfac4bc8c8ff61ab4505..a66637e725f3e763b11bbc4257ee55bd64a91c0d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 08e237c7bc435bfeca3a33ff35b4a0467de602d4..c43b66acd4d50ab99756138bd0656a0822b82399 100644 (file)
@@ -97,8 +97,8 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
                return -ENODEV;
 
        is_bigendian =
-               device_is_compatible(dn, "ohci-bigendian") ||
-               device_is_compatible(dn, "ohci-be");
+               of_device_is_compatible(dn, "ohci-bigendian") ||
+               of_device_is_compatible(dn, "ohci-be");
 
        dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
 
index c849f72b508a0022f32ae9c414096d542cbf4dd0..d7cf07288b0bdbea54e444e9d7e862349eaf1b8d 100644 (file)
@@ -99,7 +99,7 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
        dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
                __LINE__, dev->m_region->lpar_addr);
 
-       result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
+       result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
 
        if (result) {
                dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
@@ -157,7 +157,7 @@ fail_add_hcd:
 fail_ioremap:
        usb_put_hcd(hcd);
 fail_create_hcd:
-       ps3_free_io_irq(virq);
+       ps3_io_irq_destroy(virq);
 fail_irq:
        ps3_free_mmio_region(dev->m_region);
 fail_mmio:
index 5fa5647ea0951a9b28958060848eb195e67b58b2..4cfa3ff2c993249045d2c08dd570156e22c3ce87 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index a7fa0d75567dcdb995fca738f65878ca30f71f18..ff0dba01f1c7d2129a9830cae777fa3e1f85b938 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/pci_ids.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index d308afd06935b03446c0692102e53ece8603ca3c..36502a06f73af9f3fff9d0bcdb453f4d3c4ced1a 100644 (file)
@@ -94,7 +94,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 
index 896cb2b71020d99f2c61a95721add5dc87e54602..51bd80d2b8ccb4379756b83d6185e175b2bbd4b8 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/proc_fs.h>
 
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
deleted file mode 100644 (file)
index a792e42..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-#
-# USB Input driver configuration
-#
-comment "USB Input Devices"
-       depends on USB
-
-config USB_AIPTEK
-       tristate "Aiptek 6000U/8000U tablet support"
-       depends on USB && INPUT
-       help
-         Say Y here if you want to use the USB version of the Aiptek 6000U
-         or Aiptek 8000U tablet.  Make sure to say Y to "Mouse support"
-         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-         (CONFIG_INPUT_EVDEV) as well.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aiptek.
-
-config USB_WACOM
-       tristate "Wacom Intuos/Graphire tablet support"
-       depends on USB && INPUT
-       help
-         Say Y here if you want to use the USB version of the Wacom Intuos
-         or Graphire tablet.  Make sure to say Y to "Mouse support"
-         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-         (CONFIG_INPUT_EVDEV) as well.
-
-         To compile this driver as a module, choose M here: the
-         module will be called wacom.
-
-config USB_ACECAD
-       tristate "Acecad Flair tablet support"
-       depends on USB && INPUT
-       help
-         Say Y here if you want to use the USB version of the Acecad Flair
-         tablet.  Make sure to say Y to "Mouse support"
-         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-         (CONFIG_INPUT_EVDEV) as well.
-
-         To compile this driver as a module, choose M here: the
-         module will be called acecad.
-
-config USB_KBTAB
-       tristate "KB Gear JamStudio tablet support"
-       depends on USB && INPUT
-       help
-         Say Y here if you want to use the USB version of the KB Gear
-         JamStudio tablet.  Make sure to say Y to "Mouse support"
-         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-         (CONFIG_INPUT_EVDEV) as well.
-
-         To compile this driver as a module, choose M here: the
-         module will be called kbtab.
-
-config USB_POWERMATE
-       tristate "Griffin PowerMate and Contour Jog support"
-       depends on USB && INPUT
-       ---help---
-         Say Y here if you want to use Griffin PowerMate or Contour Jog devices.
-         These are aluminum dials which can measure clockwise and anticlockwise
-         rotation.  The dial also acts as a pushbutton.  The base contains an LED
-         which can be instructed to pulse or to switch to a particular intensity.
-
-         You can download userspace tools from
-         <http://sowerbutts.com/powermate/>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called powermate.
-
-config USB_TOUCHSCREEN
-       tristate "USB Touchscreen Driver"
-       depends on USB && INPUT
-       ---help---
-         USB Touchscreen driver for:
-         - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
-         - PanJit TouchSet USB
-         - 3M MicroTouch USB (EX II series)
-         - ITM
-         - some other eTurboTouch
-         - Gunze AHL61
-         - DMC TSC-10/25
-
-         Have a look at <http://linux.chapter7.ch/touchkit/> for
-         a usage description and the required user-space stuff.
-
-         To compile this driver as a module, choose M here: the
-         module will be called usbtouchscreen.
-
-config USB_TOUCHSCREEN_EGALAX
-       default y
-       bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_PANJIT
-       default y
-       bool "PanJit device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_3M
-       default y
-       bool "3M/Microtouch EX II series device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_ITM
-       default y
-       bool "ITM device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_ETURBO
-       default y
-       bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_GUNZE
-       default y
-       bool "Gunze AHL61 device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_TOUCHSCREEN_DMC_TSC10
-       default y
-       bool "DMC TSC-10/25 device support" if EMBEDDED
-       depends on USB_TOUCHSCREEN
-
-config USB_YEALINK
-       tristate "Yealink usb-p1k voip phone"
-       depends on USB && INPUT && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to enable keyboard and LCD functions of the
-         Yealink usb-p1k usb phones. The audio part is enabled by the generic
-         usb sound driver, so you might want to enable that as well.
-
-         For information about how to use these additional functions, see
-         <file:Documentation/input/yealink.txt>.
-
-         To compile this driver as a module, choose M here: the module will be
-         called yealink.
-
-config USB_XPAD
-       tristate "X-Box gamepad support"
-       depends on USB && INPUT
-       ---help---
-         Say Y here if you want to use the X-Box pad with your computer.
-         Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV)
-         and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well.
-
-         For information about how to connect the X-Box pad to USB, see
-         <file:Documentation/input/xpad.txt>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called xpad.
-         
-config USB_ATI_REMOTE
-       tristate "ATI / X10 USB RF remote control"
-       depends on USB && INPUT
-       ---help---
-         Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
-         These are RF remotes with USB receivers. 
-         The ATI remote comes with many of ATI's All-In-Wonder video cards.
-         The X10 "Lola" remote is available at:
-            <http://www.x10.com/products/lola_sg1.htm>
-         This driver provides mouse pointer, left and right mouse buttons, 
-         and maps all the other remote buttons to keypress events.
-         
-         To compile this driver as a module, choose M here: the module will be
-         called ati_remote.
-
-config USB_ATI_REMOTE2
-       tristate "ATI / Philips USB RF remote control"
-       depends on USB && INPUT
-       ---help---
-         Say Y here if you want to use an ATI or Philips USB RF remote control.
-         These are RF remotes with USB receivers.
-         ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
-         and is also available as a separate product.
-         This driver provides mouse pointer, left and right mouse buttons,
-         and maps all the other remote buttons to keypress events.
-
-         To compile this driver as a module, choose M here: the module will be
-         called ati_remote2.
-
-config USB_KEYSPAN_REMOTE
-       tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
-       depends on USB && INPUT && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to use a Keyspan DMR USB remote control.
-         Currently only the UIA-11 type of receiver has been tested.  The tag
-         on the receiver that connects to the USB port should have a P/N that
-         will tell you what type of DMR you have.  The UIA-10 type is not
-         supported at this time.  This driver maps all buttons to keypress
-         events.
-
-         To compile this driver as a module, choose M here: the module will
-         be called keyspan_remote.
-
-config USB_APPLETOUCH
-       tristate "Apple USB Touchpad support"
-       depends on USB && INPUT
-       ---help---
-         Say Y here if you want to use an Apple USB Touchpad.
-
-         These are the touchpads that can be found on post-February 2005
-         Apple Powerbooks (prior models have a Synaptics touchpad connected
-         to the ADB bus).
-
-         This driver provides a basic mouse driver but can be interfaced
-         with the synaptics X11 driver to provide acceleration and
-         scrolling in X11.
-
-         For further information, see
-         <file:Documentation/input/appletouch.txt>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called appletouch.
-
-config USB_GTCO
-        tristate "GTCO CalComp/InterWrite USB Support"
-        depends on USB && INPUT
-        ---help---
-          Say Y here if you want to use the USB version of the GTCO
-          CalComp/InterWrite Tablet.  Make sure to say Y to "Mouse support"
-          (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-          (CONFIG_INPUT_EVDEV) as well.
-
-          To compile this driver as a module, choose M here: the
-          module will be called gtco.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
deleted file mode 100644 (file)
index 284a073..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Makefile for the USB input drivers
-#
-
-# Multipart objects.
-wacom-objs     := wacom_wac.o wacom_sys.o
-
-obj-$(CONFIG_USB_AIPTEK)       += aiptek.o
-obj-$(CONFIG_USB_ATI_REMOTE)   += ati_remote.o
-obj-$(CONFIG_USB_ATI_REMOTE2)  += ati_remote2.o
-obj-$(CONFIG_USB_KBTAB)                += kbtab.o
-obj-$(CONFIG_USB_KEYSPAN_REMOTE)       += keyspan_remote.o
-obj-$(CONFIG_USB_TOUCHSCREEN)  += usbtouchscreen.o
-obj-$(CONFIG_USB_POWERMATE)    += powermate.o
-obj-$(CONFIG_USB_WACOM)                += wacom.o
-obj-$(CONFIG_USB_ACECAD)       += acecad.o
-obj-$(CONFIG_USB_YEALINK)      += yealink.o
-obj-$(CONFIG_USB_XPAD)         += xpad.o
-obj-$(CONFIG_USB_APPLETOUCH)   += appletouch.o
-obj-$(CONFIG_USB_GTCO)         += gtco.o
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
index b5332e679c4644f86ed1ab0a45459ebf9810b04c..88fb56d5db8f8c2b22a21ceaa51602d72b86827f 100644 (file)
@@ -1307,7 +1307,7 @@ static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp)
 }
 
 
-/* remove a service from the the device
+/* remove a service from the device
    scp->id must be set! */
 static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp)
 {
index 15c70bd048c448cf9baa5b4b6d969d57f43cb611..8d0e360636e64e65ce5db737e9d23a892bf7b9f6 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
index 5dce797bddb7e2369ad41dc3f9bd1661718c201f..1713e19a789974b086fe96cd458136f37df5175f 100644 (file)
@@ -80,7 +80,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
index fdf68479a1664fac31cf09164c2d6946c7fb8b37..88f6abe7362480223f250c514f6868288c029965 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 
 #include "rio500_usb.h"
index 1730d8642a47dd31276b72ac06be26217d58396f..5947afb0017ef49159d4b6558a1b740bd0160a83 100644 (file)
@@ -62,7 +62,6 @@
 #include <linux/selection.h>
 #include <linux/spinlock.h>
 #include <linux/kref.h>
-#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
@@ -322,7 +321,7 @@ sisusbcon_deinit(struct vc_data *c)
 /* interface routine */
 static u8
 sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
-                           u8 blink, u8 underline, u8 reverse)
+                           u8 blink, u8 underline, u8 reverse, u8 unused)
 {
        u8 attr = color;
 
index 8a1df2c9c73eb137a4bdbab9dc53770b4da7fbc8..8977ec0d0f9928218ada7a44fdb62cfd142aa072 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/mutex.h>
 
index cbb53e065d6c198626151f3a9f4235263bd79aa8..82db5a8e528e57b95ad40c369afb31b7298c2aa6 100644 (file)
@@ -129,7 +129,7 @@ extern void usbnet_disconnect(struct usb_interface *);
 
 
 /* Drivers that reuse some of the standard USB CDC infrastructure
- * (notably, using multiple interfaces according to the the CDC
+ * (notably, using multiple interfaces according to the CDC
  * union descriptor) get some helper code.
  */
 struct cdc_state {
index ba5d1dc030369c9a3b3d4b7d29281786da0d4778..3efe67092f15b85c1db4c4a145b83a79270789e6 100644 (file)
@@ -558,7 +558,7 @@ config USB_SERIAL_DEBUG
        tristate "USB Debugging Device"
        depends on USB_SERIAL
        help
-         Say Y here if you have a USB debugging device used to recieve
+         Say Y here if you have a USB debugging device used to receive
          debugging data from another machine.  The most common of these
          devices is the NetChip TurboCONNECT device.
 
index b675735bfbee559718a5fb650bf6dfe814a23a5d..fbc8c27d5d994763b842a718d8df2406a62881e7 100644 (file)
@@ -9,7 +9,7 @@
  * The device works as an standard CDC device, it has 2 interfaces, the first
  * one is for firmware access and the second is the serial one.
  * The protocol is very simply, there are two posibilities reading or writing.
- * When writting the first urb must have a Header that starts with 0x20 0x29 the
+ * When writing the first urb must have a Header that starts with 0x20 0x29 the
  * next two bytes must say how much data will be sended.
  * When reading the process is almost equal except that the header starts with
  * 0x00 0x20.
@@ -18,7 +18,7 @@
  * buffer: The First and Second byte is used for a Header, the Third and Fourth
  * tells the  device the amount of information the package holds.
  * Packages are 60 bytes long Header Stuff.
- * When writting to the device the first two bytes of the header are 0x20 0x29
+ * When writing to the device the first two bytes of the header are 0x20 0x29
  * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange
  * situation, when too much data arrives to the device because it sends the data
  * but with out the header. I will use a simply hack to override this situation,
index 18f74ac7656565ff1ba3607a5ce0155a08ea729f..4807f960150bd389c58127323e3b5fc350dac62f 100644 (file)
@@ -2465,7 +2465,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
            ((edge_serial->is_epic) &&
             (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) &&
             (regNum == MCR))) {
-               dbg("SendCmdWriteUartReg - Not writting to MCR Register");
+               dbg("SendCmdWriteUartReg - Not writing to MCR Register");
                return 0;
        }
 
@@ -2473,7 +2473,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
            ((edge_serial->is_epic) &&
             (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) &&
             (regNum == LCR))) {
-               dbg ("SendCmdWriteUartReg - Not writting to LCR Register");
+               dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
                return 0;
        }
 
index 7639022cdf84af83a74bcf5550abf5e642e527d6..87f378806db645d5d7897e0f56ecb7ceb885e092 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
index 21f3ddbc90805ca6f93f58c514d00fc49e63e320..6dac1ffdde86203ed6972679e0432848d47521d3 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/usb.h>
 #include <linux/usb_usual.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
 #include <scsi/scsi_host.h>
index 344c37595305385360972d27e87d2afc4506f179..9a256d2ff9dc8e18cae69f852c28b9061022b2d2 100644 (file)
@@ -5,6 +5,11 @@
 menu "Graphics support"
 
 source "drivers/video/backlight/Kconfig"
+source "drivers/video/display/Kconfig"
+
+config VGASTATE
+       tristate
+       default n
 
 config FB
        tristate "Support for frame buffer devices"
@@ -90,6 +95,43 @@ config FB_CFB_IMAGEBLIT
          blitting. This is used by drivers that don't provide their own
          (accelerated) version.
 
+config FB_SYS_FILLRECT
+       tristate
+       depends on FB
+       default n
+       ---help---
+         Include the sys_fillrect function for generic software rectangle
+         filling. This is used by drivers that don't provide their own
+         (accelerated) version and the framebuffer is in system RAM.
+
+config FB_SYS_COPYAREA
+       tristate
+       depends on FB
+       default n
+       ---help---
+         Include the sys_copyarea function for generic software area copying.
+         This is used by drivers that don't provide their own (accelerated)
+         version and the framebuffer is in system RAM.
+
+config FB_SYS_IMAGEBLIT
+       tristate
+       depends on FB
+       default n
+       ---help---
+         Include the sys_imageblit function for generic software image
+         blitting. This is used by drivers that don't provide their own
+         (accelerated) version and the framebuffer is in system RAM.
+
+config FB_SYS_FOPS
+       tristate
+       depends on FB
+       default n
+
+config FB_DEFERRED_IO
+       bool
+       depends on FB
+       default y
+
 config FB_SVGALIB
        tristate
        depends on FB
@@ -375,9 +417,10 @@ config FB_FM2
 config FB_ARC
        tristate "Arc Monochrome LCD board support"
        depends on FB && X86
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
        help
          This enables support for the Arc Monochrome LCD board. The board
          is based on the KS-108 lcd controller and is typically a matrix
@@ -475,6 +518,8 @@ config FB_VGA16
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select VGASTATE
+       select FONT_8x16 if FRAMEBUFFER_CONSOLE
        help
          This is the frame buffer device driver for VGA 16 color graphic
          cards. Say Y if you have such a card.
@@ -519,15 +564,25 @@ config FB_HP300
        default y
 
 config FB_TGA
-       tristate "TGA framebuffer support"
-       depends on FB && ALPHA
+       tristate "TGA/SFB+ framebuffer support"
+       depends on FB && (ALPHA || TC)
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select BITREVERSE
-       help
-         This is the frame buffer device driver for generic TGA graphic
-         cards. Say Y if you have one of those.
+       ---help---
+         This is the frame buffer device driver for generic TGA and SFB+
+         graphic cards.  These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
+         also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3
+         TURBOchannel cards, also known as PMAGD-A, -B and -C.
+
+         Due to hardware limitations ZLX-E2 and E3 cards are not supported
+         for DECstation 5000/200 systems.  Additionally due to firmware
+         limitations these cards may cause troubles with booting DECstation
+         5000/240 and /260 systems, but are fully supported under Linux if
+         you manage to get it going. ;-)
+
+         Say Y if you have one of those.
 
 config FB_VESA
        bool "VESA VGA graphics support"
@@ -551,6 +606,21 @@ config FB_IMAC
        help
          This is the frame buffer device driver for the Intel-based Macintosh
 
+config FB_HECUBA
+       tristate "Hecuba board support"
+       depends on FB && X86 && MMU
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
+       select FB_DEFERRED_IO
+       help
+         This enables support for the Hecuba board. This driver was tested
+         with an E-Ink 800x600 display and x86 SBCs through a 16 bit GPIO
+         interface (8 bit data, 4 bit control). If you anticpate using
+         this driver, say Y or M; otherwise say N. You must specify the
+         GPIO IO address to be used for setting control and data.
+
 config FB_HGA
        tristate "Hercules mono graphics support"
        depends on FB && X86
@@ -686,6 +756,7 @@ config FB_NVIDIA
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select BITREVERSE
+       select VGASTATE
        help
          This driver supports graphics boards with the nVidia chips, TNT
          and newer. For very old chipsets, such as the RIVA128, then use
@@ -724,6 +795,7 @@ config FB_RIVA
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select BITREVERSE
+       select VGASTATE
        help
          This driver supports graphics boards with the nVidia Riva/Geforce
          chips.
@@ -770,6 +842,7 @@ config FB_I810
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select VGASTATE
        help
          This driver supports the on-board graphics built in to the Intel 810 
           and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -809,6 +882,22 @@ config FB_I810_I2C
        select FB_DDC
        help
 
+config FB_LE80578
+       tristate "Intel LE80578 (Vermilion) support"
+       depends on FB && PCI && X86
+       select FB_MODE_HELPERS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This driver supports the LE80578 (Vermilion Range) chipset
+
+config FB_CARILLO_RANCH
+       tristate "Intel Carillo Ranch support"
+       depends on FB_LE80578 && FB && PCI && X86
+       help
+         This driver supports the LE80578 (Carillo Ranch) board
+
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
        depends on FB && EXPERIMENTAL && PCI && X86
@@ -1120,6 +1209,8 @@ config FB_S3
        select FB_CFB_IMAGEBLIT
        select FB_TILEBLITTING
        select FB_SVGALIB
+       select VGASTATE
+       select FONT_8x16 if FRAMEBUFFER_CONSOLE
        ---help---
          Driver for graphics boards with S3 Trio / S3 Virge chip.
 
@@ -1130,6 +1221,7 @@ config FB_SAVAGE
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select VGASTATE
        help
          This driver supports notebooks and computers with S3 Savage PCI/AGP
          chips.
@@ -1196,6 +1288,7 @@ config FB_NEOMAGIC
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select VGASTATE
        help
          This driver supports notebooks with NeoMagic PCI chips.
          Say Y if you have such a graphics card. 
@@ -1255,6 +1348,20 @@ config FB_VOODOO1
          Please read the <file:Documentation/fb/README-sstfb.txt> for supported
          options and other important info  support.
 
+config FB_VT8623
+       tristate "VIA VT8623 support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_TILEBLITTING
+       select FB_SVGALIB
+       select VGASTATE
+       select FONT_8x16 if FRAMEBUFFER_CONSOLE
+       ---help---
+         Driver for CastleRock integrated graphics core in the
+         VIA VT8623 [Apollo CLE266] chipset.
+
 config FB_CYBLA
        tristate "Cyberblade/i1 support"
        depends on FB && PCI && X86_32 && !64BIT
@@ -1308,6 +1415,20 @@ config FB_TRIDENT_ACCEL
        This will compile the Trident frame buffer device with
        acceleration functions.
 
+config FB_ARK
+       tristate "ARK 2000PV support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_TILEBLITTING
+       select FB_SVGALIB
+       select VGASTATE
+       select FONT_8x16 if FRAMEBUFFER_CONSOLE
+       ---help---
+         Driver for PCI graphics boards with ARK 2000PV chip
+         and ICS 5342 RAMDAC.
+
 config FB_PM3
        tristate "Permedia3 support"
        depends on FB && PCI && BROKEN
@@ -1662,12 +1783,24 @@ config FB_PS3_DEFAULT_SIZE_M
          The default value can be overridden on the kernel command line
          using the "ps3fb" option (e.g. "ps3fb=9M");
 
-config FB_VIRTUAL
-       tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
-       depends on FB
+config FB_XILINX
+       tristate "Xilinx frame buffer support"
+       depends on FB && XILINX_VIRTEX
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       ---help---
+         Include support for the Xilinx ML300/ML403 reference design
+         framebuffer. ML300 carries a 640*480 LCD display on the board,
+         ML403 uses a standard DB15 VGA connector.
+
+config FB_VIRTUAL
+       tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+       depends on FB
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
        ---help---
          This is a `virtual' frame buffer device. It operates on a chunk of
          unswappable kernel memory instead of on the memory of a graphics
index 558473d040d645cfedbe41c990e42af154d3045b..0b70567458fb266b4c09cf7236ff8952932cb2a3 100644 (file)
@@ -4,6 +4,7 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-y                             += fb_notify.o
 obj-$(CONFIG_FB)                  += fb.o
 fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
@@ -12,14 +13,19 @@ fb-objs                           := $(fb-y)
 
 obj-$(CONFIG_VT)                 += console/
 obj-$(CONFIG_LOGO)               += logo/
-obj-y                            += backlight/
+obj-y                            += backlight/ display/
 
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
 obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SYS_FILLRECT)  += sysfillrect.o
+obj-$(CONFIG_FB_SYS_COPYAREA)  += syscopyarea.o
+obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
+obj-$(CONFIG_FB_SYS_FOPS)      += fb_sys_fops.o
 obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
+obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
@@ -30,7 +36,7 @@ obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)             += pm3fb.o
 
 obj-$(CONFIG_FB_MATROX)                  += matrox/
-obj-$(CONFIG_FB_RIVA)            += riva/ vgastate.o
+obj-$(CONFIG_FB_RIVA)            += riva/
 obj-$(CONFIG_FB_NVIDIA)                  += nvidia/
 obj-$(CONFIG_FB_ATY)             += aty/ macmodes.o
 obj-$(CONFIG_FB_ATY128)                  += aty/ macmodes.o
@@ -40,8 +46,7 @@ obj-$(CONFIG_FB_KYRO)             += kyro/
 obj-$(CONFIG_FB_SAVAGE)                  += savage/
 obj-$(CONFIG_FB_GEODE)           += geode/
 obj-$(CONFIG_FB_MBX)             += mbx/
-obj-$(CONFIG_FB_I810)             += vgastate.o
-obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
+obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o
 obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
@@ -49,9 +54,12 @@ obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o
+obj-$(CONFIG_FB_VT8623)           += vt8623fb.o
 obj-$(CONFIG_FB_CYBLA)            += cyblafb.o
 obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
-obj-$(CONFIG_FB_S3)               += s3fb.o vgastate.o
+obj-$(CONFIG_FB_LE80578)          += vermilion/
+obj-$(CONFIG_FB_S3)               += s3fb.o
+obj-$(CONFIG_FB_ARK)              += arkfb.o
 obj-$(CONFIG_FB_STI)              += stifb.o
 obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
 obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
@@ -66,6 +74,7 @@ obj-$(CONFIG_FB_ACORN)            += acornfb.o
 obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
                                      atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
 obj-$(CONFIG_FB_MAC)              += macfb.o
+obj-$(CONFIG_FB_HECUBA)           += hecubafb.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o
 obj-$(CONFIG_FB_XVR500)           += sunxvr500.o
 obj-$(CONFIG_FB_XVR2500)          += sunxvr2500.o
@@ -102,11 +111,12 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
+obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
 obj-$(CONFIG_FB_IMAC)             += imacfb.o
-obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
 
 # the test framebuffer is last
index 30a8369757e7ceca4b2a82ef49c98f7f9cb05cf3..db15baca3f7b01a6d3d5c934490ffb5b57ab756a 100644 (file)
@@ -262,7 +262,8 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
        ks108_set_yaddr(par, chipindex, upper/8);
 
        linesize = par->info->var.xres/8;
-       src = par->info->screen_base + (left/8) + (upper * linesize);
+       src = (unsigned char __force *) par->info->screen_base + (left/8) +
+               (upper * linesize);
        ks108_set_xaddr(par, chipindex, left);
 
        bitmask=1;
@@ -368,7 +369,7 @@ static void arcfb_fillrect(struct fb_info *info,
 {
        struct arcfb_par *par = info->par;
 
-       cfb_fillrect(info, rect);
+       sys_fillrect(info, rect);
 
        /* update the physical lcd */
        arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
@@ -379,7 +380,7 @@ static void arcfb_copyarea(struct fb_info *info,
 {
        struct arcfb_par *par = info->par;
 
-       cfb_copyarea(info, area);
+       sys_copyarea(info, area);
 
        /* update the physical lcd */
        arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
@@ -389,7 +390,7 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct arcfb_par *par = info->par;
 
-       cfb_imageblit(info, image);
+       sys_imageblit(info, image);
 
        /* update the physical lcd */
        arcfb_lcd_update(par, image->dx, image->dy, image->width,
@@ -439,14 +440,11 @@ static int arcfb_ioctl(struct fb_info *info,
  * the fb. it's inefficient for them to do anything less than 64*8
  * writes since we update the lcd in each write() anyway.
  */
-static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t count,
-                               loff_t *ppos)
+static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
+                          size_t count, loff_t *ppos)
 {
        /* modded from epson 1355 */
 
-       struct inode *inode;
-       int fbidx;
-       struct fb_info *info;
        unsigned long p;
        int err=-EINVAL;
        unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
@@ -454,13 +452,6 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
        unsigned int xres;
 
        p = *ppos;
-       inode = file->f_path.dentry->d_inode;
-       fbidx = iminor(inode);
-       info = registered_fb[fbidx];
-
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
        par = info->par;
        xres = info->var.xres;
        fbmemlength = (xres * info->var.yres)/8;
@@ -477,7 +468,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
        if (count) {
                char *base_addr;
 
-               base_addr = info->screen_base;
+               base_addr = (char __force *)info->screen_base;
                count -= copy_from_user(base_addr + p, buf, count);
                *ppos += count;
                err = -EFAULT;
@@ -503,6 +494,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
 static struct fb_ops arcfb_ops = {
        .owner          = THIS_MODULE,
        .fb_open        = arcfb_open,
+       .fb_read        = fb_sys_read,
        .fb_write       = arcfb_write,
        .fb_release     = arcfb_release,
        .fb_pan_display = arcfb_pan_display,
@@ -603,7 +595,7 @@ static int arcfb_remove(struct platform_device *dev)
 
        if (info) {
                unregister_framebuffer(info);
-               vfree(info->screen_base);
+               vfree((void __force *)info->screen_base);
                framebuffer_release(info);
        }
        return 0;
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
new file mode 100644 (file)
index 0000000..ba6fede
--- /dev/null
@@ -0,0 +1,1200 @@
+/*
+ *  linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
+ *  with ICS 5342 dac (it is easy to add support for different dacs).
+ *
+ *  Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ *  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.
+ *
+ *  Code is based on s3fb
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct arkfb_info {
+       int mclk_freq;
+       int mtrr_reg;
+
+       struct dac_info *dac;
+       struct vgastate state;
+       struct mutex open_lock;
+       unsigned int ref_count;
+       u32 pseudo_palette[16];
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static const struct svga_fb_format arkfb_formats[] = {
+       { 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,   FB_VISUAL_PSEUDOCOLOR, 8, 8},
+       { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 8, 16},
+       { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+               FB_TYPE_INTERLEAVED_PLANES, 1,          FB_VISUAL_PSEUDOCOLOR, 8, 16},
+       { 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 8, 8},
+       {16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},
+       {16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},
+       {24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 8, 8},
+       {32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 2, 2},
+       SVGA_FORMAT_END
+};
+
+
+/* CRT timing register sets */
+
+static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
+static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7  }, VGA_REGSET_END};
+static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
+// const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
+static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
+
+static const struct svga_timing_regs ark_timing_regs     = {
+       ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
+       ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
+       ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
+       ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Module parameters */
+
+static char *mode = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
+
+module_param(mode, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+static int threshold = 4;
+
+module_param(threshold, int, 0644);
+MODULE_PARM_DESC(threshold, "FIFO threshold");
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+       const u8 *font = map->data;
+       u8 __iomem *fb = (u8 __iomem *)info->screen_base;
+       int i, c;
+
+       if ((map->width != 8) || (map->height != 16) ||
+           (map->depth != 1) || (map->length != 256)) {
+               printk(KERN_ERR "fb%d: unsupported font parameters: width %d, "
+                      "height %d, depth %d, length %d\n", info->node,
+                      map->width, map->height, map->depth, map->length);
+               return;
+       }
+
+       fb += 2;
+       for (c = 0; c < map->length; c++) {
+               for (i = 0; i < map->height; i++) {
+                       fb_writeb(font[i], &fb[i * 4]);
+                       fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
+               }
+               fb += 128;
+
+               if ((c % 8) == 7)
+                       fb += 128*8;
+
+               font += map->height;
+       }
+}
+
+static struct fb_tile_ops arkfb_tile_ops = {
+       .fb_settile     = arkfb_settile,
+       .fb_tilecopy    = svga_tilecopy,
+       .fb_tilefill    = svga_tilefill,
+       .fb_tileblit    = svga_tileblit,
+       .fb_tilecursor  = svga_tilecursor,
+       .fb_get_tilemax = svga_get_tilemax,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+       return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       u32 fg = expand_color(image->fg_color);
+       u32 bg = expand_color(image->bg_color);
+       const u8 *src1, *src;
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       u32 val;
+       int x, y;
+
+       src1 = image->data;
+       dst1 = info->screen_base + (image->dy * info->fix.line_length)
+                + ((image->dx / 8) * 4);
+
+       for (y = 0; y < image->height; y++) {
+               src = src1;
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < image->width; x += 8) {
+                       val = *(src++) * 0x01010101;
+                       val = (val & fg) | (~val & bg);
+                       fb_writel(val, dst++);
+               }
+               src1 += image->width / 8;
+               dst1 += info->fix.line_length;
+       }
+
+}
+
+/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       u32 fg = expand_color(rect->color);
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       int x, y;
+
+       dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+                + ((rect->dx / 8) * 4);
+
+       for (y = 0; y < rect->height; y++) {
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < rect->width; x += 8) {
+                       fb_writel(fg, dst++);
+               }
+               dst1 += info->fix.line_length;
+       }
+
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+       return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+               ((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       u32 fg = image->fg_color * 0x11111111;
+       u32 bg = image->bg_color * 0x11111111;
+       const u8 *src1, *src;
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       u32 val;
+       int x, y;
+
+       src1 = image->data;
+       dst1 = info->screen_base + (image->dy * info->fix.line_length)
+                + ((image->dx / 8) * 4);
+
+       for (y = 0; y < image->height; y++) {
+               src = src1;
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < image->width; x += 8) {
+                       val = expand_pixel(*(src++));
+                       val = (val & fg) | (~val & bg);
+                       fb_writel(val, dst++);
+               }
+               src1 += image->width / 8;
+               dst1 += info->fix.line_length;
+       }
+
+}
+
+static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+           && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+               if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+                       arkfb_iplan_imageblit(info, image);
+               else
+                       arkfb_cfb4_imageblit(info, image);
+       } else
+               cfb_imageblit(info, image);
+}
+
+static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       if ((info->var.bits_per_pixel == 4)
+           && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+           && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+               arkfb_iplan_fillrect(info, rect);
+        else
+               cfb_fillrect(info, rect);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+enum
+{
+       DAC_PSEUDO8_8,
+       DAC_RGB1555_8,
+       DAC_RGB0565_8,
+       DAC_RGB0888_8,
+       DAC_RGB8888_8,
+       DAC_PSEUDO8_16,
+       DAC_RGB1555_16,
+       DAC_RGB0565_16,
+       DAC_RGB0888_16,
+       DAC_RGB8888_16,
+       DAC_MAX
+};
+
+struct dac_ops {
+       int (*dac_get_mode)(struct dac_info *info);
+       int (*dac_set_mode)(struct dac_info *info, int mode);
+       int (*dac_get_freq)(struct dac_info *info, int channel);
+       int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
+       void (*dac_release)(struct dac_info *info);
+};
+
+typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
+typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
+
+struct dac_info
+{
+       struct dac_ops *dacops;
+       dac_read_regs_t dac_read_regs;
+       dac_write_regs_t dac_write_regs;
+       void *data;
+};
+
+
+static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
+{
+       u8 code[2] = {reg, 0};
+       info->dac_read_regs(info->data, code, 1);
+       return code[1];
+}
+
+static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
+{
+       info->dac_read_regs(info->data, code, count);
+}
+
+static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
+{
+       u8 code[2] = {reg, val};
+       info->dac_write_regs(info->data, code, 1);
+}
+
+static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
+{
+       info->dac_write_regs(info->data, code, count);
+}
+
+static inline int dac_set_mode(struct dac_info *info, int mode)
+{
+       return info->dacops->dac_set_mode(info, mode);
+}
+
+static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
+{
+       return info->dacops->dac_set_freq(info, channel, freq);
+}
+
+static inline void dac_release(struct dac_info *info)
+{
+       info->dacops->dac_release(info);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* ICS5342 DAC */
+
+struct ics5342_info
+{
+       struct dac_info dac;
+       u8 mode;
+};
+
+#define DAC_PAR(info) ((struct ics5342_info *) info)
+
+/* LSB is set to distinguish unused slots */
+static const u8 ics5342_mode_table[DAC_MAX] = {
+       [DAC_PSEUDO8_8]  = 0x01, [DAC_RGB1555_8]  = 0x21, [DAC_RGB0565_8]  = 0x61,
+       [DAC_RGB0888_8]  = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
+       [DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
+};
+
+static int ics5342_set_mode(struct dac_info *info, int mode)
+{
+       u8 code;
+
+       if (mode >= DAC_MAX)
+               return -EINVAL;
+
+       code = ics5342_mode_table[mode];
+
+       if (! code)
+               return -EINVAL;
+
+       dac_write_reg(info, 6, code & 0xF0);
+       DAC_PAR(info)->mode = mode;
+
+       return 0;
+}
+
+static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
+       60000, 250000, 14318};
+
+/* pd4 - allow only posdivider 4 (r=2) */
+static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
+       60000, 335000, 14318};
+
+/* 270 MHz should be upper bound for VCO clock according to specs,
+   but that is too restrictive in pd4 case */
+
+static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
+{
+       u16 m, n, r;
+
+       /* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
+       int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
+                                 ? &ics5342_pll_pd4 : &ics5342_pll,
+                                 freq, &m, &n, &r, 0);
+
+       if (rv < 0) {
+               return -EINVAL;
+       } else {
+               u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
+               dac_write_regs(info, code, 3);
+               return 0;
+       }
+}
+
+static void ics5342_release(struct dac_info *info)
+{
+       ics5342_set_mode(info, DAC_PSEUDO8_8);
+       kfree(info);
+}
+
+static struct dac_ops ics5342_ops = {
+       .dac_set_mode   = ics5342_set_mode,
+       .dac_set_freq   = ics5342_set_freq,
+       .dac_release    = ics5342_release
+};
+
+
+static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
+{
+       struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
+
+       if (! info)
+               return NULL;
+
+       info->dacops = &ics5342_ops;
+       info->dac_read_regs = drr;
+       info->dac_write_regs = dwr;
+       info->data = data;
+       DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
+       return info;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
+
+static void ark_dac_read_regs(void *data, u8 *code, int count)
+{
+       u8 regval = vga_rseq(NULL, 0x1C);
+
+       while (count != 0)
+       {
+               vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0);
+               code[1] = vga_r(NULL, dac_regs[code[0] & 3]);
+               count--;
+               code += 2;
+       }
+
+       vga_wseq(NULL, 0x1C, regval);
+}
+
+static void ark_dac_write_regs(void *data, u8 *code, int count)
+{
+       u8 regval = vga_rseq(NULL, 0x1C);
+
+       while (count != 0)
+       {
+               vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0);
+               vga_w(NULL, dac_regs[code[0] & 3], code[1]);
+               count--;
+               code += 2;
+       }
+
+       vga_wseq(NULL, 0x1C, regval);
+}
+
+
+static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+       struct arkfb_info *par = info->par;
+       u8 regval;
+
+       int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
+       if (rv < 0) {
+               printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
+               return;
+       }
+
+       /* Set VGA misc register  */
+       regval = vga_r(NULL, VGA_MIS_R);
+       vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+}
+
+
+/* Open framebuffer */
+
+static int arkfb_open(struct fb_info *info, int user)
+{
+       struct arkfb_info *par = info->par;
+
+       mutex_lock(&(par->open_lock));
+       if (par->ref_count == 0) {
+               memset(&(par->state), 0, sizeof(struct vgastate));
+               par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+               par->state.num_crtc = 0x60;
+               par->state.num_seq = 0x30;
+               save_vga(&(par->state));
+       }
+
+       par->ref_count++;
+       mutex_unlock(&(par->open_lock));
+
+       return 0;
+}
+
+/* Close framebuffer */
+
+static int arkfb_release(struct fb_info *info, int user)
+{
+       struct arkfb_info *par = info->par;
+
+       mutex_lock(&(par->open_lock));
+       if (par->ref_count == 0) {
+               mutex_unlock(&(par->open_lock));
+               return -EINVAL;
+       }
+
+       if (par->ref_count == 1) {
+               restore_vga(&(par->state));
+               dac_set_mode(par->dac, DAC_PSEUDO8_8);
+       }
+
+       par->ref_count--;
+       mutex_unlock(&(par->open_lock));
+
+       return 0;
+}
+
+/* Validate passed in var */
+
+static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int rv, mem, step;
+
+       /* Find appropriate format */
+       rv = svga_match_format (arkfb_formats, var, NULL);
+       if (rv < 0)
+       {
+               printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
+               return rv;
+       }
+
+       /* Do not allow to have real resoulution larger than virtual */
+       if (var->xres > var->xres_virtual)
+               var->xres_virtual = var->xres;
+
+       if (var->yres > var->yres_virtual)
+               var->yres_virtual = var->yres;
+
+       /* Round up xres_virtual to have proper alignment of lines */
+       step = arkfb_formats[rv].xresstep - 1;
+       var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+
+       /* Check whether have enough memory */
+       mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+       if (mem > info->screen_size)
+       {
+               printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
+               return -EINVAL;
+       }
+
+       rv = svga_check_timings (&ark_timing_regs, var, info->node);
+       if (rv < 0)
+       {
+               printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
+               return rv;
+       }
+
+       /* Interlaced mode is broken */
+       if (var->vmode & FB_VMODE_INTERLACED)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* Set video mode from par */
+
+static int arkfb_set_par(struct fb_info *info)
+{
+       struct arkfb_info *par = info->par;
+       u32 value, mode, hmul, hdiv, offset_value, screen_size;
+       u32 bpp = info->var.bits_per_pixel;
+       u8 regval;
+
+       if (bpp != 0) {
+               info->fix.ypanstep = 1;
+               info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+               info->flags &= ~FBINFO_MISC_TILEBLITTING;
+               info->tileops = NULL;
+
+               /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+               info->pixmap.blit_y = ~(u32)0;
+
+               offset_value = (info->var.xres_virtual * bpp) / 64;
+               screen_size = info->var.yres_virtual * info->fix.line_length;
+       } else {
+               info->fix.ypanstep = 16;
+               info->fix.line_length = 0;
+
+               info->flags |= FBINFO_MISC_TILEBLITTING;
+               info->tileops = &arkfb_tile_ops;
+
+               /* supports 8x16 tiles only */
+               info->pixmap.blit_x = 1 << (8 - 1);
+               info->pixmap.blit_y = 1 << (16 - 1);
+
+               offset_value = info->var.xres_virtual / 16;
+               screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+       }
+
+       info->var.xoffset = 0;
+       info->var.yoffset = 0;
+       info->var.activate = FB_ACTIVATE_NOW;
+
+       /* Unlock registers */
+       svga_wcrt_mask(0x11, 0x00, 0x80);
+
+       /* Blank screen and turn off sync */
+       svga_wseq_mask(0x01, 0x20, 0x20);
+       svga_wcrt_mask(0x17, 0x00, 0x80);
+
+       /* Set default values */
+       svga_set_default_gfx_regs();
+       svga_set_default_atc_regs();
+       svga_set_default_seq_regs();
+       svga_set_default_crt_regs();
+       svga_wcrt_multi(ark_line_compare_regs, 0xFFFFFFFF);
+       svga_wcrt_multi(ark_start_address_regs, 0);
+
+       /* ARK specific initialization */
+       svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
+       svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
+
+       vga_wseq(NULL, 0x13, info->fix.smem_start >> 16);
+       vga_wseq(NULL, 0x14, info->fix.smem_start >> 24);
+       vga_wseq(NULL, 0x15, 0);
+       vga_wseq(NULL, 0x16, 0);
+
+       /* Set the FIFO threshold register */
+       /* It is fascinating way to store 5-bit value in 8-bit register */
+       regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
+       vga_wseq(NULL, 0x18, regval);
+
+       /* Set the offset register */
+       pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
+       svga_wcrt_multi(ark_offset_regs, offset_value);
+
+       /* fix for hi-res textmode */
+       svga_wcrt_mask(0x40, 0x08, 0x08);
+
+       if (info->var.vmode & FB_VMODE_DOUBLE)
+               svga_wcrt_mask(0x09, 0x80, 0x80);
+       else
+               svga_wcrt_mask(0x09, 0x00, 0x80);
+
+       if (info->var.vmode & FB_VMODE_INTERLACED)
+               svga_wcrt_mask(0x44, 0x04, 0x04);
+       else
+               svga_wcrt_mask(0x44, 0x00, 0x04);
+
+       hmul = 1;
+       hdiv = 1;
+       mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
+
+       /* Set mode-specific register values */
+       switch (mode) {
+       case 0:
+               pr_debug("fb%d: text mode\n", info->node);
+               svga_set_textmode_vga_regs();
+
+               vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
+               svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
+               dac_set_mode(par->dac, DAC_PSEUDO8_8);
+
+               break;
+       case 1:
+               pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
+               vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
+
+               vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
+               svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
+               dac_set_mode(par->dac, DAC_PSEUDO8_8);
+               break;
+       case 2:
+               pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
+               svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
+               dac_set_mode(par->dac, DAC_PSEUDO8_8);
+               break;
+       case 3:
+               pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */
+
+               if (info->var.pixclock > 20000) {
+                       pr_debug("fb%d: not using multiplex\n", info->node);
+                       svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
+                       dac_set_mode(par->dac, DAC_PSEUDO8_8);
+               } else {
+                       pr_debug("fb%d: using multiplex\n", info->node);
+                       svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
+                       dac_set_mode(par->dac, DAC_PSEUDO8_16);
+                       hdiv = 2;
+               }
+               break;
+       case 4:
+               pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */
+               svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
+               dac_set_mode(par->dac, DAC_RGB1555_16);
+               break;
+       case 5:
+               pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */
+               svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
+               dac_set_mode(par->dac, DAC_RGB0565_16);
+               break;
+       case 6:
+               pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */
+               svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
+               dac_set_mode(par->dac, DAC_RGB0888_16);
+               hmul = 3;
+               hdiv = 2;
+               break;
+       case 7:
+               pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
+
+               vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */
+               svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
+               dac_set_mode(par->dac, DAC_RGB8888_16);
+               hmul = 2;
+               break;
+       default:
+               printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
+               return -EINVAL;
+       }
+
+       ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
+       svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv,
+                        (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
+                        (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
+                         hmul, info->node);
+
+       /* Set interlaced mode start/end register */
+       value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
+       value = ((value * hmul / hdiv) / 8) - 5;
+       vga_wcrt(NULL, 0x42, (value + 1) / 2);
+
+       memset_io(info->screen_base, 0x00, screen_size);
+       /* Device and screen back on */
+       svga_wcrt_mask(0x17, 0x80, 0x80);
+       svga_wseq_mask(0x01, 0x00, 0x20);
+
+       return 0;
+}
+
+/* Set a colour register */
+
+static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                               u_int transp, struct fb_info *fb)
+{
+       switch (fb->var.bits_per_pixel) {
+       case 0:
+       case 4:
+               if (regno >= 16)
+                       return -EINVAL;
+
+               if ((fb->var.bits_per_pixel == 4) &&
+                   (fb->var.nonstd == 0)) {
+                       outb(0xF0, VGA_PEL_MSK);
+                       outb(regno*16, VGA_PEL_IW);
+               } else {
+                       outb(0x0F, VGA_PEL_MSK);
+                       outb(regno, VGA_PEL_IW);
+               }
+               outb(red >> 10, VGA_PEL_D);
+               outb(green >> 10, VGA_PEL_D);
+               outb(blue >> 10, VGA_PEL_D);
+               break;
+       case 8:
+               if (regno >= 256)
+                       return -EINVAL;
+
+               outb(0xFF, VGA_PEL_MSK);
+               outb(regno, VGA_PEL_IW);
+               outb(red >> 10, VGA_PEL_D);
+               outb(green >> 10, VGA_PEL_D);
+               outb(blue >> 10, VGA_PEL_D);
+               break;
+       case 16:
+               if (regno >= 16)
+                       return 0;
+
+               if (fb->var.green.length == 5)
+                       ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+                               ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+               else if (fb->var.green.length == 6)
+                       ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+                               ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+               else
+                       return -EINVAL;
+               break;
+       case 24:
+       case 32:
+               if (regno >= 16)
+                       return 0;
+
+               ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
+                       (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Set the display blanking state */
+
+static int arkfb_blank(int blank_mode, struct fb_info *info)
+{
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               pr_debug("fb%d: unblank\n", info->node);
+               svga_wseq_mask(0x01, 0x00, 0x20);
+               svga_wcrt_mask(0x17, 0x80, 0x80);
+               break;
+       case FB_BLANK_NORMAL:
+               pr_debug("fb%d: blank\n", info->node);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               svga_wcrt_mask(0x17, 0x80, 0x80);
+               break;
+       case FB_BLANK_POWERDOWN:
+       case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_VSYNC_SUSPEND:
+               pr_debug("fb%d: sync down\n", info->node);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               svga_wcrt_mask(0x17, 0x00, 0x80);
+               break;
+       }
+       return 0;
+}
+
+
+/* Pan the display */
+
+static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       unsigned int offset;
+
+       /* Calculate the offset */
+       if (var->bits_per_pixel == 0) {
+               offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+               offset = offset >> 2;
+       } else {
+               offset = (var->yoffset * info->fix.line_length) +
+                        (var->xoffset * var->bits_per_pixel / 8);
+               offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3);
+       }
+
+       /* Set the offset */
+       svga_wcrt_multi(ark_start_address_regs, offset);
+
+       return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Frame buffer operations */
+
+static struct fb_ops arkfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open        = arkfb_open,
+       .fb_release     = arkfb_release,
+       .fb_check_var   = arkfb_check_var,
+       .fb_set_par     = arkfb_set_par,
+       .fb_setcolreg   = arkfb_setcolreg,
+       .fb_blank       = arkfb_blank,
+       .fb_pan_display = arkfb_pan_display,
+       .fb_fillrect    = arkfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = arkfb_imageblit,
+       .fb_get_caps    = svga_get_caps,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* PCI probe */
+static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct fb_info *info;
+       struct arkfb_info *par;
+       int rc;
+       u8 regval;
+
+       /* Ignore secondary VGA device because there is no VGA arbitration */
+       if (! svga_primary_device(dev)) {
+               dev_info(&(dev->dev), "ignoring secondary device\n");
+               return -ENODEV;
+       }
+
+       /* Allocate and fill driver data structure */
+       info = framebuffer_alloc(sizeof(struct arkfb_info), NULL);
+       if (! info) {
+               dev_err(&(dev->dev), "cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       par = info->par;
+       mutex_init(&par->open_lock);
+
+       info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+       info->fbops = &arkfb_ops;
+
+       /* Prepare PCI device */
+       rc = pci_enable_device(dev);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot enable PCI device\n");
+               goto err_enable_device;
+       }
+
+       rc = pci_request_regions(dev, "arkfb");
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
+               goto err_request_regions;
+       }
+
+       par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
+       if (! par->dac) {
+               rc = -ENOMEM;
+               dev_err(&(dev->dev), "RAMDAC initialization failed\n");
+               goto err_dac;
+       }
+
+       info->fix.smem_start = pci_resource_start(dev, 0);
+       info->fix.smem_len = pci_resource_len(dev, 0);
+
+       /* Map physical IO memory address into kernel space */
+       info->screen_base = pci_iomap(dev, 0, 0);
+       if (! info->screen_base) {
+               rc = -ENOMEM;
+               dev_err(&(dev->dev), "iomap for framebuffer failed\n");
+               goto err_iomap;
+       }
+
+       /* FIXME get memsize */
+       regval = vga_rseq(NULL, 0x10);
+       info->screen_size = (1 << (regval >> 6)) << 20;
+       info->fix.smem_len = info->screen_size;
+
+       strcpy(info->fix.id, "ARK 2000PV");
+       info->fix.mmio_start = 0;
+       info->fix.mmio_len = 0;
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+       info->fix.ypanstep = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+       info->pseudo_palette = (void*) (par->pseudo_palette);
+
+       /* Prepare startup mode */
+       rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
+       if (! ((rc == 1) || (rc == 2))) {
+               rc = -EINVAL;
+               dev_err(&(dev->dev), "mode %s not found\n", mode);
+               goto err_find_mode;
+       }
+
+       rc = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot allocate colormap\n");
+               goto err_alloc_cmap;
+       }
+
+       rc = register_framebuffer(info);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot register framebugger\n");
+               goto err_reg_fb;
+       }
+
+       printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id,
+                pci_name(dev), info->fix.smem_len >> 20);
+
+       /* Record a reference to the driver data */
+       pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+       if (mtrr) {
+               par->mtrr_reg = -1;
+               par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+       }
+#endif
+
+       return 0;
+
+       /* Error handling */
+err_reg_fb:
+       fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+       pci_iounmap(dev, info->screen_base);
+err_iomap:
+       dac_release(par->dac);
+err_dac:
+       pci_release_regions(dev);
+err_request_regions:
+/*     pci_disable_device(dev); */
+err_enable_device:
+       framebuffer_release(info);
+       return rc;
+}
+
+/* PCI remove */
+
+static void __devexit ark_pci_remove(struct pci_dev *dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct arkfb_info *par = info->par;
+
+       if (info) {
+#ifdef CONFIG_MTRR
+               if (par->mtrr_reg >= 0) {
+                       mtrr_del(par->mtrr_reg, 0, 0);
+                       par->mtrr_reg = -1;
+               }
+#endif
+
+               dac_release(par->dac);
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+
+               pci_iounmap(dev, info->screen_base);
+               pci_release_regions(dev);
+/*             pci_disable_device(dev); */
+
+               pci_set_drvdata(dev, NULL);
+               framebuffer_release(info);
+       }
+}
+
+
+#ifdef CONFIG_PM
+/* PCI suspend */
+
+static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct arkfb_info *par = info->par;
+
+       dev_info(&(dev->dev), "suspend\n");
+
+       acquire_console_sem();
+       mutex_lock(&(par->open_lock));
+
+       if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+               mutex_unlock(&(par->open_lock));
+               release_console_sem();
+               return 0;
+       }
+
+       fb_set_suspend(info, 1);
+
+       pci_save_state(dev);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+
+       mutex_unlock(&(par->open_lock));
+       release_console_sem();
+
+       return 0;
+}
+
+
+/* PCI resume */
+
+static int ark_pci_resume (struct pci_dev* dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct arkfb_info *par = info->par;
+
+       dev_info(&(dev->dev), "resume\n");
+
+       acquire_console_sem();
+       mutex_lock(&(par->open_lock));
+
+       if (par->ref_count == 0) {
+               mutex_unlock(&(par->open_lock));
+               release_console_sem();
+               return 0;
+       }
+
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       if (pci_enable_device(dev))
+               goto fail;
+
+       pci_set_master(dev);
+
+       arkfb_set_par(info);
+       fb_set_suspend(info, 0);
+
+       mutex_unlock(&(par->open_lock));
+fail:
+       release_console_sem();
+       return 0;
+}
+#else
+#define ark_pci_suspend NULL
+#define ark_pci_resume NULL
+#endif /* CONFIG_PM */
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id ark_devices[] __devinitdata = {
+       {PCI_DEVICE(0xEDD8, 0xA099)},
+       {0, 0, 0, 0, 0, 0, 0}
+};
+
+
+MODULE_DEVICE_TABLE(pci, ark_devices);
+
+static struct pci_driver arkfb_pci_driver = {
+       .name           = "arkfb",
+       .id_table       = ark_devices,
+       .probe          = ark_pci_probe,
+       .remove         = __devexit_p(ark_pci_remove),
+       .suspend        = ark_pci_suspend,
+       .resume         = ark_pci_resume,
+};
+
+/* Cleanup */
+
+static void __exit arkfb_cleanup(void)
+{
+       pr_debug("arkfb: cleaning up\n");
+       pci_unregister_driver(&arkfb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init arkfb_init(void)
+{
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("arkfb", &option))
+               return -ENODEV;
+
+       if (option && *option)
+               mode = option;
+#endif
+
+       pr_debug("arkfb: initializing\n");
+       return pci_register_driver(&arkfb_pci_driver);
+}
+
+module_init(arkfb_init);
+module_exit(arkfb_cleanup);
index 39ab483fc25011112f7a47898c56716c3be30b43..90e7df22f508a8dc992c133ee1f6dfb6d0fe0685 100644 (file)
 #define PCI_CHIP_R423_5D57              0x5D57
 #define PCI_CHIP_RS350_7834             0x7834
 #define PCI_CHIP_RS350_7835             0x7835
-
+#define PCI_CHIP_RS480_5955             0x5955
index e86d7e0c98254eaa3af3370e52d789b437a765c8..7fea4d8ae8e2a59719c6db6d918c9f77d79531a8 100644 (file)
@@ -2165,18 +2165,29 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
 static int aty128fb_blank(int blank, struct fb_info *fb)
 {
        struct aty128fb_par *par = fb->par;
-       u8 state = 0;
+       u8 state;
 
        if (par->lock_blank || par->asleep)
                return 0;
 
-       if (blank & FB_BLANK_VSYNC_SUSPEND)
-               state |= 2;
-       if (blank & FB_BLANK_HSYNC_SUSPEND)
-               state |= 1;
-       if (blank & FB_BLANK_POWERDOWN)
-               state |= 4;
-
+       switch (blank) {
+       case FB_BLANK_NORMAL:
+               state = 4;
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               state = 6;
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               state = 5;
+               break;
+       case FB_BLANK_POWERDOWN:
+               state = 7;
+               break;
+       case FB_BLANK_UNBLANK:
+       default:
+               state = 0;
+               break;
+       }
        aty_st_8(CRTC_EXT_CNTL+1, state);
 
        if (par->chip_gen == rage_M3) {
@@ -2430,7 +2441,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        wait_for_idle(par);
 
        /* Blank display and LCD */
-       aty128fb_blank(VESA_POWERDOWN, info);
+       aty128fb_blank(FB_BLANK_POWERDOWN, info);
 
        /* Sleep */
        par->asleep = 1;
index 8514f2a6f060ccd0d578e10df3ef16ae9b6793bc..8d3455da663aa6261545e6368e5fab78f8edd081 100644 (file)
@@ -80,8 +80,9 @@
 #include "../macmodes.h"
 #endif
 #ifdef __sparc__
-#include <asm/pbm.h>
 #include <asm/fbio.h>
+#include <asm/oplib.h>
+#include <asm/prom.h>
 #endif
 
 #ifdef CONFIG_ADB_PMU
@@ -2297,20 +2298,6 @@ static int __devinit aty_init(struct fb_info *info)
                par->pll_limits.xclk = 53;
        }
 #endif
-       if (pll)
-               par->pll_limits.pll_max = pll;
-       if (mclk)
-               par->pll_limits.mclk = mclk;
-       if (xclk)
-               par->pll_limits.xclk = xclk;
-
-       aty_calc_mem_refresh(par, par->pll_limits.xclk);
-       par->pll_per = 1000000/par->pll_limits.pll_max;
-       par->mclk_per = 1000000/par->pll_limits.mclk;
-       par->xclk_per = 1000000/par->pll_limits.xclk;
-
-       par->ref_clk_per = 1000000000000ULL / 14318180;
-       xtal = "14.31818";
 
 #ifdef CONFIG_FB_ATY_GX
        if (!M64_HAS(INTEGRATED)) {
@@ -2338,6 +2325,7 @@ static int __devinit aty_init(struct fb_info *info)
                case DAC_IBMRGB514:
                        par->dac_ops = &aty_dac_ibm514;
                        break;
+#ifdef CONFIG_ATARI
                case DAC_ATI68860_B:
                case DAC_ATI68860_C:
                        par->dac_ops = &aty_dac_ati68860b;
@@ -2346,6 +2334,7 @@ static int __devinit aty_init(struct fb_info *info)
                case DAC_ATT21C498:
                        par->dac_ops = &aty_dac_att21c498;
                        break;
+#endif
                default:
                        PRINTKI("aty_init: DAC type not implemented yet!\n");
                        par->dac_ops = &aty_dac_unsupported;
@@ -2389,8 +2378,29 @@ static int __devinit aty_init(struct fb_info *info)
                /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
                if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
                        par->pll_limits.mclk = 63;
+               /* Mobility + 32bit memory interface need halved XCLK. */
+               if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32)
+                       par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
        }
+#endif
 
+       /* Allow command line to override clocks. */
+       if (pll)
+               par->pll_limits.pll_max = pll;
+       if (mclk)
+               par->pll_limits.mclk = mclk;
+       if (xclk)
+               par->pll_limits.xclk = xclk;
+
+       aty_calc_mem_refresh(par, par->pll_limits.xclk);
+       par->pll_per = 1000000/par->pll_limits.pll_max;
+       par->mclk_per = 1000000/par->pll_limits.mclk;
+       par->xclk_per = 1000000/par->pll_limits.xclk;
+
+       par->ref_clk_per = 1000000000000ULL / 14318180;
+       xtal = "14.31818";
+
+#ifdef CONFIG_FB_ATY_CT
        if (M64_HAS(GTB_DSP)) {
                u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
 
index 1fdcfdbf669b2a26f770af8d4b5816479f8f6f86..cc9e9779b75f753fd9f937d845ca7a5cd7b415a8 100644 (file)
@@ -608,12 +608,10 @@ static void aty_resume_pll_ct(const struct fb_info *info,
                aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
                aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
                /*
-                * The sclk has been started. However, I believe the first clock
-                * ticks it generates are not very stable. Hope this primitive loop
-                * helps for Rage Mobilities that sometimes crash when
-                * we switch to sclk. (Daniel Mantione, 13-05-2003)
+                * SCLK has been started. Wait for the PLL to lock. 5 ms
+                * should be enough according to mach64 programmer's guide.
                 */
-               udelay(500);
+               mdelay(5);
        }
 
        aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
index 2a7f381c330feb102bc17e0a4332e52205fc0ae3..fe2c6ad01a8d1ffaeb096262b70baafac86eede1 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/uaccess.h>
 
 #ifdef __sparc__
-#include <asm/pbm.h>
 #include <asm/fbio.h>
 #endif
 
index a4b3fd185de7618113a7bd43d33553f0afc1574b..2ce05019301892d9a0420f97ef2b803f8742100a 100644 (file)
        { PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
 
 static struct pci_device_id radeonfb_pci_table[] = {
+        /* Radeon Xpress 200m */
+       CHIP_DEF(PCI_CHIP_RS480_5955,   RS480,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
        /* Mobility M6 */
        CHIP_DEF(PCI_CHIP_RADEON_LY,    RV100,  CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
        CHIP_DEF(PCI_CHIP_RADEON_LZ,    RV100,  CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
@@ -422,7 +424,7 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
 
        if (dp == NULL)
                return -ENODEV;
-       val = get_property(dp, "ATY,RefCLK", NULL);
+       val = of_get_property(dp, "ATY,RefCLK", NULL);
        if (!val || !*val) {
                printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
                return -EINVAL;
@@ -430,11 +432,11 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
 
        rinfo->pll.ref_clk = (*val) / 10;
 
-       val = get_property(dp, "ATY,SCLK", NULL);
+       val = of_get_property(dp, "ATY,SCLK", NULL);
        if (val && *val)
                rinfo->pll.sclk = (*val) / 10;
 
-       val = get_property(dp, "ATY,MCLK", NULL);
+       val = of_get_property(dp, "ATY,MCLK", NULL);
        if (val && *val)
                rinfo->pll.mclk = (*val) / 10;
 
@@ -1994,7 +1996,8 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
        /* framebuffer size */
         if ((rinfo->family == CHIP_FAMILY_RS100) ||
             (rinfo->family == CHIP_FAMILY_RS200) ||
-            (rinfo->family == CHIP_FAMILY_RS300)) {
+            (rinfo->family == CHIP_FAMILY_RS300) ||
+           (rinfo->family == CHIP_FAMILY_RS480) ) {
           u32 tom = INREG(NB_TOM);
           tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
 
index 737b5c09dbdb64684fec83e5c738abed60ebb9d7..2030ed813429f802114fff22ff4919aabc858f26 100644 (file)
@@ -70,7 +70,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
         int i, mt = MT_NONE;  
        
        RTRACE("analyzing OF properties...\n");
-       pmt = get_property(dp, "display-type", NULL);
+       pmt = of_get_property(dp, "display-type", NULL);
        if (!pmt)
                return MT_NONE;
        RTRACE("display-type: %s\n", pmt);
@@ -89,7 +89,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
        }
 
        for (i = 0; propnames[i] != NULL; ++i) {
-               pedid = get_property(dp, propnames[i], NULL);
+               pedid = of_get_property(dp, propnames[i], NULL);
                if (pedid != NULL)
                        break;
        }
@@ -98,9 +98,10 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
         * single-head cards have hdno == -1 and skip this step
         */
        if (pedid == NULL && dp->parent && (hdno != -1))
-               pedid = get_property(dp->parent, (hdno == 0) ? "EDID1" : "EDID2", NULL);
+               pedid = of_get_property(dp->parent,
+                               (hdno == 0) ? "EDID1" : "EDID2", NULL);
        if (pedid == NULL && dp->parent && (hdno == 0))
-               pedid = get_property(dp->parent, "EDID", NULL);
+               pedid = of_get_property(dp->parent, "EDID", NULL);
        if (pedid == NULL)
                return mt;
 
@@ -130,7 +131,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
                do {
                        if (!dp)
                                return MT_NONE;
-                       pname = get_property(dp, "name", NULL);
+                       pname = of_get_property(dp, "name", NULL);
                        if (!pname)
                                return MT_NONE;
                        len = strlen(pname);
index c411293cefc8a9bb3a88ca46f5abf0b185cf4b3b..be1d57bf9dc8f82c7c9f6b4ea62b35bdf6d43be7 100644 (file)
@@ -1290,7 +1290,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
                if (rinfo->of_node != NULL) {
                        int size;
 
-                       mrtable = get_property(rinfo->of_node, "ATY,MRT", &size);
+                       mrtable = of_get_property(rinfo->of_node, "ATY,MRT", &size);
                        if (mrtable)
                                mrtable_size = size >> 2;
                        else
@@ -2826,11 +2826,15 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis
        rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
 
        /* Enable/Disable dynamic clocks: TODO add sysfs access */
-       rinfo->dynclk = dynclk;
-       if (dynclk == 1) {
+       if (rinfo->family == CHIP_FAMILY_RS480)
+               rinfo->dynclk = -1;
+       else
+               rinfo->dynclk = dynclk;
+
+       if (rinfo->dynclk == 1) {
                radeon_pm_enable_dynamic_mode(rinfo);
                printk("radeonfb: Dynamic Clock Power Management enabled\n");
-       } else if (dynclk == 0) {
+       } else if (rinfo->dynclk == 0) {
                radeon_pm_disable_dynamic_mode(rinfo);
                printk("radeonfb: Dynamic Clock Power Management disabled\n");
        }
index 319000360285a9d2d70226aa1c53c409a52af8df..7ebffcdfd1e38e67d64b155dc8abf4d706ec11dd 100644 (file)
@@ -48,6 +48,7 @@ enum radeon_family {
        CHIP_FAMILY_RV350,
        CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
        CHIP_FAMILY_R420,     /* R420/R423/M18 */
+       CHIP_FAMILY_RS480,
        CHIP_FAMILY_LAST,
 };
 
@@ -64,7 +65,8 @@ enum radeon_family {
                                ((rinfo)->family == CHIP_FAMILY_RV350) || \
                                ((rinfo)->family == CHIP_FAMILY_R350)  || \
                                ((rinfo)->family == CHIP_FAMILY_RV380) || \
-                               ((rinfo)->family == CHIP_FAMILY_R420))
+                               ((rinfo)->family == CHIP_FAMILY_R420)  || \
+                               ((rinfo)->family == CHIP_FAMILY_RS480) )
 
 /*
  * Chip flags
index 47d15b5d985a0ce3f124a7d83cf3a7e7a8fd82e5..fbef663fc0571988001fa848a11b460020035972 100644 (file)
@@ -63,3 +63,11 @@ config BACKLIGHT_PROGEAR
        help
          If you have a Frontpath ProGear say Y to enable the
          backlight driver.
+
+config BACKLIGHT_CARILLO_RANCH
+       tristate "Intel Carillo Ranch Backlight Driver"
+       depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578
+       default n
+       help
+         If you have a Intel LE80578 (Carillo Ranch) say Y to enable the
+         backlight driver.
index 0c3ce46f50949d17971d91dfa8b92f8441aa92a3..c6e2266f63e2d6d7f728f196d31b65864d8699f5 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_BACKLIGHT_CORGI)   += corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)  += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
 obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
+obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
new file mode 100644 (file)
index 0000000..e9bbc34
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Carillo Ranch video subsystem driver.
+ * The Carillo Ranch video subsystem driver 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.
+ *
+ * The Carillo Ranch video subsystem driver 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 driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+/* The LVDS- and panel power controls sits on the
+ * GPIO port of the ISA bridge.
+ */
+
+#define CRVML_DEVICE_LPC    0x27B8
+#define CRVML_REG_GPIOBAR   0x48
+#define CRVML_REG_GPIOEN    0x4C
+#define CRVML_GPIOEN_BIT    (1 << 4)
+#define CRVML_PANEL_PORT    0x38
+#define CRVML_LVDS_ON       0x00000001
+#define CRVML_PANEL_ON      0x00000002
+#define CRVML_BACKLIGHT_OFF 0x00000004
+
+/* The PLL Clock register sits on Host bridge */
+#define CRVML_DEVICE_MCH   0x5001
+#define CRVML_REG_MCHBAR   0x44
+#define CRVML_REG_MCHEN    0x54
+#define CRVML_MCHEN_BIT    (1 << 28)
+#define CRVML_MCHMAP_SIZE  4096
+#define CRVML_REG_CLOCK    0xc3c
+#define CRVML_CLOCK_SHIFT  8
+#define CRVML_CLOCK_MASK   0x00000f00
+
+static struct pci_dev *lpc_dev;
+static u32 gpio_bar;
+
+struct cr_panel {
+       struct backlight_device *cr_backlight_device;
+       struct lcd_device *cr_lcd_device;
+};
+
+static int cr_backlight_set_intensity(struct backlight_device *bd)
+{
+       int intensity = bd->props.brightness;
+       u32 addr = gpio_bar + CRVML_PANEL_PORT;
+       u32 cur = inl(addr);
+
+       if (bd->props.power == FB_BLANK_UNBLANK)
+               intensity = FB_BLANK_UNBLANK;
+       if (bd->props.fb_blank == FB_BLANK_UNBLANK)
+               intensity = FB_BLANK_UNBLANK;
+       if (bd->props.power == FB_BLANK_POWERDOWN)
+               intensity = FB_BLANK_POWERDOWN;
+       if (bd->props.fb_blank == FB_BLANK_POWERDOWN)
+               intensity = FB_BLANK_POWERDOWN;
+
+       if (intensity == FB_BLANK_UNBLANK) { /* FULL ON */
+               cur &= ~CRVML_BACKLIGHT_OFF;
+               outl(cur, addr);
+       } else if (intensity == FB_BLANK_POWERDOWN) { /* OFF */
+               cur |= CRVML_BACKLIGHT_OFF;
+               outl(cur, addr);
+       } /* anything else, don't bother */
+
+       return 0;
+}
+
+static int cr_backlight_get_intensity(struct backlight_device *bd)
+{
+       u32 addr = gpio_bar + CRVML_PANEL_PORT;
+       u32 cur = inl(addr);
+       u8 intensity;
+
+       if (cur & CRVML_BACKLIGHT_OFF)
+               intensity = FB_BLANK_POWERDOWN;
+       else
+               intensity = FB_BLANK_UNBLANK;
+
+       return intensity;
+}
+
+static struct backlight_ops cr_backlight_ops = {
+       .get_brightness = cr_backlight_get_intensity,
+       .update_status = cr_backlight_set_intensity,
+};
+
+static void cr_panel_on(void)
+{
+       u32 addr = gpio_bar + CRVML_PANEL_PORT;
+       u32 cur = inl(addr);
+
+       if (!(cur & CRVML_PANEL_ON)) {
+               /* Make sure LVDS controller is down. */
+               if (cur & 0x00000001) {
+                       cur &= ~CRVML_LVDS_ON;
+                       outl(cur, addr);
+               }
+               /* Power up Panel */
+               schedule_timeout(HZ / 10);
+               cur |= CRVML_PANEL_ON;
+               outl(cur, addr);
+       }
+
+       /* Power up LVDS controller */
+
+       if (!(cur & CRVML_LVDS_ON)) {
+               schedule_timeout(HZ / 10);
+               outl(cur | CRVML_LVDS_ON, addr);
+       }
+}
+
+static void cr_panel_off(void)
+{
+       u32 addr = gpio_bar + CRVML_PANEL_PORT;
+       u32 cur = inl(addr);
+
+       /* Power down LVDS controller first to avoid high currents */
+       if (cur & CRVML_LVDS_ON) {
+               cur &= ~CRVML_LVDS_ON;
+               outl(cur, addr);
+       }
+       if (cur & CRVML_PANEL_ON) {
+               schedule_timeout(HZ / 10);
+               outl(cur & ~CRVML_PANEL_ON, addr);
+       }
+}
+
+static int cr_lcd_set_power(struct lcd_device *ld, int power)
+{
+       if (power == FB_BLANK_UNBLANK)
+               cr_panel_on();
+       if (power == FB_BLANK_POWERDOWN)
+               cr_panel_off();
+
+       return 0;
+}
+
+static struct lcd_ops cr_lcd_ops = {
+       .set_power = cr_lcd_set_power,
+};
+
+static int cr_backlight_probe(struct platform_device *pdev)
+{
+       struct cr_panel *crp;
+       u8 dev_en;
+
+       crp = kzalloc(sizeof(crp), GFP_KERNEL);
+       if (crp == NULL)
+               return -ENOMEM;
+
+       lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                       CRVML_DEVICE_LPC, NULL);
+       if (!lpc_dev) {
+               printk("INTEL CARILLO RANCH LPC not found.\n");
+               return -ENODEV;
+       }
+
+       pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
+       if (!(dev_en & CRVML_GPIOEN_BIT)) {
+               printk(KERN_ERR
+                      "Carillo Ranch GPIO device was not enabled.\n");
+               pci_dev_put(lpc_dev);
+               return -ENODEV;
+       }
+
+       crp->cr_backlight_device = backlight_device_register("cr-backlight",
+                                                            &pdev->dev, NULL,
+                                                            &cr_backlight_ops);
+       if (IS_ERR(crp->cr_backlight_device)) {
+               pci_dev_put(lpc_dev);
+               return PTR_ERR(crp->cr_backlight_device);
+       }
+
+       crp->cr_lcd_device = lcd_device_register("cr-lcd",
+                                                       &pdev->dev,
+                                                       &cr_lcd_ops);
+
+       if (IS_ERR(crp->cr_lcd_device)) {
+               pci_dev_put(lpc_dev);
+               return PTR_ERR(crp->cr_backlight_device);
+       }
+
+       pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
+                             &gpio_bar);
+       gpio_bar &= ~0x3F;
+
+       crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK;
+       crp->cr_backlight_device->props.brightness = 0;
+       crp->cr_backlight_device->props.max_brightness = 0;
+       cr_backlight_set_intensity(crp->cr_backlight_device);
+
+       cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK);
+
+       platform_set_drvdata(pdev, crp);
+
+       return 0;
+}
+
+static int cr_backlight_remove(struct platform_device *pdev)
+{
+       struct cr_panel *crp = platform_get_drvdata(pdev);
+       crp->cr_backlight_device->props.power = FB_BLANK_POWERDOWN;
+       crp->cr_backlight_device->props.brightness = 0;
+       crp->cr_backlight_device->props.max_brightness = 0;
+       cr_backlight_set_intensity(crp->cr_backlight_device);
+       cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN);
+       backlight_device_unregister(crp->cr_backlight_device);
+       lcd_device_unregister(crp->cr_lcd_device);
+       pci_dev_put(lpc_dev);
+
+       return 0;
+}
+
+static struct platform_driver cr_backlight_driver = {
+       .probe = cr_backlight_probe,
+       .remove = cr_backlight_remove,
+       .driver = {
+                  .name = "cr_backlight",
+                  },
+};
+
+static struct platform_device *crp;
+
+static int __init cr_backlight_init(void)
+{
+       int ret = platform_driver_register(&cr_backlight_driver);
+
+       if (!ret) {
+               crp = platform_device_alloc("cr_backlight", -1);
+               if (!crp)
+                       return -ENOMEM;
+
+               ret = platform_device_add(crp);
+
+               if (ret) {
+                       platform_device_put(crp);
+                       platform_driver_unregister(&cr_backlight_driver);
+               }
+       }
+
+       printk("Carillo Ranch Backlight Driver Initialized.\n");
+
+       return ret;
+}
+
+static void __exit cr_backlight_exit(void)
+{
+       platform_device_unregister(crp);
+       platform_driver_unregister(&cr_backlight_driver);
+}
+
+module_init(cr_backlight_init);
+module_exit(cr_backlight_exit);
+
+MODULE_AUTHOR("Tungsten Graphics Inc.");
+MODULE_DESCRIPTION("Carillo Ranch Backlight Driver");
+MODULE_LICENSE("GPL");
index 6faea4034e3db7dccd666bb032c73a1fece237a3..032210f45be37a539831030b63d64c1a5d3df61a 100644 (file)
@@ -22,8 +22,6 @@
  *  help moving some redundant computations and branches out of the loop, too.
  */
 
-
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -31,6 +29,7 @@
 #include <linux/slab.h>
 #include <asm/types.h>
 #include <asm/io.h>
+#include "fb_draw.h"
 
 #if BITS_PER_LONG == 32
 #  define FB_WRITEL fb_writel
 #  define FB_READL  fb_readq
 #endif
 
-    /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline unsigned long
-comp(unsigned long a, unsigned long b, unsigned long mask)
-{
-    return ((a ^ b) & mask) ^ b;
-}
-
     /*
      *  Generic bitwise copy algorithm
      */
index f00b50aab6061e509f957aebd5fd48f603617a48..71623b4f8ca26581dbf4f8258734685fbd55e079 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 #include <asm/types.h>
+#include "fb_draw.h"
 
 #if BITS_PER_LONG == 32
 #  define FB_WRITEL fb_writel
 #else
 #  define FB_WRITEL fb_writeq
 #  define FB_READL  fb_readq
-#endif
-
-    /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline unsigned long
-comp(unsigned long a, unsigned long b, unsigned long mask)
-{
-    return ((a ^ b) & mask) ^ b;
-}
-
-    /*
-     *  Create a pattern with the given pixel's color
-     */
-
-#if BITS_PER_LONG == 64
-static inline unsigned long
-pixel_to_pat( u32 bpp, u32 pixel)
-{
-       switch (bpp) {
-       case 1:
-               return 0xfffffffffffffffful*pixel;
-       case 2:
-               return 0x5555555555555555ul*pixel;
-       case 4:
-               return 0x1111111111111111ul*pixel;
-       case 8:
-               return 0x0101010101010101ul*pixel;
-       case 12:
-               return 0x0001001001001001ul*pixel;
-       case 16:
-               return 0x0001000100010001ul*pixel;
-       case 24:
-               return 0x0000000001000001ul*pixel;
-       case 32:
-               return 0x0000000100000001ul*pixel;
-       default:
-               panic("pixel_to_pat(): unsupported pixelformat\n");
-    }
-}
-#else
-static inline unsigned long
-pixel_to_pat( u32 bpp, u32 pixel)
-{
-       switch (bpp) {
-       case 1:
-               return 0xfffffffful*pixel;
-       case 2:
-               return 0x55555555ul*pixel;
-       case 4:
-               return 0x11111111ul*pixel;
-       case 8:
-               return 0x01010101ul*pixel;
-       case 12:
-               return 0x00001001ul*pixel;
-       case 16:
-               return 0x00010001ul*pixel;
-       case 24:
-               return 0x00000001ul*pixel;
-       case 32:
-               return 0x00000001ul*pixel;
-       default:
-               panic("pixel_to_pat(): unsupported pixelformat\n");
-    }
-}
 #endif
 
     /*
index 2c4bc6205738992f643128a812769859352f20f8..8269d704ab2a2c27731490b3eeb39b203c9f80f3 100644 (file)
 #define assert(expr)
 #endif
 
-#ifdef TRUE
-#undef TRUE
-#endif
-#ifdef FALSE
-#undef FALSE
-#endif
-#define TRUE  1
-#define FALSE 0
-
 #define MB_ (1024*1024)
 #define KB_ (1024)
 
@@ -146,9 +137,9 @@ static const struct cirrusfb_board_info_rec {
        char *name;             /* ASCII name of chipset */
        long maxclock[5];               /* maximum video clock */
        /* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
-       unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
-       unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
-       unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
+       bool init_sr07 : 1; /* init SR07 during init_vgachip() */
+       bool init_sr1f : 1; /* write SR1F during init_vgachip() */
+       bool scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
 
        /* initial SR07 value, then for each mode */
        unsigned char sr07;
@@ -166,9 +157,9 @@ static const struct cirrusfb_board_info_rec {
                        /* the SD64/P4 have a higher max. videoclock */
                        140000, 140000, 140000, 140000, 140000,
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = true,
                .sr07                   = 0xF0,
                .sr07_1bpp              = 0xF0,
                .sr07_8bpp              = 0xF1,
@@ -180,9 +171,9 @@ static const struct cirrusfb_board_info_rec {
                        /* guess */
                        90000, 90000, 90000, 90000, 90000
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = false,
                .sr07                   = 0x80,
                .sr07_1bpp              = 0x80,
                .sr07_8bpp              = 0x81,
@@ -194,9 +185,9 @@ static const struct cirrusfb_board_info_rec {
                        /* guess */
                        90000, 90000, 90000, 90000, 90000
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = false,
                .sr07                   = 0x20,
                .sr07_1bpp              = 0x20,
                .sr07_8bpp              = 0x21,
@@ -208,9 +199,9 @@ static const struct cirrusfb_board_info_rec {
                        /* guess */
                        90000, 90000, 90000, 90000, 90000
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = false,
                .sr07                   = 0x80,
                .sr07_1bpp              = 0x80,
                .sr07_8bpp              = 0x81,
@@ -221,9 +212,9 @@ static const struct cirrusfb_board_info_rec {
                .maxclock               = {
                        135100, 135100, 85500, 85500, 0
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = FALSE,
-               .scrn_start_bit19       = TRUE,
+               .init_sr07              = true,
+               .init_sr1f              = false,
+               .scrn_start_bit19       = true,
                .sr07                   = 0x20,
                .sr07_1bpp              = 0x20,
                .sr07_8bpp              = 0x21,
@@ -235,9 +226,9 @@ static const struct cirrusfb_board_info_rec {
                        /* for the GD5430.  GD5446 can do more... */
                        85500, 85500, 50000, 28500, 0
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = true,
                .sr07                   = 0xA0,
                .sr07_1bpp              = 0xA1,
                .sr07_1bpp_mux          = 0xA7,
@@ -250,9 +241,9 @@ static const struct cirrusfb_board_info_rec {
                .maxclock               = {
                        135100, 200000, 200000, 135100, 135100
                },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
+               .init_sr07              = true,
+               .init_sr1f              = true,
+               .scrn_start_bit19       = true,
                .sr07                   = 0x10,
                .sr07_1bpp              = 0x11,
                .sr07_8bpp              = 0x11,
@@ -264,9 +255,9 @@ static const struct cirrusfb_board_info_rec {
                        /* guess */
                        135100, 135100, 135100, 135100, 135100,
                },
-               .init_sr07              = FALSE,
-               .init_sr1f              = FALSE,
-               .scrn_start_bit19       = TRUE,
+               .init_sr07              = false,
+               .init_sr1f              = false,
+               .scrn_start_bit19       = true,
        }
 };
 
@@ -815,7 +806,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
 
        default:
                DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
-               assert (FALSE);
+               assert(false);
                /* should never occur */
                break;
        }
@@ -886,7 +877,7 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
 
        default:
                DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
-               assert (FALSE);
+               assert(false);
                /* should never occur */
                break;
        }
@@ -3203,7 +3194,7 @@ void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_clas
                        break;
                default:
                        /* should never occur */
-                       assert (FALSE);
+                       assert(false);
                        break;
                }
 
index 0429fd2cece09cff24a3e3f849a9894bac3056cb..73813c60d03a9c010597c35a3960216005fe9ea2 100644 (file)
@@ -107,7 +107,9 @@ static struct display fb_display[MAX_NR_CONSOLES];
 
 static signed char con2fb_map[MAX_NR_CONSOLES];
 static signed char con2fb_map_boot[MAX_NR_CONSOLES];
+#ifndef MODULE
 static int logo_height;
+#endif
 static int logo_lines;
 /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
    enums.  */
@@ -576,6 +578,13 @@ static int fbcon_takeover(int show_logo)
        return err;
 }
 
+#ifdef MODULE
+static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
+                              int cols, int rows, int new_cols, int new_rows)
+{
+       logo_shown = FBCON_LOGO_DONTSHOW;
+}
+#else
 static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
                               int cols, int rows, int new_cols, int new_rows)
 {
@@ -584,6 +593,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
        int cnt, erase = vc->vc_video_erase_char, step;
        unsigned short *save = NULL, *r, *q;
 
+       if (info->flags & FBINFO_MODULE) {
+               logo_shown = FBCON_LOGO_DONTSHOW;
+               return;
+       }
+
        /*
         * remove underline attribute from erase character
         * if black and white framebuffer.
@@ -618,8 +632,13 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
                        r -= cols;
                }
                if (!save) {
-                       vc->vc_y += logo_lines;
-                       vc->vc_pos += logo_lines * vc->vc_size_row;
+                       int lines;
+                       if (vc->vc_y + logo_lines >= rows)
+                               lines = rows - vc->vc_y - 1;
+                       else
+                               lines = logo_lines;
+                       vc->vc_y += lines;
+                       vc->vc_pos += lines * vc->vc_size_row;
                }
        }
        scr_memsetw((unsigned short *) vc->vc_origin,
@@ -650,6 +669,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
                vc->vc_top = logo_lines;
        }
 }
+#endif /* MODULE */
 
 #ifdef CONFIG_FB_TILEBLITTING
 static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
@@ -665,6 +685,17 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
                fbcon_set_bitops(ops);
        }
 }
+
+static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+{
+       int err = 0;
+
+       if (info->flags & FBINFO_MISC_TILEBLITTING &&
+           info->tileops->fb_get_tilemax(info) < charcount)
+               err = 1;
+
+       return err;
+}
 #else
 static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 {
@@ -675,6 +706,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
        fbcon_set_rotation(info);
        fbcon_set_bitops(ops);
 }
+
+static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+{
+       return 0;
+}
+
 #endif /* CONFIG_MISC_TILEBLITTING */
 
 
@@ -968,7 +1005,9 @@ static const char *fbcon_startup(void)
        if (!p->fontdata) {
                if (!fontname[0] || !(font = find_font(fontname)))
                        font = get_default_font(info->var.xres,
-                                               info->var.yres);
+                                               info->var.yres,
+                                               info->pixmap.blit_x,
+                                               info->pixmap.blit_y);
                vc->vc_font.width = font->width;
                vc->vc_font.height = font->height;
                vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -1088,7 +1127,9 @@ static void fbcon_init(struct vc_data *vc, int init)
 
                        if (!fontname[0] || !(font = find_font(fontname)))
                                font = get_default_font(info->var.xres,
-                                                       info->var.yres);
+                                                       info->var.yres,
+                                                       info->pixmap.blit_x,
+                                                       info->pixmap.blit_y);
                        vc->vc_font.width = font->width;
                        vc->vc_font.height = font->height;
                        vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -1305,7 +1346,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
        int y;
        int c = scr_readw((u16 *) vc->vc_pos);
 
-       if (fbcon_is_inactive(vc, info))
+       if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
                return;
 
        ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
@@ -2475,6 +2516,7 @@ static int fbcon_copy_font(struct vc_data *vc, int con)
 
 static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags)
 {
+       struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        unsigned charcount = font->charcount;
        int w = font->width;
        int h = font->height;
@@ -2488,6 +2530,15 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
        if (charcount != 256 && charcount != 512)
                return -EINVAL;
 
+       /* Make sure drawing engine can handle the font */
+       if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
+           !(info->pixmap.blit_y & (1 << (font->height - 1))))
+               return -EINVAL;
+
+       /* Make sure driver can handle the font length */
+       if (fbcon_invalid_charcount(info, charcount))
+               return -EINVAL;
+
        size = h * pitch * charcount;
 
        new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
@@ -2532,7 +2583,8 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha
        const struct font_desc *f;
 
        if (!name)
-               f = get_default_font(info->var.xres, info->var.yres);
+               f = get_default_font(info->var.xres, info->var.yres,
+                                    info->pixmap.blit_x, info->pixmap.blit_y);
        else if (!(f = find_font(name)))
                return -ENOENT;
 
@@ -2829,7 +2881,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
        struct display *p;
-       int i, rows, cols;
+       int i, rows, cols, fg = -1;
 
        if (!ops || ops->currcon < 0)
                return;
@@ -2840,34 +2892,23 @@ static void fbcon_set_all_vcs(struct fb_info *info)
                    registered_fb[con2fb_map[i]] != info)
                        continue;
 
+               if (CON_IS_VISIBLE(vc)) {
+                       fg = i;
+                       continue;
+               }
+
                p = &fb_display[vc->vc_num];
                set_blitting_type(vc, info);
                var_to_display(p, &info->var, info);
-               cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
-               rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+               cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
+               rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
                cols /= vc->vc_font.width;
                rows /= vc->vc_font.height;
                vc_resize(vc, cols, rows);
-
-               if (CON_IS_VISIBLE(vc)) {
-                       updatescrollmode(p, info, vc);
-                       scrollback_max = 0;
-                       scrollback_current = 0;
-
-                       if (!fbcon_is_inactive(vc, info)) {
-                           ops->var.xoffset = ops->var.yoffset =
-                               p->yscroll = 0;
-                           ops->update_start(info);
-                       }
-
-                       fbcon_set_palette(vc, color_table);
-                       update_screen(vc);
-                       if (softback_buf)
-                               fbcon_update_softback(vc);
-               }
        }
 
-       ops->p = &fb_display[ops->currcon];
+       if (fg != -1)
+               fbcon_modechanged(info);
 }
 
 static int fbcon_mode_deleted(struct fb_info *info,
@@ -3002,6 +3043,42 @@ static void fbcon_new_modelist(struct fb_info *info)
        }
 }
 
+static void fbcon_get_requirement(struct fb_info *info,
+                                 struct fb_blit_caps *caps)
+{
+       struct vc_data *vc;
+       struct display *p;
+
+       if (caps->flags) {
+               int i, charcnt;
+
+               for (i = first_fb_vc; i <= last_fb_vc; i++) {
+                       vc = vc_cons[i].d;
+                       if (vc && vc->vc_mode == KD_TEXT &&
+                           info->node == con2fb_map[i]) {
+                               p = &fb_display[i];
+                               caps->x |= 1 << (vc->vc_font.width - 1);
+                               caps->y |= 1 << (vc->vc_font.height - 1);
+                               charcnt = (p->userfont) ?
+                                       FNTCHARCNT(p->fontdata) : 256;
+                               if (caps->len < charcnt)
+                                       caps->len = charcnt;
+                       }
+               }
+       } else {
+               vc = vc_cons[fg_console].d;
+
+               if (vc && vc->vc_mode == KD_TEXT &&
+                   info->node == con2fb_map[fg_console]) {
+                       p = &fb_display[fg_console];
+                       caps->x = 1 << (vc->vc_font.width - 1);
+                       caps->y = 1 << (vc->vc_font.height - 1);
+                       caps->len = (p->userfont) ?
+                               FNTCHARCNT(p->fontdata) : 256;
+               }
+       }
+}
+
 static int fbcon_event_notify(struct notifier_block *self, 
                              unsigned long action, void *data)
 {
@@ -3009,6 +3086,7 @@ static int fbcon_event_notify(struct notifier_block *self,
        struct fb_info *info = event->info;
        struct fb_videomode *mode;
        struct fb_con2fbmap *con2fb;
+       struct fb_blit_caps *caps;
        int ret = 0;
 
        /*
@@ -3057,6 +3135,10 @@ static int fbcon_event_notify(struct notifier_block *self,
        case FB_EVENT_NEW_MODELIST:
                fbcon_new_modelist(info);
                break;
+       case FB_EVENT_GET_REQ:
+               caps = event->data;
+               fbcon_get_requirement(info, caps);
+               break;
        }
 
 done:
index c960728b7e82dd2fe6439f2a7364cabdcede9c43..a6828d0a4c5674d3553fda2e65b1c6fd1f4ddc7f 100644 (file)
@@ -98,6 +98,8 @@ const struct font_desc *find_font(const char *name)
  *     get_default_font - get default font
  *     @xres: screen size of X
  *     @yres: screen size of Y
+ *      @font_w: bit array of supported widths (1 - 32)
+ *      @font_h: bit array of supported heights (1 - 32)
  *
  *     Get the default font for a specified screen size.
  *     Dimensions are in pixels.
@@ -107,7 +109,8 @@ const struct font_desc *find_font(const char *name)
  *
  */
 
-const struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres, u32 font_w,
+                                        u32 font_h)
 {
     int i, c, cc;
     const struct font_desc *f, *g;
@@ -129,6 +132,11 @@ const struct font_desc *get_default_font(int xres, int yres)
 #endif
        if ((yres < 400) == (f->height <= 8))
            c += 1000;
+
+       if (!(font_w & (1 << (f->width - 1))) ||
+           !(font_w & (1 << (f->height - 1))))
+           c += 1000;
+
        if (c > cc) {
            cc = c;
            g = f;
index 124ecbe6f88cf37dc00152e393ecddc2b4b568a2..bd8d995fe25de13a1a0fa7444ba35eef58ded727 100644 (file)
@@ -384,7 +384,7 @@ static inline u16 mda_convert_attr(u16 ch)
 }
 
 static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, 
-                           u8 blink, u8 underline, u8 reverse)
+                           u8 blink, u8 underline, u8 reverse, u8 italic)
 {
        /* The attribute is just a bit vector:
         *
@@ -397,6 +397,7 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
        return (intensity & 3) |
                ((underline & 1) << 2) |
                ((reverse   & 1) << 3) |
+               (!!italic << 4) |
                ((blink     & 1) << 7);
 }
 
index b78eac63459f09d18c928f88f33f6b86cc8155aa..ae02e4eb18e7967e065e0aadc1c1fe6425fdd0ff 100644 (file)
@@ -548,7 +548,8 @@ promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
 }
 
 #if !(PROMCON_COLOR)
-static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
+static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity,
+    u8 _blink, u8 _underline, u8 _reverse, u8 _italic)
 {
        return (_reverse) ? 0xf : 0x7;
 }
index f577bd80e020ee832c28657629128d57cd7a73f7..03cfb7ac5733fd19af0d287d03d003d41f081c05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/video/softcursor.c
+ * linux/drivers/video/console/softcursor.c
  *
  * Generic software cursor for frame buffer devices
  *
index 57b21e533036983637c4fd6be89b3ba581ee042c..67a682d6cc7bb03ba043753d4585928b248f1b6f 100644 (file)
@@ -314,7 +314,7 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
 }
 
 static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,
-                           u8 blink, u8 underline, u8 reverse)
+                           u8 blink, u8 underline, u8 reverse, u8 italic)
 {
     u8 attr = ((color & 0x70) >> 1) | ((color & 7));
 
index 88e7038eab889f68eedc0ace5911cac131e3ec93..717b360d041536ee80f8a4ce8ee99c7bf88c7c9e 100644 (file)
@@ -495,7 +495,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
                return NULL;
        fbfont = find_font(fbfont_name);
        if (!fbfont)
-               fbfont = get_default_font(1024,768);
+               fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0);
        if (!fbfont)
                return NULL;
 
index 3e67c34df9a593d6c93f7722037330f9eaff8460..2460b82a1d9323e6c4a17d64d4122d1425b57b83 100644 (file)
@@ -86,8 +86,6 @@ static int vgacon_set_origin(struct vc_data *c);
 static void vgacon_save_screen(struct vc_data *c);
 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
                         int lines);
-static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
-                           u8 blink, u8 underline, u8 reverse);
 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
 static unsigned long vgacon_uni_pagedir[2];
 
@@ -578,12 +576,14 @@ static void vgacon_deinit(struct vc_data *c)
 }
 
 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
-                           u8 blink, u8 underline, u8 reverse)
+                           u8 blink, u8 underline, u8 reverse, u8 italic)
 {
        u8 attr = color;
 
        if (vga_can_do_color) {
-               if (underline)
+               if (italic)
+                       attr = (attr & 0xF0) | c->vc_itcolor;
+               else if (underline)
                        attr = (attr & 0xf0) | c->vc_ulcolor;
                else if (intensity == 0)
                        attr = (attr & 0xf0) | c->vc_halfcolor;
@@ -597,7 +597,9 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
        if (intensity == 2)
                attr ^= 0x08;
        if (!vga_can_do_color) {
-               if (underline)
+               if (italic)
+                       attr = (attr & 0xF8) | 0x02;
+               else if (underline)
                        attr = (attr & 0xf8) | 0x01;
                else if (intensity == 0)
                        attr = (attr & 0xf0) | 0x08;
@@ -658,6 +660,9 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
 
 static void vgacon_cursor(struct vc_data *c, int mode)
 {
+       if (c->vc_mode != KD_TEXT)
+               return;
+
        vgacon_restore_screen(c);
 
        switch (mode) {
@@ -1316,7 +1321,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
        unsigned long oldo;
        unsigned int delta;
 
-       if (t || b != c->vc_rows || vga_is_gfx)
+       if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
                return 0;
 
        if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
new file mode 100644 (file)
index 0000000..f99af93
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Display drivers configuration
+#
+
+menu "Display device support"
+
+config DISPLAY_SUPPORT
+       tristate "Display panel/monitor support"
+       ---help---
+         This framework adds support for low-level control of a display.
+         This includes support for power.
+
+         Enable this to be able to choose the drivers for controlling the
+         physical display panel/monitor on some platforms. This not only
+         covers LCD displays for PDAs but also other types of displays
+         such as CRT, TVout etc.
+
+         To have support for your specific display panel you will have to
+         select the proper drivers which depend on this option.
+
+comment "Display hardware drivers"
+       depends on DISPLAY_SUPPORT
+
+endmenu
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
new file mode 100644 (file)
index 0000000..c0ea832
--- /dev/null
@@ -0,0 +1,6 @@
+# Display drivers
+
+display-objs                           := display-sysfs.o
+
+obj-$(CONFIG_DISPLAY_SUPPORT)          += display.o
+
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
new file mode 100644 (file)
index 0000000..3547717
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ *  display-sysfs.c - Display output driver sysfs interface
+ *
+ *  Copyright (C) 2007 James Simmons <jsimmons@infradead.org>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/module.h>
+#include <linux/display.h>
+#include <linux/ctype.h>
+#include <linux/idr.h>
+#include <linux/err.h>
+
+static ssize_t display_show_name(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
+}
+
+static ssize_t display_show_type(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
+}
+
+static ssize_t display_show_contrast(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+       ssize_t rc = -ENXIO;
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver) && dsp->driver->get_contrast)
+               rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
+       mutex_unlock(&dsp->lock);
+       return rc;
+}
+
+static ssize_t display_store_contrast(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+       ssize_t ret = -EINVAL, size;
+       int contrast;
+       char *endp;
+
+       contrast = simple_strtoul(buf, &endp, 0);
+       size = endp - buf;
+
+       if (*endp && isspace(*endp))
+               size++;
+
+       if (size != count)
+               return ret;
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver && dsp->driver->set_contrast)) {
+               pr_debug("display: set contrast to %d\n", contrast);
+               dsp->driver->set_contrast(dsp, contrast);
+               ret = count;
+       }
+       mutex_unlock(&dsp->lock);
+       return ret;
+}
+
+static ssize_t display_show_max_contrast(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+       ssize_t rc = -ENXIO;
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver))
+               rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
+       mutex_unlock(&dsp->lock);
+       return rc;
+}
+
+static struct device_attribute display_attrs[] = {
+       __ATTR(name, S_IRUGO, display_show_name, NULL),
+       __ATTR(type, S_IRUGO, display_show_type, NULL),
+       __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
+       __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
+};
+
+static int display_suspend(struct device *dev, pm_message_t state)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver->suspend))
+               dsp->driver->suspend(dsp, state);
+       mutex_unlock(&dsp->lock);
+       return 0;
+};
+
+static int display_resume(struct device *dev)
+{
+       struct display_device *dsp = dev_get_drvdata(dev);
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver->resume))
+               dsp->driver->resume(dsp);
+       mutex_unlock(&dsp->lock);
+       return 0;
+};
+
+static struct mutex allocated_dsp_lock;
+static DEFINE_IDR(allocated_dsp);
+static struct class *display_class;
+
+struct display_device *display_device_register(struct display_driver *driver,
+                                               struct device *parent, void *devdata)
+{
+       struct display_device *new_dev = NULL;
+       int ret = -EINVAL;
+
+       if (unlikely(!driver))
+               return ERR_PTR(ret);
+
+       mutex_lock(&allocated_dsp_lock);
+       ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
+       mutex_unlock(&allocated_dsp_lock);
+       if (!ret)
+               return ERR_PTR(ret);
+
+       new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
+       if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
+               // Reserve the index for this display
+               mutex_lock(&allocated_dsp_lock);
+               ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
+               mutex_unlock(&allocated_dsp_lock);
+
+               if (!ret) {
+                       new_dev->dev = device_create(display_class, parent, 0,
+                                               "display%d", new_dev->idx);
+                       if (!IS_ERR(new_dev->dev)) {
+                               dev_set_drvdata(new_dev->dev, new_dev);
+                               new_dev->parent = parent;
+                               new_dev->driver = driver;
+                               mutex_init(&new_dev->lock);
+                               return new_dev;
+                       }
+                       mutex_lock(&allocated_dsp_lock);
+                       idr_remove(&allocated_dsp, new_dev->idx);
+                       mutex_unlock(&allocated_dsp_lock);
+                       ret = -EINVAL;
+               }
+       }
+       kfree(new_dev);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(display_device_register);
+
+void display_device_unregister(struct display_device *ddev)
+{
+       if (!ddev)
+               return;
+       // Free device
+       mutex_lock(&ddev->lock);
+       device_unregister(ddev->dev);
+       mutex_unlock(&ddev->lock);
+       // Mark device index as avaliable
+       mutex_lock(&allocated_dsp_lock);
+       idr_remove(&allocated_dsp, ddev->idx);
+       mutex_unlock(&allocated_dsp_lock);
+       kfree(ddev);
+}
+EXPORT_SYMBOL(display_device_unregister);
+
+static int __init display_class_init(void)
+{
+       display_class = class_create(THIS_MODULE, "display");
+       if (IS_ERR(display_class)) {
+               printk(KERN_ERR "Failed to create display class\n");
+               display_class = NULL;
+               return -EINVAL;
+       }
+       display_class->dev_attrs = display_attrs;
+       display_class->suspend = display_suspend;
+       display_class->resume = display_resume;
+       mutex_init(&allocated_dsp_lock);
+       return 0;
+}
+
+static void __exit display_class_exit(void)
+{
+       class_destroy(display_class);
+}
+
+module_init(display_class_init);
+module_exit(display_class_exit);
+
+MODULE_DESCRIPTION("Display Hardware handling");
+MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
+MODULE_LICENSE("GPL");
+
index 29e07c1098876997db774ae77572a1e9d649c175..ca2c54ce508e678ee8deaafa63016c9bae783948 100644 (file)
@@ -403,17 +403,10 @@ static inline unsigned long copy_to_user16(void *to, const void *from,
 
 
 static ssize_t
-epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+epson1355fb_read(struct fb_info *info, char *buf, size_t count, loff_t * ppos)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
        unsigned long p = *ppos;
 
-       /* from fbmem.c except for our own copy_*_user */
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
        if (p >= info->fix.smem_len)
                return 0;
        if (count >= info->fix.smem_len)
@@ -434,19 +427,12 @@ epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
 }
 
 static ssize_t
-epson1355fb_write(struct file *file, const char *buf,
+epson1355fb_write(struct fb_info *info, const char *buf,
                  size_t count, loff_t * ppos)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
        unsigned long p = *ppos;
        int err;
 
-       /* from fbmem.c except for our own copy_*_user */
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
        /* from fbmem.c except for our own copy_*_user */
        if (p > info->fix.smem_len)
                return -ENOSPC;
@@ -650,9 +636,10 @@ int __init epson1355fb_probe(struct platform_device *dev)
        }
 
        info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
-       if (!info)
+       if (!info) {
                rc = -ENOMEM;
                goto bail;
+       }
 
        default_par = info->par;
        default_par->reg_addr = (unsigned long) ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
new file mode 100644 (file)
index 0000000..1a8643f
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  linux/drivers/video/fb_defio.c
+ *
+ *  Copyright (C) 2006 Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+
+/* to support deferred IO */
+#include <linux/rmap.h>
+#include <linux/pagemap.h>
+
+/* this is to find and return the vmalloc-ed fb pages */
+static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma,
+                                       unsigned long vaddr, int *type)
+{
+       unsigned long offset;
+       struct page *page;
+       struct fb_info *info = vma->vm_private_data;
+       /* info->screen_base is in System RAM */
+       void *screen_base = (void __force *) info->screen_base;
+
+       offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+       if (offset >= info->fix.smem_len)
+               return NOPAGE_SIGBUS;
+
+       page = vmalloc_to_page(screen_base + offset);
+       if (!page)
+               return NOPAGE_OOM;
+
+       get_page(page);
+       if (type)
+               *type = VM_FAULT_MINOR;
+       return page;
+}
+
+int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+       struct fb_info *info = file->private_data;
+
+       /* Kill off the delayed work */
+       cancel_rearming_delayed_work(&info->deferred_work);
+
+       /* Run it immediately */
+       return schedule_delayed_work(&info->deferred_work, 0);
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
+
+/* vm_ops->page_mkwrite handler */
+static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
+                                 struct page *page)
+{
+       struct fb_info *info = vma->vm_private_data;
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       /* this is a callback we get when userspace first tries to
+       write to the page. we schedule a workqueue. that workqueue
+       will eventually mkclean the touched pages and execute the
+       deferred framebuffer IO. then if userspace touches a page
+       again, we repeat the same scheme */
+
+       /* protect against the workqueue changing the page list */
+       mutex_lock(&fbdefio->lock);
+       list_add(&page->lru, &fbdefio->pagelist);
+       mutex_unlock(&fbdefio->lock);
+
+       /* come back after delay to process the deferred IO */
+       schedule_delayed_work(&info->deferred_work, fbdefio->delay);
+       return 0;
+}
+
+static struct vm_operations_struct fb_deferred_io_vm_ops = {
+       .nopage         = fb_deferred_io_nopage,
+       .page_mkwrite   = fb_deferred_io_mkwrite,
+};
+
+static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       vma->vm_ops = &fb_deferred_io_vm_ops;
+       vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND );
+       vma->vm_private_data = info;
+       return 0;
+}
+
+/* workqueue callback */
+static void fb_deferred_io_work(struct work_struct *work)
+{
+       struct fb_info *info = container_of(work, struct fb_info,
+                                               deferred_work.work);
+       struct list_head *node, *next;
+       struct page *cur;
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       /* here we mkclean the pages, then do all deferred IO */
+       mutex_lock(&fbdefio->lock);
+       list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+               lock_page(cur);
+               page_mkclean(cur);
+               unlock_page(cur);
+       }
+
+       /* driver's callback with pagelist */
+       fbdefio->deferred_io(info, &fbdefio->pagelist);
+
+       /* clear the list */
+       list_for_each_safe(node, next, &fbdefio->pagelist) {
+               list_del(node);
+       }
+       mutex_unlock(&fbdefio->lock);
+}
+
+void fb_deferred_io_init(struct fb_info *info)
+{
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       BUG_ON(!fbdefio);
+       mutex_init(&fbdefio->lock);
+       info->fbops->fb_mmap = fb_deferred_io_mmap;
+       INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work);
+       INIT_LIST_HEAD(&fbdefio->pagelist);
+       if (fbdefio->delay == 0) /* set a default of 1 s */
+               fbdefio->delay = HZ;
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_init);
+
+void fb_deferred_io_cleanup(struct fb_info *info)
+{
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       BUG_ON(!fbdefio);
+       cancel_delayed_work(&info->deferred_work);
+       flush_scheduled_work();
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
new file mode 100644 (file)
index 0000000..c5c4520
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _FB_DRAW_H
+#define _FB_DRAW_H
+
+#include <asm/types.h>
+
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
+{
+    return ((a ^ b) & mask) ^ b;
+}
+
+    /*
+     *  Create a pattern with the given pixel's color
+     */
+
+#if BITS_PER_LONG == 64
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+       switch (bpp) {
+       case 1:
+               return 0xfffffffffffffffful*pixel;
+       case 2:
+               return 0x5555555555555555ul*pixel;
+       case 4:
+               return 0x1111111111111111ul*pixel;
+       case 8:
+               return 0x0101010101010101ul*pixel;
+       case 12:
+               return 0x0001001001001001ul*pixel;
+       case 16:
+               return 0x0001000100010001ul*pixel;
+       case 24:
+               return 0x0000000001000001ul*pixel;
+       case 32:
+               return 0x0000000100000001ul*pixel;
+       default:
+               panic("pixel_to_pat(): unsupported pixelformat\n");
+    }
+}
+#else
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+       switch (bpp) {
+       case 1:
+               return 0xfffffffful*pixel;
+       case 2:
+               return 0x55555555ul*pixel;
+       case 4:
+               return 0x11111111ul*pixel;
+       case 8:
+               return 0x01010101ul*pixel;
+       case 12:
+               return 0x00001001ul*pixel;
+       case 16:
+               return 0x00010001ul*pixel;
+       case 24:
+               return 0x00000001ul*pixel;
+       case 32:
+               return 0x00000001ul*pixel;
+       default:
+               panic("pixel_to_pat(): unsupported pixelformat\n");
+    }
+}
+#endif
+#endif /* FB_DRAW_H */
diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fb_sys_fops.c
new file mode 100644 (file)
index 0000000..cf2538d
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * linux/drivers/video/fb_sys_read.c - Generic file operations where
+ * framebuffer is in system RAM
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
+                   loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *src;
+       int err = 0;
+       unsigned long total_size;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return -EPERM;
+
+       total_size = info->screen_size;
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p >= total_size)
+               return 0;
+
+       if (count >= total_size)
+               count = total_size;
+
+       if (count + p > total_size)
+               count = total_size - p;
+
+       src = (void __force *)(info->screen_base + p);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       if (copy_to_user(buf, src, count))
+               err = -EFAULT;
+
+       if  (!err)
+               *ppos += count;
+
+       return (err) ? err : count;
+}
+EXPORT_SYMBOL_GPL(fb_sys_read);
+
+ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
+                    size_t count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *dst;
+       int err = 0;
+       unsigned long total_size;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return -EPERM;
+
+       total_size = info->screen_size;
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p > total_size)
+               return -EFBIG;
+
+       if (count > total_size) {
+               err = -EFBIG;
+               count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
+
+               count = total_size - p;
+       }
+
+       dst = (void __force *) (info->screen_base + p);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       if (copy_from_user(dst, buf, count))
+               err = -EFAULT;
+
+       if  (!err)
+               *ppos += count;
+
+       return (err) ? err : count;
+}
+EXPORT_SYMBOL_GPL(fb_sys_write);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic file read (fb in system RAM)");
+MODULE_LICENSE("GPL");
index 28225265159a7c42b36239918695d7e20bc1f399..38c2e2558f5e34ac8285ca91253b204e9ae4cc51 100644 (file)
@@ -354,59 +354,59 @@ static void fb_rotate_logo(struct fb_info *info, u8 *dst,
        if (rotate == FB_ROTATE_UD) {
                fb_rotate_logo_ud(image->data, dst, image->width,
                                  image->height);
-               image->dx = info->var.xres - image->width;
-               image->dy = info->var.yres - image->height;
+               image->dx = info->var.xres - image->width - image->dx;
+               image->dy = info->var.yres - image->height - image->dy;
        } else if (rotate == FB_ROTATE_CW) {
                fb_rotate_logo_cw(image->data, dst, image->width,
                                  image->height);
                tmp = image->width;
                image->width = image->height;
                image->height = tmp;
-               image->dx = info->var.xres - image->width;
+               tmp = image->dy;
+               image->dy = image->dx;
+               image->dx = info->var.xres - image->width - tmp;
        } else if (rotate == FB_ROTATE_CCW) {
                fb_rotate_logo_ccw(image->data, dst, image->width,
                                   image->height);
                tmp = image->width;
                image->width = image->height;
                image->height = tmp;
-               image->dy = info->var.yres - image->height;
+               tmp = image->dx;
+               image->dx = image->dy;
+               image->dy = info->var.yres - image->height - tmp;
        }
 
        image->data = dst;
 }
 
 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
-                           int rotate)
+                           int rotate, unsigned int num)
 {
-       int x;
+       unsigned int x;
 
        if (rotate == FB_ROTATE_UR) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.xres - fb_logo.logo->width; x++) {
+               for (x = 0;
+                    x < num && image->dx + image->width <= info->var.xres;
+                    x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dx += fb_logo.logo->width + 8;
+                       image->dx += image->width + 8;
                }
        } else if (rotate == FB_ROTATE_UD) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.xres - fb_logo.logo->width; x++) {
+               for (x = 0; x < num && image->dx >= 0; x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dx -= fb_logo.logo->width + 8;
+                       image->dx -= image->width + 8;
                }
        } else if (rotate == FB_ROTATE_CW) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.yres - fb_logo.logo->width; x++) {
+               for (x = 0;
+                    x < num && image->dy + image->height <= info->var.yres;
+                    x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dy += fb_logo.logo->width + 8;
+                       image->dy += image->height + 8;
                }
        } else if (rotate == FB_ROTATE_CCW) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.yres - fb_logo.logo->width; x++) {
+               for (x = 0; x < num && image->dy >= 0; x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dy -= fb_logo.logo->width + 8;
+                       image->dy -= image->height + 8;
                }
        }
 }
@@ -418,7 +418,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
 
        memset(&fb_logo, 0, sizeof(struct logo_data));
 
-       if (info->flags & FBINFO_MISC_TILEBLITTING)
+       if (info->flags & FBINFO_MISC_TILEBLITTING ||
+           info->flags & FBINFO_MODULE)
                return 0;
 
        if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -483,7 +484,8 @@ int fb_show_logo(struct fb_info *info, int rotate)
        struct fb_image image;
 
        /* Return if the frame buffer is not mapped or suspended */
-       if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
+       if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+           info->flags & FBINFO_MODULE)
                return 0;
 
        image.depth = 8;
@@ -532,7 +534,7 @@ int fb_show_logo(struct fb_info *info, int rotate)
                        fb_rotate_logo(info, logo_rotate, &image, rotate);
        }
 
-       fb_do_show_logo(info, &image, rotate);
+       fb_do_show_logo(info, &image, rotate, num_online_cpus());
 
        kfree(palette);
        if (saved_pseudo_palette != NULL)
@@ -586,7 +588,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                return -EPERM;
 
        if (info->fbops->fb_read)
-               return info->fbops->fb_read(file, buf, count, ppos);
+               return info->fbops->fb_read(info, buf, count, ppos);
        
        total_size = info->screen_size;
 
@@ -661,7 +663,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
                return -EPERM;
 
        if (info->fbops->fb_write)
-               return info->fbops->fb_write(file, buf, count, ppos);
+               return info->fbops->fb_write(info, buf, count, ppos);
        
        total_size = info->screen_size;
 
@@ -771,14 +773,37 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
         return 0;
 }
 
+static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
+                        u32 activate)
+{
+       struct fb_event event;
+       struct fb_blit_caps caps, fbcaps;
+       int err = 0;
+
+       memset(&caps, 0, sizeof(caps));
+       memset(&fbcaps, 0, sizeof(fbcaps));
+       caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
+       event.info = info;
+       event.data = &caps;
+       fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
+       info->fbops->fb_get_caps(info, &fbcaps, var);
+
+       if (((fbcaps.x ^ caps.x) & caps.x) ||
+           ((fbcaps.y ^ caps.y) & caps.y) ||
+           (fbcaps.len < caps.len))
+               err = -EINVAL;
+
+       return err;
+}
+
 int
 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
-       int err, flags = info->flags;
+       int flags = info->flags;
+       int ret = 0;
 
        if (var->activate & FB_ACTIVATE_INV_MODE) {
                struct fb_videomode mode1, mode2;
-               int ret = 0;
 
                fb_var_to_videomode(&mode1, var);
                fb_var_to_videomode(&mode2, &info->var);
@@ -796,40 +821,51 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                if (!ret)
                    fb_delete_videomode(&mode1, &info->modelist);
 
-               return ret;
+
+               ret = (ret) ? -EINVAL : 0;
+               goto done;
        }
 
        if ((var->activate & FB_ACTIVATE_FORCE) ||
            memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+               u32 activate = var->activate;
+
                if (!info->fbops->fb_check_var) {
                        *var = info->var;
-                       return 0;
+                       goto done;
                }
 
-               if ((err = info->fbops->fb_check_var(var, info)))
-                       return err;
+               ret = info->fbops->fb_check_var(var, info);
+
+               if (ret)
+                       goto done;
 
                if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
                        struct fb_videomode mode;
-                       int err = 0;
+
+                       if (info->fbops->fb_get_caps) {
+                               ret = fb_check_caps(info, var, activate);
+
+                               if (ret)
+                                       goto done;
+                       }
 
                        info->var = *var;
+
                        if (info->fbops->fb_set_par)
                                info->fbops->fb_set_par(info);
 
                        fb_pan_display(info, &info->var);
-
                        fb_set_cmap(&info->cmap, info);
-
                        fb_var_to_videomode(&mode, &info->var);
 
                        if (info->modelist.prev && info->modelist.next &&
                            !list_empty(&info->modelist))
-                               err = fb_add_videomode(&mode, &info->modelist);
+                               ret = fb_add_videomode(&mode, &info->modelist);
 
-                       if (!err && (flags & FBINFO_MISC_USEREVENT)) {
+                       if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
                                struct fb_event event;
-                               int evnt = (var->activate & FB_ACTIVATE_ALL) ?
+                               int evnt = (activate & FB_ACTIVATE_ALL) ?
                                        FB_EVENT_MODE_CHANGE_ALL :
                                        FB_EVENT_MODE_CHANGE;
 
@@ -839,7 +875,9 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                        }
                }
        }
-       return 0;
+
+ done:
+       return ret;
 }
 
 int
@@ -1198,6 +1236,10 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
 #elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__avr32__)
+       vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+                                     & ~_PAGE_CACHABLE)
+                                    | (_PAGE_BUFFER | _PAGE_DIRTY));
 #elif defined(__ia64__)
        if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
                vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -1266,6 +1308,9 @@ static const struct file_operations fb_fops = {
 #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
        .get_unmapped_area = get_fb_unmapped_area,
 #endif
+#ifdef CONFIG_FB_DEFERRED_IO
+       .fsync =        fb_deferred_io_fsync,
+#endif
 };
 
 struct class *fb_class;
@@ -1316,6 +1361,12 @@ register_framebuffer(struct fb_info *fb_info)
        }       
        fb_info->pixmap.offset = 0;
 
+       if (!fb_info->pixmap.blit_x)
+               fb_info->pixmap.blit_x = ~(u32)0;
+
+       if (!fb_info->pixmap.blit_y)
+               fb_info->pixmap.blit_y = ~(u32)0;
+
        if (!fb_info->modelist.prev || !fb_info->modelist.next)
                INIT_LIST_HEAD(&fb_info->modelist);
 
index 6b385c39b8b5cdc13b0ec781c72067aed810ef78..438b9411905c58e1536578b266a919e1df152a6d 100644 (file)
@@ -48,8 +48,9 @@
 #define DPRINTK(fmt, args...)
 #endif
 
-#define FBMON_FIX_HEADER 1
-#define FBMON_FIX_INPUT  2
+#define FBMON_FIX_HEADER  1
+#define FBMON_FIX_INPUT   2
+#define FBMON_FIX_TIMINGS 3
 
 #ifdef CONFIG_FB_MODE_HELPERS
 struct broken_edid {
@@ -71,6 +72,12 @@ static const struct broken_edid brokendb[] = {
                .model        = 0x5a44,
                .fix          = FBMON_FIX_INPUT,
        },
+       /* Sharp UXGA? */
+       {
+               .manufacturer = "SHP",
+               .model        = 0x138e,
+               .fix          = FBMON_FIX_TIMINGS,
+       },
 };
 
 static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
@@ -87,6 +94,55 @@ static void copy_string(unsigned char *c, unsigned char *s)
   while (i-- && (*--s == 0x20)) *s = 0;
 }
 
+static int edid_is_serial_block(unsigned char *block)
+{
+       if ((block[0] == 0x00) && (block[1] == 0x00) &&
+           (block[2] == 0x00) && (block[3] == 0xff) &&
+           (block[4] == 0x00))
+               return 1;
+       else
+               return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+       if ((block[0] == 0x00) && (block[1] == 0x00) &&
+           (block[2] == 0x00) && (block[3] == 0xfe) &&
+           (block[4] == 0x00))
+               return 1;
+       else
+               return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+       if ((block[0] == 0x00) && (block[1] == 0x00) &&
+           (block[2] == 0x00) && (block[3] == 0xfd) &&
+           (block[4] == 0x00))
+               return 1;
+       else
+               return 0;
+}
+
+static int edid_is_monitor_block(unsigned char *block)
+{
+       if ((block[0] == 0x00) && (block[1] == 0x00) &&
+           (block[2] == 0x00) && (block[3] == 0xfc) &&
+           (block[4] == 0x00))
+               return 1;
+       else
+               return 0;
+}
+
+static int edid_is_timing_block(unsigned char *block)
+{
+       if ((block[0] != 0x00) || (block[1] != 0x00) ||
+           (block[2] != 0x00) || (block[4] != 0x00))
+               return 1;
+       else
+               return 0;
+}
+
 static int check_edid(unsigned char *edid)
 {
        unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
@@ -104,9 +160,6 @@ static int check_edid(unsigned char *edid)
        for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
                if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
                        brokendb[i].model == model) {
-                       printk("fbmon: The EDID Block of "
-                              "Manufacturer: %s Model: 0x%x is known to "
-                              "be broken,\n",  manufacturer, model);
                        fix = brokendb[i].fix;
                        break;
                }
@@ -115,8 +168,10 @@ static int check_edid(unsigned char *edid)
        switch (fix) {
        case FBMON_FIX_HEADER:
                for (i = 0; i < 8; i++) {
-                       if (edid[i] != edid_v1_header[i])
+                       if (edid[i] != edid_v1_header[i]) {
                                ret = fix;
+                               break;
+                       }
                }
                break;
        case FBMON_FIX_INPUT:
@@ -126,14 +181,34 @@ static int check_edid(unsigned char *edid)
                if (b[4] & 0x01 && b[0] & 0x80)
                        ret = fix;
                break;
+       case FBMON_FIX_TIMINGS:
+               b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+               ret = fix;
+
+               for (i = 0; i < 4; i++) {
+                       if (edid_is_limits_block(b)) {
+                               ret = 0;
+                               break;
+                       }
+
+                       b += DETAILED_TIMING_DESCRIPTION_SIZE;
+               }
+
+               break;
        }
 
+       if (ret)
+               printk("fbmon: The EDID Block of "
+                      "Manufacturer: %s Model: 0x%x is known to "
+                      "be broken,\n",  manufacturer, model);
+
        return ret;
 }
 
 static void fix_edid(unsigned char *edid, int fix)
 {
-       unsigned char *b;
+       int i;
+       unsigned char *b, csum = 0;
 
        switch (fix) {
        case FBMON_FIX_HEADER:
@@ -145,6 +220,37 @@ static void fix_edid(unsigned char *edid, int fix)
                b = edid + EDID_STRUCT_DISPLAY;
                b[0] &= ~0x80;
                edid[127] += 0x80;
+               break;
+       case FBMON_FIX_TIMINGS:
+               printk("fbmon: trying to fix monitor timings\n");
+               b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+               for (i = 0; i < 4; i++) {
+                       if (!(edid_is_serial_block(b) ||
+                             edid_is_ascii_block(b) ||
+                             edid_is_monitor_block(b) ||
+                             edid_is_timing_block(b))) {
+                               b[0] = 0x00;
+                               b[1] = 0x00;
+                               b[2] = 0x00;
+                               b[3] = 0xfd;
+                               b[4] = 0x00;
+                               b[5] = 60;   /* vfmin */
+                               b[6] = 60;   /* vfmax */
+                               b[7] = 30;   /* hfmin */
+                               b[8] = 75;   /* hfmax */
+                               b[9] = 17;   /* pixclock - 170 MHz*/
+                               b[10] = 0;   /* GTF */
+                               break;
+                       }
+
+                       b += DETAILED_TIMING_DESCRIPTION_SIZE;
+               }
+
+               for (i = 0; i < EDID_LENGTH - 1; i++)
+                       csum += edid[i];
+
+               edid[127] = 256 - csum;
+               break;
        }
 }
 
@@ -273,46 +379,6 @@ static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
        DPRINTK("WhiteY:   0.%03d\n", specs->chroma.whitey);
 }
 
-static int edid_is_serial_block(unsigned char *block)
-{
-       if ((block[0] == 0x00) && (block[1] == 0x00) && 
-           (block[2] == 0x00) && (block[3] == 0xff) &&
-           (block[4] == 0x00))
-               return 1;
-       else
-               return 0;
-}
-
-static int edid_is_ascii_block(unsigned char *block)
-{
-       if ((block[0] == 0x00) && (block[1] == 0x00) && 
-           (block[2] == 0x00) && (block[3] == 0xfe) &&
-           (block[4] == 0x00))
-               return 1;
-       else
-               return 0;
-}
-
-static int edid_is_limits_block(unsigned char *block)
-{
-       if ((block[0] == 0x00) && (block[1] == 0x00) && 
-           (block[2] == 0x00) && (block[3] == 0xfd) &&
-           (block[4] == 0x00))
-               return 1;
-       else
-               return 0;
-}
-
-static int edid_is_monitor_block(unsigned char *block)
-{
-       if ((block[0] == 0x00) && (block[1] == 0x00) && 
-           (block[2] == 0x00) && (block[3] == 0xfc) &&
-           (block[4] == 0x00))
-               return 1;
-       else
-               return 0;
-}
-
 static void calc_mode_timings(int xres, int yres, int refresh,
                              struct fb_videomode *mode)
 {
@@ -795,15 +861,6 @@ static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
        }
 }
 
-static int edid_is_timing_block(unsigned char *block)
-{
-       if ((block[0] != 0x00) || (block[1] != 0x00) ||
-           (block[2] != 0x00) || (block[4] != 0x00))
-               return 1;
-       else
-               return 0;
-}
-
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
        int i;
index 40c80c8190e2f744dfc43e3f99fb08189a0c303e..d4a2c11d980975be84131abd3a94670a1e2f7c98 100644 (file)
@@ -376,7 +376,7 @@ static ssize_t show_pan(struct device *device,
 {
        struct fb_info *fb_info = dev_get_drvdata(device);
        return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
-                       fb_info->var.xoffset);
+                       fb_info->var.yoffset);
 }
 
 static ssize_t show_name(struct device *device,
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
new file mode 100644 (file)
index 0000000..abfcb50
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller
+ *
+ * Copyright (C) 2006, Jaya Kumar
+ * This work was sponsored by CIS(M) Sdn Bhd
+ *
+ * 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.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ * This work was possible because of apollo display code from E-Ink's website
+ * http://support.eink.com/community
+ * All information used to write this code is from public material made
+ * available by E-Ink on its support site. Some commands such as 0xA4
+ * were found by looping through cmd=0x00 thru 0xFF and supplying random
+ * values. There are other commands that the display is capable of,
+ * beyond the 5 used here but they are more complex.
+ *
+ * This driver is written to be used with the Hecuba display controller
+ * board, and tested with the EInk 800x600 display in 1 bit mode.
+ * The interface between Hecuba and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 6 lines for control.
+ * Only 4 of the controls are actually used here but 6 for future use.
+ * The driver requires the IO addresses for data and control GPIO at
+ * load time. It is also possible to use this display with a standard
+ * PC parallel port.
+ *
+ * General notes:
+ * - User must set hecubafb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+
+/* Apollo controller specific defines */
+#define APOLLO_START_NEW_IMG   0xA0
+#define APOLLO_STOP_IMG_DATA   0xA1
+#define APOLLO_DISPLAY_IMG     0xA2
+#define APOLLO_ERASE_DISPLAY   0xA3
+#define APOLLO_INIT_DISPLAY    0xA4
+
+/* Hecuba interface specific defines */
+/* WUP is inverted, CD is inverted, DS is inverted */
+#define HCB_NWUP_BIT   0x01
+#define HCB_NDS_BIT    0x02
+#define HCB_RW_BIT     0x04
+#define HCB_NCD_BIT    0x08
+#define HCB_ACK_BIT    0x80
+
+/* Display specific information */
+#define DPY_W 600
+#define DPY_H 800
+
+struct hecubafb_par {
+       unsigned long dio_addr;
+       unsigned long cio_addr;
+       unsigned long c2io_addr;
+       unsigned char ctl;
+       struct fb_info *info;
+       unsigned int irq;
+};
+
+static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
+       .id =           "hecubafb",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_MONO01,
+       .xpanstep =     0,
+       .ypanstep =     0,
+       .ywrapstep =    0,
+       .accel =        FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo hecubafb_var __devinitdata = {
+       .xres           = DPY_W,
+       .yres           = DPY_H,
+       .xres_virtual   = DPY_W,
+       .yres_virtual   = DPY_H,
+       .bits_per_pixel = 1,
+       .nonstd         = 1,
+};
+
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned int nosplash;
+static unsigned int hecubafb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq);
+
+static void hcb_set_ctl(struct hecubafb_par *par)
+{
+       outb(par->ctl, par->cio_addr);
+}
+
+static unsigned char hcb_get_ctl(struct hecubafb_par *par)
+{
+       return inb(par->c2io_addr);
+}
+
+static void hcb_set_data(struct hecubafb_par *par, unsigned char value)
+{
+       outb(value, par->dio_addr);
+}
+
+static int __devinit apollo_init_control(struct hecubafb_par *par)
+{
+       unsigned char ctl;
+       /* for init, we want the following setup to be set:
+       WUP = lo
+       ACK = hi
+       DS = hi
+       RW = hi
+       CD = lo
+       */
+
+       /* write WUP to lo, DS to hi, RW to hi, CD to lo */
+       par->ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ;
+       par->ctl &= ~HCB_NDS_BIT;
+       hcb_set_ctl(par);
+
+       /* check ACK is not lo */
+       ctl = hcb_get_ctl(par);
+       if ((ctl & HCB_ACK_BIT)) {
+               printk(KERN_ERR "Fail because ACK is already low\n");
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static void hcb_wait_for_ack(struct hecubafb_par *par)
+{
+
+       int timeout;
+       unsigned char ctl;
+
+       timeout=500;
+       do {
+               ctl = hcb_get_ctl(par);
+               if ((ctl & HCB_ACK_BIT))
+                       return;
+               udelay(1);
+       } while (timeout--);
+       printk(KERN_ERR "timed out waiting for ack\n");
+}
+
+static void hcb_wait_for_ack_clear(struct hecubafb_par *par)
+{
+
+       int timeout;
+       unsigned char ctl;
+
+       timeout=500;
+       do {
+               ctl = hcb_get_ctl(par);
+               if (!(ctl & HCB_ACK_BIT))
+                       return;
+               udelay(1);
+       } while (timeout--);
+       printk(KERN_ERR "timed out waiting for clear\n");
+}
+
+static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
+{
+       /* set data */
+       hcb_set_data(par, data);
+
+       /* set DS low */
+       par->ctl |= HCB_NDS_BIT;
+       hcb_set_ctl(par);
+
+       hcb_wait_for_ack(par);
+
+       /* set DS hi */
+       par->ctl &= ~(HCB_NDS_BIT);
+       hcb_set_ctl(par);
+
+       hcb_wait_for_ack_clear(par);
+}
+
+static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
+{
+       /* command so set CD to high */
+       par->ctl &= ~(HCB_NCD_BIT);
+       hcb_set_ctl(par);
+
+       /* actually strobe with command */
+       apollo_send_data(par, data);
+
+       /* clear CD back to low */
+       par->ctl |= (HCB_NCD_BIT);
+       hcb_set_ctl(par);
+}
+
+/* main hecubafb functions */
+
+static void hecubafb_dpy_update(struct hecubafb_par *par)
+{
+       int i;
+       unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+
+       apollo_send_command(par, 0xA0);
+
+       for (i=0; i < (DPY_W*DPY_H/8); i++) {
+               apollo_send_data(par, *(buf++));
+       }
+
+       apollo_send_command(par, 0xA1);
+       apollo_send_command(par, 0xA2);
+}
+
+/* this is called back from the deferred io workqueue */
+static void hecubafb_dpy_deferred_io(struct fb_info *info,
+                               struct list_head *pagelist)
+{
+       hecubafb_dpy_update(info->par);
+}
+
+static void hecubafb_fillrect(struct fb_info *info,
+                                  const struct fb_fillrect *rect)
+{
+       struct hecubafb_par *par = info->par;
+
+       sys_fillrect(info, rect);
+
+       hecubafb_dpy_update(par);
+}
+
+static void hecubafb_copyarea(struct fb_info *info,
+                                  const struct fb_copyarea *area)
+{
+       struct hecubafb_par *par = info->par;
+
+       sys_copyarea(info, area);
+
+       hecubafb_dpy_update(par);
+}
+
+static void hecubafb_imageblit(struct fb_info *info,
+                               const struct fb_image *image)
+{
+       struct hecubafb_par *par = info->par;
+
+       sys_imageblit(info, image);
+
+       hecubafb_dpy_update(par);
+}
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       unsigned long p;
+       int err=-EINVAL;
+       struct hecubafb_par *par;
+       unsigned int xres;
+       unsigned int fbmemlength;
+
+       p = *ppos;
+       par = info->par;
+       xres = info->var.xres;
+       fbmemlength = (xres * info->var.yres)/8;
+
+       if (p > fbmemlength)
+               return -ENOSPC;
+
+       err = 0;
+       if ((count + p) > fbmemlength) {
+               count = fbmemlength - p;
+               err = -ENOSPC;
+       }
+
+       if (count) {
+               char *base_addr;
+
+               base_addr = (char __force *)info->screen_base;
+               count -= copy_from_user(base_addr + p, buf, count);
+               *ppos += count;
+               err = -EFAULT;
+       }
+
+       hecubafb_dpy_update(par);
+
+       if (count)
+               return count;
+
+       return err;
+}
+
+static struct fb_ops hecubafb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_read        = fb_sys_read,
+       .fb_write       = hecubafb_write,
+       .fb_fillrect    = hecubafb_fillrect,
+       .fb_copyarea    = hecubafb_copyarea,
+       .fb_imageblit   = hecubafb_imageblit,
+};
+
+static struct fb_deferred_io hecubafb_defio = {
+       .delay          = HZ,
+       .deferred_io    = hecubafb_dpy_deferred_io,
+};
+
+static int __devinit hecubafb_probe(struct platform_device *dev)
+{
+       struct fb_info *info;
+       int retval = -ENOMEM;
+       int videomemorysize;
+       unsigned char *videomemory;
+       struct hecubafb_par *par;
+
+       videomemorysize = (DPY_W*DPY_H)/8;
+
+       if (!(videomemory = vmalloc(videomemorysize)))
+               return retval;
+
+       memset(videomemory, 0, videomemorysize);
+
+       info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
+       if (!info)
+               goto err;
+
+       info->screen_base = (char __iomem *) videomemory;
+       info->fbops = &hecubafb_ops;
+
+       info->var = hecubafb_var;
+       info->fix = hecubafb_fix;
+       info->fix.smem_len = videomemorysize;
+       par = info->par;
+       par->info = info;
+
+       if (!dio_addr || !cio_addr || !c2io_addr) {
+               printk(KERN_WARNING "no IO addresses supplied\n");
+               goto err1;
+       }
+       par->dio_addr = dio_addr;
+       par->cio_addr = cio_addr;
+       par->c2io_addr = c2io_addr;
+       info->flags = FBINFO_FLAG_DEFAULT;
+
+       info->fbdefio = &hecubafb_defio;
+       fb_deferred_io_init(info);
+
+       retval = register_framebuffer(info);
+       if (retval < 0)
+               goto err1;
+       platform_set_drvdata(dev, info);
+
+       printk(KERN_INFO
+              "fb%d: Hecuba frame buffer device, using %dK of video memory\n",
+              info->node, videomemorysize >> 10);
+
+       /* this inits the dpy */
+       apollo_init_control(par);
+
+       apollo_send_command(par, APOLLO_INIT_DISPLAY);
+       apollo_send_data(par, 0x81);
+
+       /* have to wait while display resets */
+       udelay(1000);
+
+       /* if we were told to splash the screen, we just clear it */
+       if (!nosplash) {
+               apollo_send_command(par, APOLLO_ERASE_DISPLAY);
+               apollo_send_data(par, splashval);
+       }
+
+       return 0;
+err1:
+       framebuffer_release(info);
+err:
+       vfree(videomemory);
+       return retval;
+}
+
+static int __devexit hecubafb_remove(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+
+       if (info) {
+               fb_deferred_io_cleanup(info);
+               unregister_framebuffer(info);
+               vfree((void __force *)info->screen_base);
+               framebuffer_release(info);
+       }
+       return 0;
+}
+
+static struct platform_driver hecubafb_driver = {
+       .probe  = hecubafb_probe,
+       .remove = hecubafb_remove,
+       .driver = {
+               .name   = "hecubafb",
+       },
+};
+
+static struct platform_device *hecubafb_device;
+
+static int __init hecubafb_init(void)
+{
+       int ret;
+
+       if (!hecubafb_enable) {
+               printk(KERN_ERR "Use hecubafb_enable to enable the device\n");
+               return -ENXIO;
+       }
+
+       ret = platform_driver_register(&hecubafb_driver);
+       if (!ret) {
+               hecubafb_device = platform_device_alloc("hecubafb", 0);
+               if (hecubafb_device)
+                       ret = platform_device_add(hecubafb_device);
+               else
+                       ret = -ENOMEM;
+
+               if (ret) {
+                       platform_device_put(hecubafb_device);
+                       platform_driver_unregister(&hecubafb_driver);
+               }
+       }
+       return ret;
+
+}
+
+static void __exit hecubafb_exit(void)
+{
+       platform_device_unregister(hecubafb_device);
+       platform_driver_unregister(&hecubafb_driver);
+}
+
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(hecubafb_enable, uint, 0);
+MODULE_PARM_DESC(hecubafb_enable, "Enable communication with Hecuba board");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
+module_param(irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ for the Hecuba board");
+
+module_init(hecubafb_init);
+module_exit(hecubafb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Hecuba board");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
index aa65ffce915b9a62db0ff615e11c1635578d6139..889e4ea5edc1292a3c8e9daa1daf8beb59cecf17 100644 (file)
 /* Masks (AND ops) and OR's */
 #define FB_START_MASK               (0x3f << (32 - 6))
 #define MMIO_ADDR_MASK              (0x1FFF << (32 - 13))
-#define FREQ_MASK                   0x1EF
+#define FREQ_MASK                   (1 << 4)
 #define SCR_OFF                     0x20
 #define DRAM_ON                     0x08            
 #define DRAM_OFF                    0xE7
index 7e760197cf29a9932e6533641da3919fc597ca51..1a7d7789d8772f600c6bb3100b86b50b68a45dab 100644 (file)
@@ -1717,7 +1717,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
  * @info: pointer to device specific info structure
  *
  * DESCRIPTION:
- * Sets the the user monitor's horizontal and vertical
+ * Sets the user monitor's horizontal and vertical
  * frequency limits
  */
 static void __devinit i810_init_monspecs(struct fb_info *info)
index c1eb18bf088392655f81886e9ccc9015ebcf6bd2..16bc8d75e36e758ce5ca4b922b5f4e0671c022b7 100644 (file)
@@ -1428,6 +1428,24 @@ static void refresh_ring(struct intelfb_info *dinfo);
 static void reset_state(struct intelfb_info *dinfo);
 static void do_flush(struct intelfb_info *dinfo);
 
+static  u32 get_ring_space(struct intelfb_info *dinfo)
+{
+       u32 ring_space;
+
+       if (dinfo->ring_tail >= dinfo->ring_head)
+               ring_space = dinfo->ring.size -
+                       (dinfo->ring_tail - dinfo->ring_head);
+       else
+               ring_space = dinfo->ring_head - dinfo->ring_tail;
+
+       if (ring_space > RING_MIN_FREE)
+               ring_space -= RING_MIN_FREE;
+       else
+               ring_space = 0;
+
+       return ring_space;
+}
+
 static int
 wait_ring(struct intelfb_info *dinfo, int n)
 {
@@ -1442,13 +1460,8 @@ wait_ring(struct intelfb_info *dinfo, int n)
        end = jiffies + (HZ * 3);
        while (dinfo->ring_space < n) {
                dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
-               if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
-                       dinfo->ring_space = dinfo->ring_head
-                               - (dinfo->ring_tail + RING_MIN_FREE);
-               else
-                       dinfo->ring_space = (dinfo->ring.size +
-                                            dinfo->ring_head)
-                               - (dinfo->ring_tail + RING_MIN_FREE);
+               dinfo->ring_space = get_ring_space(dinfo);
+
                if (dinfo->ring_head != last_head) {
                        end = jiffies + (HZ * 3);
                        last_head = dinfo->ring_head;
@@ -1513,12 +1526,7 @@ refresh_ring(struct intelfb_info *dinfo)
 
        dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
        dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
-       if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
-               dinfo->ring_space = dinfo->ring_head
-                       - (dinfo->ring_tail + RING_MIN_FREE);
-       else
-               dinfo->ring_space = (dinfo->ring.size + dinfo->ring_head)
-                       - (dinfo->ring_tail + RING_MIN_FREE);
+       dinfo->ring_space = get_ring_space(dinfo);
 }
 
 static void
index f0e6512c87ff4bd8e0acfdb3e7576c4e5405b428..9397bcef3018c6e95b22f01bc1429ea905383cce 100644 (file)
@@ -2,73 +2,69 @@
 # Logo configuration
 #
 
-menu "Logo configuration"
-
-config LOGO
+menuconfig LOGO
        bool "Bootup logo"
        depends on FB || SGI_NEWPORT_CONSOLE
        help
          Enable and select frame buffer bootup logos.
 
+if LOGO
+
 config LOGO_LINUX_MONO
        bool "Standard black and white Linux logo"
-       depends on LOGO
        default y
 
 config LOGO_LINUX_VGA16
        bool "Standard 16-color Linux logo"
-       depends on LOGO
        default y
 
 config LOGO_LINUX_CLUT224
        bool "Standard 224-color Linux logo"
-       depends on LOGO
        default y
 
 config LOGO_DEC_CLUT224
        bool "224-color Digital Equipment Corporation Linux logo"
-       depends on LOGO && (MACH_DECSTATION || ALPHA)
+       depends on MACH_DECSTATION || ALPHA
        default y
 
 config LOGO_MAC_CLUT224
        bool "224-color Macintosh Linux logo"
-       depends on LOGO && MAC
+       depends on MAC
        default y
 
 config LOGO_PARISC_CLUT224
        bool "224-color PA-RISC Linux logo"
-       depends on LOGO && PARISC
+       depends on PARISC
        default y
 
 config LOGO_SGI_CLUT224
        bool "224-color SGI Linux logo"
-       depends on LOGO && (SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS)
+       depends on SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS
        default y
 
 config LOGO_SUN_CLUT224
        bool "224-color Sun Linux logo"
-       depends on LOGO && SPARC
+       depends on SPARC
        default y
 
 config LOGO_SUPERH_MONO
        bool "Black and white SuperH Linux logo"
-       depends on LOGO && SUPERH
+       depends on SUPERH
        default y
 
 config LOGO_SUPERH_VGA16
        bool "16-color SuperH Linux logo"
-       depends on LOGO && SUPERH
+       depends on SUPERH
        default y
 
 config LOGO_SUPERH_CLUT224
        bool "224-color SuperH Linux logo"
-       depends on LOGO && SUPERH
+       depends on SUPERH
        default y
 
 config LOGO_M32R_CLUT224
        bool "224-color M32R Linux logo"
-       depends on LOGO && M32R
+       depends on M32R
        default y
 
-endmenu
-
+endif # LOGO
index a5690a5f29d585f69f069c43e7b783af8f494475..9445cdb759b1f090d21ffa6bb1a30bde8dccfbe5 100644 (file)
@@ -72,7 +72,7 @@
  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  *
  * (following author is not in any relation with this code, but his ideas
- *  were used when writting this driver)
+ *  were used when writing this driver)
  *
  *              FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  *
index a5c825d994661090c990e6423fb6245a063902b1..c57aaadf410c9d5a6cfe030282315311aecbb585 100644 (file)
@@ -70,7 +70,7 @@
  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  *
  * (following author is not in any relation with this code, but his ideas
- *  were used when writting this driver)
+ *  were used when writing this driver)
  *
  *              FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  *
index cb2aa402ddfd93eb0b180f9a05c74909c2be859a..c8559a756b75ff5bbe017c43cea941160d002168 100644 (file)
@@ -93,7 +93,7 @@
  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  *
  * (following author is not in any relation with this code, but his ideas
- *  were used when writting this driver)
+ *  were used when writing this driver)
  *
  *              FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  *
index 18886b629cb1bb3c8fcea5cb9a0f4132f0fdb20c..5948e54b9ef9ceb68e2914a30f7600667c771569 100644 (file)
@@ -78,7 +78,7 @@
  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  *
  * (following author is not in any relation with this code, but his ideas
- *  were used when writting this driver)
+ *  were used when writing this driver)
  *
  *              FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  *
index 3e517940c5a581cdd30f960803e001176bd4b88d..3741ad729401c02226a60b8d7a0a20e9e3638579 100644 (file)
@@ -395,7 +395,7 @@ static int my_atoi(const char *name)
 
     for (;; name++) {
        switch (*name) {
-           case '0'...'9':
+           case '0' ... '9':
                val = 10*val+(*name-'0');
                break;
            default:
@@ -548,7 +548,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                    } else
                        goto done;
                    break;
-               case '0'...'9':
+               case '0' ... '9':
                    break;
                case 'M':
                    if (!yres_specified)
index 395ccedde9a63b5718afdefb34d3f3c4f7235db8..bd30aba242d07643722ef8d58aa1870128a3bec3 100644 (file)
@@ -665,6 +665,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        var->red.msb_right = 0;
        var->green.msb_right = 0;
        var->blue.msb_right = 0;
+       var->transp.msb_right = 0;
 
        switch (var->bits_per_pixel) {
        case 8:         /* PSEUDOCOLOUR, 256 */
index 9efb8a3854e2671d18b5f944b855035a3c9c0029..fa4821c5572b7904a9fbcc21510f3737a4cfe2bd 100644 (file)
@@ -69,27 +69,38 @@ static const int NVCopyROP_PM[16] = {
        0x5A,                   /* invert */
 };
 
-static inline void NVFlush(struct nvidia_par *par)
+static inline void nvidiafb_safe_mode(struct fb_info *info)
 {
+       struct nvidia_par *par = info->par;
+
+       touch_softlockup_watchdog();
+       info->pixmap.scan_align = 1;
+       par->lockup = 1;
+}
+
+static inline void NVFlush(struct fb_info *info)
+{
+       struct nvidia_par *par = info->par;
        int count = 1000000000;
 
        while (--count && READ_GET(par) != par->dmaPut) ;
 
        if (!count) {
                printk("nvidiafb: DMA Flush lockup\n");
-               par->lockup = 1;
+               nvidiafb_safe_mode(info);
        }
 }
 
-static inline void NVSync(struct nvidia_par *par)
+static inline void NVSync(struct fb_info *info)
 {
+       struct nvidia_par *par = info->par;
        int count = 1000000000;
 
        while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
 
        if (!count) {
                printk("nvidiafb: DMA Sync lockup\n");
-               par->lockup = 1;
+               nvidiafb_safe_mode(info);
        }
 }
 
@@ -101,8 +112,9 @@ static void NVDmaKickoff(struct nvidia_par *par)
        }
 }
 
-static void NVDmaWait(struct nvidia_par *par, int size)
+static void NVDmaWait(struct fb_info *info, int size)
 {
+       struct nvidia_par *par = info->par;
        int dmaGet;
        int count = 1000000000, cnt;
        size++;
@@ -135,34 +147,38 @@ static void NVDmaWait(struct nvidia_par *par, int size)
        }
 
        if (!count) {
-               printk("DMA Wait Lockup\n");
-               par->lockup = 1;
+               printk("nvidiafb: DMA Wait Lockup\n");
+               nvidiafb_safe_mode(info);
        }
 }
 
-static void NVSetPattern(struct nvidia_par *par, u32 clr0, u32 clr1,
+static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1,
                         u32 pat0, u32 pat1)
 {
-       NVDmaStart(par, PATTERN_COLOR_0, 4);
+       struct nvidia_par *par = info->par;
+
+       NVDmaStart(info, par, PATTERN_COLOR_0, 4);
        NVDmaNext(par, clr0);
        NVDmaNext(par, clr1);
        NVDmaNext(par, pat0);
        NVDmaNext(par, pat1);
 }
 
-static void NVSetRopSolid(struct nvidia_par *par, u32 rop, u32 planemask)
+static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask)
 {
+       struct nvidia_par *par = info->par;
+
        if (planemask != ~0) {
-               NVSetPattern(par, 0, planemask, ~0, ~0);
+               NVSetPattern(info, 0, planemask, ~0, ~0);
                if (par->currentRop != (rop + 32)) {
-                       NVDmaStart(par, ROP_SET, 1);
+                       NVDmaStart(info, par, ROP_SET, 1);
                        NVDmaNext(par, NVCopyROP_PM[rop]);
                        par->currentRop = rop + 32;
                }
        } else if (par->currentRop != rop) {
                if (par->currentRop >= 16)
-                       NVSetPattern(par, ~0, ~0, ~0, ~0);
-               NVDmaStart(par, ROP_SET, 1);
+                       NVSetPattern(info, ~0, ~0, ~0, ~0);
+               NVDmaStart(info, par, ROP_SET, 1);
                NVDmaNext(par, NVCopyROP[rop]);
                par->currentRop = rop;
        }
@@ -175,7 +191,7 @@ static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
        int h = y2 - y1 + 1;
        int w = x2 - x1 + 1;
 
-       NVDmaStart(par, CLIP_POINT, 2);
+       NVDmaStart(info, par, CLIP_POINT, 2);
        NVDmaNext(par, (y1 << 16) | x1);
        NVDmaNext(par, (h << 16) | w);
 }
@@ -237,23 +253,23 @@ void NVResetGraphics(struct fb_info *info)
                break;
        }
 
-       NVDmaStart(par, SURFACE_FORMAT, 4);
+       NVDmaStart(info, par, SURFACE_FORMAT, 4);
        NVDmaNext(par, surfaceFormat);
        NVDmaNext(par, pitch | (pitch << 16));
        NVDmaNext(par, 0);
        NVDmaNext(par, 0);
 
-       NVDmaStart(par, PATTERN_FORMAT, 1);
+       NVDmaStart(info, par, PATTERN_FORMAT, 1);
        NVDmaNext(par, patternFormat);
 
-       NVDmaStart(par, RECT_FORMAT, 1);
+       NVDmaStart(info, par, RECT_FORMAT, 1);
        NVDmaNext(par, rectFormat);
 
-       NVDmaStart(par, LINE_FORMAT, 1);
+       NVDmaStart(info, par, LINE_FORMAT, 1);
        NVDmaNext(par, lineFormat);
 
        par->currentRop = ~0;   /* set to something invalid */
-       NVSetRopSolid(par, ROP_COPY, ~0);
+       NVSetRopSolid(info, ROP_COPY, ~0);
 
        NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
                               info->var.yres_virtual);
@@ -269,10 +285,10 @@ int nvidiafb_sync(struct fb_info *info)
                return 0;
 
        if (!par->lockup)
-               NVFlush(par);
+               NVFlush(info);
 
        if (!par->lockup)
-               NVSync(par);
+               NVSync(info);
 
        return 0;
 }
@@ -287,7 +303,7 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
        if (par->lockup)
                return cfb_copyarea(info, region);
 
-       NVDmaStart(par, BLIT_POINT_SRC, 3);
+       NVDmaStart(info, par, BLIT_POINT_SRC, 3);
        NVDmaNext(par, (region->sy << 16) | region->sx);
        NVDmaNext(par, (region->dy << 16) | region->dx);
        NVDmaNext(par, (region->height << 16) | region->width);
@@ -312,19 +328,19 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
                color = ((u32 *) info->pseudo_palette)[rect->color];
 
        if (rect->rop != ROP_COPY)
-               NVSetRopSolid(par, rect->rop, ~0);
+               NVSetRopSolid(info, rect->rop, ~0);
 
-       NVDmaStart(par, RECT_SOLID_COLOR, 1);
+       NVDmaStart(info, par, RECT_SOLID_COLOR, 1);
        NVDmaNext(par, color);
 
-       NVDmaStart(par, RECT_SOLID_RECTS(0), 2);
+       NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2);
        NVDmaNext(par, (rect->dx << 16) | rect->dy);
        NVDmaNext(par, (rect->width << 16) | rect->height);
 
        NVDmaKickoff(par);
 
        if (rect->rop != ROP_COPY)
-               NVSetRopSolid(par, ROP_COPY, ~0);
+               NVSetRopSolid(info, ROP_COPY, ~0);
 }
 
 static void nvidiafb_mono_color_expand(struct fb_info *info,
@@ -346,7 +362,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
                bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
        }
 
-       NVDmaStart(par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
+       NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
        NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
        NVDmaNext(par, ((image->dy + image->height) << 16) |
                  ((image->dx + image->width) & 0xffff));
@@ -357,7 +373,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
        NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
 
        while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
-               NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0),
+               NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0),
                           RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
 
                for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
@@ -370,7 +386,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
        }
 
        if (dsize) {
-               NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+               NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
 
                for (j = dsize; j--;) {
                        tmp = data[k++];
index ea426115c6f952ed3a83198cf8ce30adebadf80e..c627955aa124797cd41019816744d99c828fbca1 100644 (file)
@@ -149,8 +149,7 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
                pll = NV_RD32(par->PMC, 0x4024);
                M = pll & 0xFF;
                N = (pll >> 8) & 0xFF;
-               if (((par->Chipset & 0xfff0) == 0x0290) ||
-                               ((par->Chipset & 0xfff0) == 0x0390)) {
+               if (((par->Chipset & 0xfff0) == 0x0290) || ((par->Chipset & 0xfff0) == 0x0390) || ((par->Chipset & 0xfff0) == 0x02E0)) {
                        MB = 1;
                        NB = 1;
                } else {
@@ -686,7 +685,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk,
 
        if ((par->Chipset & 0x0FF0) == 0x01A0) {
                unsigned int uMClkPostDiv;
-               dev = pci_find_slot(0, 3);
+               dev = pci_get_bus_and_slot(0, 3);
                pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
                uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
 
@@ -694,11 +693,11 @@ static void nForceUpdateArbitrationSettings(unsigned VClk,
                        uMClkPostDiv = 4;
                MClk = 400000 / uMClkPostDiv;
        } else {
-               dev = pci_find_slot(0, 5);
+               dev = pci_get_bus_and_slot(0, 5);
                pci_read_config_dword(dev, 0x4c, &MClk);
                MClk /= 1000;
        }
-
+       pci_dev_put(dev);
        pll = NV_RD32(par->PRAMDAC0, 0x0500);
        M = (pll >> 0) & 0xFF;
        N = (pll >> 8) & 0xFF;
@@ -707,19 +706,21 @@ static void nForceUpdateArbitrationSettings(unsigned VClk,
        sim_data.pix_bpp = (char)pixelDepth;
        sim_data.enable_video = 0;
        sim_data.enable_mp = 0;
-       pci_find_slot(0, 1);
+       dev = pci_get_bus_and_slot(0, 1);
        pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+       pci_dev_put(dev);
        sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
        sim_data.memory_width = 64;
 
-       dev = pci_find_slot(0, 3);
+       dev = pci_get_bus_and_slot(0, 3);
        pci_read_config_dword(dev, 0, &memctrl);
+       pci_dev_put(dev);
        memctrl >>= 16;
 
        if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
                int dimm[3];
 
-               pci_find_slot(0, 2);
+               dev = pci_get_bus_and_slot(0, 2);
                pci_read_config_dword(dev, 0x40, &dimm[0]);
                dimm[0] = (dimm[0] >> 8) & 0x4f;
                pci_read_config_dword(dev, 0x44, &dimm[1]);
@@ -731,6 +732,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk,
                        printk("nvidiafb: your nForce DIMMs are not arranged "
                               "in optimal banks!\n");
                }
+               pci_dev_put(dev);
        }
 
        sim_data.mem_latency = 3;
@@ -960,6 +962,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 
                if (((par->Chipset & 0xfff0) == 0x0090) ||
                    ((par->Chipset & 0xfff0) == 0x01D0) ||
+                   ((par->Chipset & 0xfff0) == 0x02E0) ||
                    ((par->Chipset & 0xfff0) == 0x0290))
                        regions = 15;
                for(i = 0; i < regions; i++) {
@@ -1272,6 +1275,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
                                                0x00100000);
                                        break;
                                case 0x0090:
+                               case 0x02E0:
                                case 0x0290:
                                        NV_WR32(par->PRAMDAC, 0x0608,
                                                NV_RD32(par->PRAMDAC, 0x0608) |
@@ -1349,6 +1353,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
                        } else {
                                if (((par->Chipset & 0xfff0) == 0x0090) ||
                                    ((par->Chipset & 0xfff0) == 0x01D0) ||
+                                   ((par->Chipset & 0xfff0) == 0x02E0) ||
                                    ((par->Chipset & 0xfff0) == 0x0290)) {
                                        for (i = 0; i < 60; i++) {
                                                NV_WR32(par->PGRAPH,
@@ -1400,6 +1405,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
                                } else {
                                        if ((par->Chipset & 0xfff0) == 0x0090 ||
                                            (par->Chipset & 0xfff0) == 0x01D0 ||
+                                           (par->Chipset & 0xfff0) == 0x02E0 ||
                                            (par->Chipset & 0xfff0) == 0x0290) {
                                                NV_WR32(par->PGRAPH, 0x0DF0,
                                                        NV_RD32(par->PFB, 0x0200));
index b8588973e400936eec3f3dccd2c3400affcf298b..afe4567e1ff48d5c728315f9f81018e8a9ccb982 100644 (file)
@@ -30,16 +30,14 @@ static void nvidia_gpio_setscl(void *data, int state)
        struct nvidia_par *par = chan->par;
        u32 val;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
-       val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+       val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
 
        if (state)
                val |= 0x20;
        else
                val &= ~0x20;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
-       VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+       NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
 }
 
 static void nvidia_gpio_setsda(void *data, int state)
@@ -48,16 +46,14 @@ static void nvidia_gpio_setsda(void *data, int state)
        struct nvidia_par *par = chan->par;
        u32 val;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
-       val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+       val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
 
        if (state)
                val |= 0x10;
        else
                val &= ~0x10;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
-       VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+       NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
 }
 
 static int nvidia_gpio_getscl(void *data)
@@ -66,12 +62,9 @@ static int nvidia_gpio_getscl(void *data)
        struct nvidia_par *par = chan->par;
        u32 val = 0;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
-       if (VGA_RD08(par->PCIO, 0x3d5) & 0x04)
+       if (NVReadCrtc(par, chan->ddc_base) & 0x04)
                val = 1;
 
-       val = VGA_RD08(par->PCIO, 0x3d5);
-
        return val;
 }
 
@@ -81,20 +74,21 @@ static int nvidia_gpio_getsda(void *data)
        struct nvidia_par *par = chan->par;
        u32 val = 0;
 
-       VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
-       if (VGA_RD08(par->PCIO, 0x3d5) & 0x08)
+       if (NVReadCrtc(par, chan->ddc_base) & 0x08)
                val = 1;
 
        return val;
 }
 
-static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
+static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
+                               unsigned int i2c_class)
 {
        int rc;
 
        strcpy(chan->adapter.name, name);
        chan->adapter.owner = THIS_MODULE;
        chan->adapter.id = I2C_HW_B_NVIDIA;
+       chan->adapter.class = i2c_class;
        chan->adapter.algo_data = &chan->algo;
        chan->adapter.dev.parent = &chan->par->pci_dev->dev;
        chan->algo.setsda = nvidia_gpio_setsda;
@@ -127,83 +121,39 @@ static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
 
 void nvidia_create_i2c_busses(struct nvidia_par *par)
 {
-       par->bus = 3;
-
        par->chan[0].par = par;
        par->chan[1].par = par;
        par->chan[2].par = par;
 
-       par->chan[0].ddc_base = 0x3e;
-       nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0");
+       par->chan[0].ddc_base = 0x36;
+       nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0", I2C_CLASS_HWMON);
 
-       par->chan[1].ddc_base = 0x36;
-       nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1");
+       par->chan[1].ddc_base = 0x3e;
+       nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1", 0);
 
        par->chan[2].ddc_base = 0x50;
-       nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2");
+       nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);
 }
 
 void nvidia_delete_i2c_busses(struct nvidia_par *par)
 {
-       if (par->chan[0].par)
-               i2c_del_adapter(&par->chan[0].adapter);
-       par->chan[0].par = NULL;
-
-       if (par->chan[1].par)
-               i2c_del_adapter(&par->chan[1].adapter);
-       par->chan[1].par = NULL;
-
-       if (par->chan[2].par)
-               i2c_del_adapter(&par->chan[2].adapter);
-       par->chan[2].par = NULL;
-
-}
+       int i;
 
-static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
-{
-       u8 start = 0x0;
-       struct i2c_msg msgs[] = {
-               {
-                .addr = 0x50,
-                .len = 1,
-                .buf = &start,
-                }, {
-                    .addr = 0x50,
-                    .flags = I2C_M_RD,
-                    .len = EDID_LENGTH,
-                    },
-       };
-       u8 *buf;
-
-       if (!chan->par)
-               return NULL;
-
-       buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
-       if (!buf) {
-               dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n");
-               return NULL;
+       for (i = 0; i < 3; i++) {
+               if (!par->chan[i].par)
+                       continue;
+               i2c_del_adapter(&par->chan[i].adapter);
+               par->chan[i].par = NULL;
        }
-       msgs[1].buf = buf;
-
-       if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
-               return buf;
-       dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n");
-       kfree(buf);
-       return NULL;
 }
 
 int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
 {
        struct nvidia_par *par = info->par;
        u8 *edid = NULL;
-       int i;
 
-       for (i = 0; i < 3; i++) {
-               /* Do the real work */
-               edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]);
-               if (edid)
-                       break;
-       }
+       if (par->chan[conn - 1].par)
+               edid = fb_ddc_read(&par->chan[conn - 1].adapter);
 
        if (!edid && conn == 1) {
                /* try to get from firmware */
index e009d242ea10c6de95bb0edf11e78a58619c1f68..68e508daa417e4861b14ea492faa0205302b7fe6 100644 (file)
@@ -73,9 +73,9 @@
 #define NVDmaNext(par, data) \
      NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
 
-#define NVDmaStart(par, tag, size) {          \
+#define NVDmaStart(info, par, tag, size) {    \
      if((par)->dmaFree <= (size))             \
-        NVDmaWait(par, size);                 \
+        NVDmaWait(info, size);                \
      NVDmaNext(par, ((size) << 18) | (tag));  \
      (par)->dmaFree -= ((size) + 1);          \
 }
index 163a774a1b30bdbfb95471b1b56d16dc7edca209..73afd7eb9977b4b34d22254aa3f57bb6199a3426 100644 (file)
@@ -46,15 +46,15 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
 
                for (dp = NULL;
                     (dp = of_get_next_child(parent, dp)) != NULL;) {
-                       pname = get_property(dp, "name", NULL);
+                       pname = of_get_property(dp, "name", NULL);
                        if (!pname)
                                continue;
                        len = strlen(pname);
                        if ((pname[len-1] == 'A' && conn == 1) ||
                            (pname[len-1] == 'B' && conn == 2)) {
                                for (i = 0; propnames[i] != NULL; ++i) {
-                                       pedid = get_property(dp, propnames[i],
-                                                            NULL);
+                                       pedid = of_get_property(dp,
+                                                       propnames[i], NULL);
                                        if (pedid != NULL)
                                                break;
                                }
@@ -65,7 +65,7 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
        }
        if (pedid == NULL) {
                for (i = 0; propnames[i] != NULL; ++i) {
-                       pedid = get_property(parent, propnames[i], NULL);
+                       pedid = of_get_property(parent, propnames[i], NULL);
                        if (pedid != NULL)
                                break;
                }
index eab3e282a4de17f6bb736f64d3aa3aa78104a11c..707e2c8a13ed85929f32df1a91488405812506d8 100644 (file)
@@ -261,7 +261,7 @@ static void nv10GetConfig(struct nvidia_par *par)
        }
 #endif
 
-       dev = pci_find_slot(0, 1);
+       dev = pci_get_bus_and_slot(0, 1);
        if ((par->Chipset & 0xffff) == 0x01a0) {
                int amt = 0;
 
@@ -276,6 +276,7 @@ static void nv10GetConfig(struct nvidia_par *par)
                par->RamAmountKBytes =
                    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
        }
+       pci_dev_put(dev);
 
        par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
            14318 : 13500;
@@ -656,7 +657,7 @@ int NVCommonSetup(struct fb_info *info)
        par->LVDS = 0;
        if (par->FlatPanel && par->twoHeads) {
                NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004);
-               if (par->PRAMDAC0[0x08b4] & 1)
+               if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1)
                        par->LVDS = 1;
                printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS");
        }
index 86e65dea60d3a9b2aebf2136d7a2a93526a0b6f5..38f7cc0a23312a9701f0626a0f2f0457c9841279 100644 (file)
@@ -4,8 +4,9 @@
 #include <linux/fb.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
-#include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/mutex.h>
+#include <video/vga.h>
 
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
@@ -94,13 +95,15 @@ struct riva_regs {
 struct nvidia_par {
        RIVA_HW_STATE SavedReg;
        RIVA_HW_STATE ModeReg;
+       RIVA_HW_STATE initial_state;
        RIVA_HW_STATE *CurrentState;
+       struct vgastate vgastate;
+       struct mutex open_lock;
        u32 pseudo_palette[16];
        struct pci_dev *pci_dev;
        u32 Architecture;
        u32 CursorStart;
        int Chipset;
-       int bus;
        unsigned long FbAddress;
        u8 __iomem *FbStart;
        u32 FbMapSize;
@@ -143,6 +146,7 @@ struct nvidia_par {
        int BlendingPossible;
        u32 paletteEnabled;
        u32 forceCRTC;
+       u32 open_count;
        u8 DDCBase;
 #ifdef CONFIG_MTRR
        struct {
index b97ec6901263ab02bef1fd4e77bb8c390b91f2f5..f85edf084da3e0fc3f54c34a7333a637bfabbe39 100644 (file)
@@ -200,7 +200,7 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
    return tweak;
 }
 
-static void nvidia_vga_protect(struct nvidia_par *par, int on)
+static void nvidia_screen_off(struct nvidia_par *par, int on)
 {
        unsigned char tmp;
 
@@ -649,7 +649,7 @@ static int nvidiafb_set_par(struct fb_info *info)
                NVLockUnlock(par, 0);
        }
 
-       nvidia_vga_protect(par, 1);
+       nvidia_screen_off(par, 1);
 
        nvidia_write_regs(par, &par->ModeReg);
        NVSetStartAddress(par, 0);
@@ -687,7 +687,7 @@ static int nvidiafb_set_par(struct fb_info *info)
 
        par->cursor_reset = 1;
 
-       nvidia_vga_protect(par, 0);
+       nvidia_screen_off(par, 0);
 
 #ifdef CONFIG_BOOTX_TEXT
        /* Update debug text engine */
@@ -696,6 +696,7 @@ static int nvidiafb_set_par(struct fb_info *info)
                             info->var.bits_per_pixel, info->fix.line_length);
 #endif
 
+       NVLockUnlock(par, 0);
        NVTRACE_LEAVE();
        return 0;
 }
@@ -948,8 +949,80 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
        return 0;
 }
 
+/*
+ * Because the VGA registers are not mapped linearly in its MMIO space,
+ * restrict VGA register saving and restore to x86 only, where legacy VGA IO
+ * access is legal. Consequently, we must also check if the device is the
+ * primary display.
+ */
+#ifdef CONFIG_X86
+static void save_vga_x86(struct nvidia_par *par)
+{
+       struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
+
+       if (res && res->flags & IORESOURCE_ROM_SHADOW) {
+               memset(&par->vgastate, 0, sizeof(par->vgastate));
+               par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS |
+                       VGA_SAVE_CMAP;
+               save_vga(&par->vgastate);
+       }
+}
+
+static void restore_vga_x86(struct nvidia_par *par)
+{
+       struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
+
+       if (res && res->flags & IORESOURCE_ROM_SHADOW)
+               restore_vga(&par->vgastate);
+}
+#else
+#define save_vga_x86(x) do {} while (0)
+#define restore_vga_x86(x) do {} while (0)
+#endif /* X86 */
+
+static int nvidiafb_open(struct fb_info *info, int user)
+{
+       struct nvidia_par *par = info->par;
+
+       mutex_lock(&par->open_lock);
+
+       if (!par->open_count) {
+               save_vga_x86(par);
+               nvidia_save_vga(par, &par->initial_state);
+       }
+
+       par->open_count++;
+       mutex_unlock(&par->open_lock);
+       return 0;
+}
+
+static int nvidiafb_release(struct fb_info *info, int user)
+{
+       struct nvidia_par *par = info->par;
+       int err = 0;
+
+       mutex_lock(&par->open_lock);
+
+       if (!par->open_count) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (par->open_count == 1) {
+               nvidia_write_regs(par, &par->initial_state);
+               restore_vga_x86(par);
+       }
+
+       par->open_count--;
+done:
+       mutex_unlock(&par->open_lock);
+       return err;
+}
+
 static struct fb_ops nvidia_fb_ops = {
        .owner          = THIS_MODULE,
+       .fb_open        = nvidiafb_open,
+       .fb_release     = nvidiafb_release,
        .fb_check_var   = nvidiafb_check_var,
        .fb_set_par     = nvidiafb_set_par,
        .fb_setcolreg   = nvidiafb_setcolreg,
@@ -1170,6 +1243,7 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info)
        case 0x0140:            /* GeForce 6600 */
        case 0x0160:            /* GeForce 6200 */
        case 0x01D0:            /* GeForce 7200, 7300, 7400 */
+       case 0x02E0:            /* GeForce 7300 GT */
        case 0x0090:            /* GeForce 7800 */
        case 0x0210:            /* GeForce 6800 */
        case 0x0220:            /* GeForce 6200 */
@@ -1207,7 +1281,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
 
        par = info->par;
        par->pci_dev = pd;
-
+       mutex_init(&par->open_lock);
        info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
 
        if (info->pixmap.addr == NULL)
index 9576a55eaf165c73b1489f700ecd0df205a5f798..885b42836cbb31f81b142154305fc90b335c5d18 100644 (file)
@@ -322,8 +322,8 @@ static void __init offb_init_fb(const char *name, const char *full_name,
                            ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
                        par->cmap_data = par->cmap_adr + 1;
                        par->cmap_type = cmap_m64;
-               } else if (dp && (device_is_compatible(dp, "pci1014,b7") ||
-                                 device_is_compatible(dp, "pci1014,21c"))) {
+               } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+                                 of_device_is_compatible(dp, "pci1014,21c"))) {
                        par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
                        if (par->cmap_adr)
                                par->cmap_type = cmap_gxt2000;
@@ -425,27 +425,27 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        const u32 *pp, *addrp, *up;
        u64 asize;
 
-       pp = get_property(dp, "linux,bootx-depth", &len);
+       pp = of_get_property(dp, "linux,bootx-depth", &len);
        if (pp == NULL)
-               pp = get_property(dp, "depth", &len);
+               pp = of_get_property(dp, "depth", &len);
        if (pp && len == sizeof(u32))
                depth = *pp;
 
-       pp = get_property(dp, "linux,bootx-width", &len);
+       pp = of_get_property(dp, "linux,bootx-width", &len);
        if (pp == NULL)
-               pp = get_property(dp, "width", &len);
+               pp = of_get_property(dp, "width", &len);
        if (pp && len == sizeof(u32))
                width = *pp;
 
-       pp = get_property(dp, "linux,bootx-height", &len);
+       pp = of_get_property(dp, "linux,bootx-height", &len);
        if (pp == NULL)
-               pp = get_property(dp, "height", &len);
+               pp = of_get_property(dp, "height", &len);
        if (pp && len == sizeof(u32))
                height = *pp;
 
-       pp = get_property(dp, "linux,bootx-linebytes", &len);
+       pp = of_get_property(dp, "linux,bootx-linebytes", &len);
        if (pp == NULL)
-               pp = get_property(dp, "linebytes", &len);
+               pp = of_get_property(dp, "linebytes", &len);
        if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
                pitch = *pp;
        else
@@ -463,9 +463,9 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
         * ranges and pick one that is both big enough and if possible encloses
         * the "address" property. If none match, we pick the biggest
         */
-       up = get_property(dp, "linux,bootx-addr", &len);
+       up = of_get_property(dp, "linux,bootx-addr", &len);
        if (up == NULL)
-               up = get_property(dp, "address", &len);
+               up = of_get_property(dp, "address", &len);
        if (up && len == sizeof(u32))
                addr_prop = *up;
 
@@ -521,7 +521,7 @@ static int __init offb_init(void)
                return -ENODEV;
 
        /* Check if we have a MacOS display without a node spec */
-       if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
+       if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
                /* The old code tried to work out which node was the MacOS
                 * display based on the address. I'm dropping that since the
                 * lack of a node spec only happens with old BootX versions
@@ -532,14 +532,14 @@ static int __init offb_init(void)
        }
 
        for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-               if (get_property(dp, "linux,opened", NULL) &&
-                   get_property(dp, "linux,boot-display", NULL)) {
+               if (of_get_property(dp, "linux,opened", NULL) &&
+                   of_get_property(dp, "linux,boot-display", NULL)) {
                        boot_disp = dp;
                        offb_init_nodriver(dp, 0);
                }
        }
        for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-               if (get_property(dp, "linux,opened", NULL) &&
+               if (of_get_property(dp, "linux,opened", NULL) &&
                    dp != boot_disp)
                        offb_init_nodriver(dp, 0);
        }
index a560a2223825ae74ba600b75f8853a6f5c8fb716..1ac5264bb2c150cdfeee12b5c43203aab6bcc7c1 100644 (file)
@@ -81,8 +81,6 @@ static int lowvsync;
 struct pm2fb_par
 {
        pm2type_t       type;           /* Board type */
-       u32             fb_size;        /* framebuffer memory size */
-       unsigned char   __iomem *v_fb;  /* virtual address of frame buffer */
        unsigned char   __iomem *v_regs;/* virtual address of p_regs */
        u32             memclock;       /* memclock */
        u32             video;          /* video flags before blanking */
@@ -103,7 +101,7 @@ static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
        .xpanstep =     1,
        .ypanstep =     1,
        .ywrapstep =    0, 
-       .accel =        FB_ACCEL_NONE,
+       .accel =        FB_ACCEL_3DLABS_PERMEDIA2,
 };
 
 /*
@@ -206,6 +204,17 @@ static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
 }
 #endif
 
+static void wait_pm2(struct pm2fb_par* par) {
+
+       WAIT_FIFO(par, 1);
+       pm2_WR(par, PM2R_SYNC, 0);
+       mb();
+       do {
+               while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0);
+               rmb();
+       } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
+}
+
 /*
  * partial products for the supported horizontal resolutions.
  */
@@ -302,10 +311,10 @@ static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
        s32 delta = 1000;
 
        *mm = *nn = *pp = 0;
-       for (n = 1; n; n++) {
-               for ( m = 1; m; m++) {
+       for ( m = 1; m < 128; m++) {
+               for (n = 2 * m + 1; n; n++) {
                        for ( p = 0; p < 2; p++) {
-                               f = PM2_REFERENCE_CLOCK * n / (m * (1 << (p + 1)));
+                               f = ( PM2_REFERENCE_CLOCK >> ( p + 1 )) * n / m;
                                if ( clk > f - delta && clk < f + delta ) {
                                        delta = ( clk > f ) ? clk - f : f - clk;
                                        *mm=m;
@@ -462,21 +471,43 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
        int i;
        unsigned char m, n, p;
 
-       pm2_mnp(clk, &m, &n, &p);
-       WAIT_FIFO(par, 10);
-       pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
-       wmb();
-       pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
-       pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
-       wmb();
-       pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-       wmb();
-       pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
-       rmb();
-       for (i = 256;
-            i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
-            i--)
-               ;
+       switch (par->type) {
+       case PM2_TYPE_PERMEDIA2V:
+               pm2v_mnp(clk/2, &m, &n, &p);
+               WAIT_FIFO(par, 8);
+               pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
+               pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
+               wmb();
+               pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
+               pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
+               pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
+               wmb();
+               pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
+               rmb();
+               for (i = 256;
+                    i && !(pm2_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2);
+                    i--)
+                       ;
+               pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+               break;
+       case PM2_TYPE_PERMEDIA2:
+               pm2_mnp(clk, &m, &n, &p);
+               WAIT_FIFO(par, 10);
+               pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
+               wmb();
+               pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
+               pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
+               wmb();
+               pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
+               wmb();
+               pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
+               rmb();
+               for (i = 256;
+                    i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
+                    i--)
+                       ;
+               break;
+       }
 }
 
 static void set_pixclock(struct pm2fb_par* par, u32 clk)
@@ -623,6 +654,8 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                return -EINVAL;
        }
 
+       var->transp.offset = 0;
+       var->transp.length = 0;
        switch(var->bits_per_pixel) {
        case 8:
                var->red.length = var->green.length = var->blue.length = 8;
@@ -1017,6 +1050,117 @@ static int pm2fb_blank(int blank_mode, struct fb_info *info)
        return 0;
 }
 
+/*
+ * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
+ */
+static void pm2fb_block_op(struct pm2fb_par* par, int copy,
+                               s32 xsrc, s32 ysrc,
+                               s32 x, s32 y, s32 w, s32 h,
+                               u32 color) {
+
+       if (!w || !h)
+               return;
+       WAIT_FIFO(par, 6);
+       pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
+               PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+       pm2_WR(par, PM2R_FB_PIXEL_OFFSET, 0);
+       if (copy)
+               pm2_WR(par, PM2R_FB_SOURCE_DELTA,
+                       ((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff));
+       else
+               pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
+       pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
+       pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
+       wmb();
+       pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE |
+                               (x<xsrc ? PM2F_INCREASE_X : 0) |
+                               (y<ysrc ? PM2F_INCREASE_Y : 0) |
+                               (copy ? 0 : PM2F_RENDER_FASTFILL));
+       wait_pm2(par);
+}
+
+static void pm2fb_fillrect (struct fb_info *info,
+                               const struct fb_fillrect *region)
+{
+       struct pm2fb_par *par = info->par;
+       struct fb_fillrect modded;
+       int vxres, vyres;
+       u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+               ((u32*)info->pseudo_palette)[region->color] : region->color;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return;
+       if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+               region->rop != ROP_COPY ) {
+               cfb_fillrect(info, region);
+               return;
+       }
+
+       vxres = info->var.xres_virtual;
+       vyres = info->var.yres_virtual;
+
+       memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+       if(!modded.width || !modded.height ||
+          modded.dx >= vxres || modded.dy >= vyres)
+               return;
+
+       if(modded.dx + modded.width  > vxres)
+               modded.width  = vxres - modded.dx;
+       if(modded.dy + modded.height > vyres)
+               modded.height = vyres - modded.dy;
+
+       if(info->var.bits_per_pixel == 8)
+               color |= color << 8;
+       if(info->var.bits_per_pixel <= 16)
+               color |= color << 16;
+
+       if(info->var.bits_per_pixel != 24)
+               pm2fb_block_op(par, 0, 0, 0,
+                               modded.dx, modded.dy,
+                               modded.width, modded.height, color);
+       else
+               cfb_fillrect(info, region);
+}
+
+static void pm2fb_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area)
+{
+       struct pm2fb_par *par = info->par;
+       struct fb_copyarea modded;
+       u32 vxres, vyres;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return;
+       if (info->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_copyarea(info, area);
+               return;
+       }
+
+       memcpy(&modded, area, sizeof(struct fb_copyarea));
+
+       vxres = info->var.xres_virtual;
+       vyres = info->var.yres_virtual;
+
+       if(!modded.width || !modded.height ||
+          modded.sx >= vxres || modded.sy >= vyres ||
+          modded.dx >= vxres || modded.dy >= vyres)
+               return;
+
+       if(modded.sx + modded.width > vxres)
+               modded.width = vxres - modded.sx;
+       if(modded.dx + modded.width > vxres)
+               modded.width = vxres - modded.dx;
+       if(modded.sy + modded.height > vyres)
+               modded.height = vyres - modded.sy;
+       if(modded.dy + modded.height > vyres)
+               modded.height = vyres - modded.dy;
+
+       pm2fb_block_op(par, 1, modded.sx, modded.sy,
+                       modded.dx, modded.dy,
+                       modded.width, modded.height, 0);
+}
+
 /* ------------ Hardware Independent Functions ------------ */
 
 /*
@@ -1030,8 +1174,8 @@ static struct fb_ops pm2fb_ops = {
        .fb_setcolreg   = pm2fb_setcolreg,
        .fb_blank       = pm2fb_blank,
        .fb_pan_display = pm2fb_pan_display,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
+       .fb_fillrect    = pm2fb_fillrect,
+       .fb_copyarea    = pm2fb_copyarea,
        .fb_imageblit   = cfb_imageblit,
 };
 
@@ -1119,38 +1263,47 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
 
        if(default_par->mem_control == 0 &&
                default_par->boot_address == 0x31 &&
-               default_par->mem_config == 0x259fffff &&
-               pdev->subsystem_vendor == 0x1048 &&
-               pdev->subsystem_device == 0x0a31) {
-               DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
-                       pdev->subsystem_vendor, pdev->subsystem_device);
-               DPRINTK("We have not been initialized by VGA BIOS "
-                       "and are running on an Elsa Winner 2000 Office\n");
-               DPRINTK("Initializing card timings manually...\n");
+               default_par->mem_config == 0x259fffff) {
+               default_par->memclock = CVPPC_MEMCLOCK;
                default_par->mem_control=0;
                default_par->boot_address=0x20;
                default_par->mem_config=0xe6002021;
-               default_par->memclock=100000;
+               if (pdev->subsystem_vendor == 0x1048 &&
+                       pdev->subsystem_device == 0x0a31) {
+                       DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
+                               pdev->subsystem_vendor, pdev->subsystem_device);
+                       DPRINTK("We have not been initialized by VGA BIOS "
+                               "and are running on an Elsa Winner 2000 Office\n");
+                       DPRINTK("Initializing card timings manually...\n");
+                       default_par->memclock=70000;
+               }
+               if (pdev->subsystem_vendor == 0x3d3d &&
+                       pdev->subsystem_device == 0x0100) {
+                       DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
+                               pdev->subsystem_vendor, pdev->subsystem_device);
+                       DPRINTK("We have not been initialized by VGA BIOS "
+                               "and are running on an 3dlabs reference board\n");
+                       DPRINTK("Initializing card timings manually...\n");
+                       default_par->memclock=74894;
+               }
        }
 
        /* Now work out how big lfb is going to be. */
        switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
        case PM2F_MEM_BANKS_1:
-               default_par->fb_size=0x200000;
+               pm2fb_fix.smem_len=0x200000;
                break;
        case PM2F_MEM_BANKS_2:
-               default_par->fb_size=0x400000;
+               pm2fb_fix.smem_len=0x400000;
                break;
        case PM2F_MEM_BANKS_3:
-               default_par->fb_size=0x600000;
+               pm2fb_fix.smem_len=0x600000;
                break;
        case PM2F_MEM_BANKS_4:
-               default_par->fb_size=0x800000;
+               pm2fb_fix.smem_len=0x800000;
                break;
        }
-       default_par->memclock = CVPPC_MEMCLOCK;
        pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
-       pm2fb_fix.smem_len = default_par->fb_size;
 
        /* Linear frame buffer - request region and map it. */
        if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
@@ -1158,9 +1311,9 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
                printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
                goto err_exit_mmio;
        }
-       info->screen_base = default_par->v_fb =
+       info->screen_base =
                ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
-       if ( !default_par->v_fb ) {
+       if ( !info->screen_base ) {
                printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
                release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
                goto err_exit_mmio;
@@ -1170,7 +1323,9 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
        info->fix               = pm2fb_fix;    
        info->pseudo_palette    = default_par->palette;
        info->flags             = FBINFO_DEFAULT |
-                                  FBINFO_HWACCEL_YPAN;
+                                  FBINFO_HWACCEL_YPAN |
+                                 FBINFO_HWACCEL_COPYAREA |
+                                 FBINFO_HWACCEL_FILLRECT;
 
        if (!mode)
                mode = "640x480@60";
@@ -1180,13 +1335,13 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
                info->var = pm2fb_var;
 
        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
-               goto err_exit_all;
+               goto err_exit_both;
 
        if (register_framebuffer(info) < 0)
-               goto err_exit_both;
+               goto err_exit_all;
 
        printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",
-              info->node, info->fix.id, default_par->fb_size / 1024);
+              info->node, info->fix.id, pm2fb_fix.smem_len / 1024);
 
        /*
         * Our driver data
@@ -1242,6 +1397,9 @@ static struct pci_device_id pm2fb_id_table[] = {
        { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
          PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
          0xff0000, 0 },
+       { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA << 8,
+         0xff00, 0 },
        { 0, }
 };
 
index 07d1979bc23e1707138286736c77fac62749d09b..9756a728b74f3e2dbb58d5ca0709b3b298266c06 100644 (file)
@@ -898,8 +898,8 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
        }
 
        ps3fb.dev = dev;
-       error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
-                             &ps3fb.irq_no);
+       error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+                                  &ps3fb.irq_no);
        if (error) {
                printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
                       error);
@@ -911,7 +911,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
        if (error) {
                printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
                       error);
-               ps3_free_irq(ps3fb.irq_no);
+               ps3_irq_plug_destroy(ps3fb.irq_no);
                return error;
        }
 
@@ -1083,7 +1083,7 @@ err_framebuffer_release:
        framebuffer_release(info);
 err_free_irq:
        free_irq(ps3fb.irq_no, ps3fb.dev);
-       ps3_free_irq(ps3fb.irq_no);
+       ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
        iounmap((u8 __iomem *)ps3fb.dinfo);
 err_gpu_context_free:
@@ -1099,7 +1099,7 @@ static void ps3fb_shutdown(struct platform_device *dev)
        ps3fb_flip_ctl(0);      /* flip off */
        ps3fb.dinfo->irq.mask = 0;
        free_irq(ps3fb.irq_no, ps3fb.dev);
-       ps3_free_irq(ps3fb.irq_no);
+       ps3_irq_plug_destroy(ps3fb.irq_no);
        iounmap((u8 __iomem *)ps3fb.dinfo);
 }
 
@@ -1114,7 +1114,7 @@ void ps3fb_cleanup(void)
        }
        if (ps3fb.irq_no) {
                free_irq(ps3fb.irq_no, ps3fb.dev);
-               ps3_free_irq(ps3fb.irq_no);
+               ps3_irq_plug_destroy(ps3fb.irq_no);
        }
        iounmap((u8 __iomem *)ps3fb.dinfo);
 
index a93618bc9d274527fd627f4decdabb96347ff05f..df2909ae704cd51132021b14a85d066f71b5517b 100644 (file)
@@ -214,7 +214,7 @@ static int pvr2_init_cable(void);
 static int pvr2_get_param(const struct pvr2_params *p, const char *s,
                             int val, int size);
 #ifdef CONFIG_SH_DMA
-static ssize_t pvr2fb_write(struct file *file, const char *buf,
+static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
                            size_t count, loff_t *ppos);
 #endif
 
@@ -674,7 +674,7 @@ static int pvr2_init_cable(void)
 }
 
 #ifdef CONFIG_SH_DMA
-static ssize_t pvr2fb_write(struct file *file, const char *buf,
+static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
                            size_t count, loff_t *ppos)
 {
        unsigned long dst, start, end, len;
index 0b195f33f84fb31c362070bddc2566988a920e3b..81e571d59b50a949589162e5ca28681a45964e0f 100644 (file)
@@ -1203,7 +1203,7 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
                                        } else
                                                goto done;
                                        break;
-                               case '0'...'9':
+                               case '0' ... '9':
                                        break;
                                default:
                                        goto done;
index d7ece8d17a2c53f41fee7ccdccadc89411082b87..0fe547842c643efceef03f9582e4940b7a3e2fd0 100644 (file)
@@ -317,15 +317,15 @@ static int riva_bl_update_status(struct backlight_device *bd)
        else
                level = bd->props.brightness;
 
-       tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
-       tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
+       tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;
+       tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;
        if(level > 0) {
                tmp_pcrt |= 0x1;
                tmp_pmc |= (1 << 31); /* backlight bit */
                tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
        }
-       par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
-       par->riva.PMC[0x10F0/4] = tmp_pmc;
+       NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt);
+       NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc);
 
        return 0;
 }
@@ -1760,13 +1760,13 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
        NVTRACE_ENTER();
        dp = pci_device_to_OF_node(pd);
        for (; dp != NULL; dp = dp->child) {
-               disptype = get_property(dp, "display-type", NULL);
+               disptype = of_get_property(dp, "display-type", NULL);
                if (disptype == NULL)
                        continue;
                if (strncmp(disptype, "LCD", 3) != 0)
                        continue;
                for (i = 0; propnames[i] != NULL; ++i) {
-                       pedid = get_property(dp, propnames[i], NULL);
+                       pedid = of_get_property(dp, propnames[i], NULL);
                        if (pedid != NULL) {
                                par->EDID = (unsigned char *)pedid;
                                NVTRACE("LCD found.\n");
@@ -1788,8 +1788,10 @@ static int __devinit riva_get_EDID_i2c(struct fb_info *info)
 
        NVTRACE_ENTER();
        riva_create_i2c_busses(par);
-       for (i = 0; i < par->bus; i++) {
-               riva_probe_i2c_connector(par, i+1, &par->EDID);
+       for (i = 0; i < 3; i++) {
+               if (!par->chan[i].par)
+                       continue;
+               riva_probe_i2c_connector(par, i, &par->EDID);
                if (par->EDID && !fb_parse_edid(par->EDID, &var)) {
                        printk(PFX "Found EDID Block from BUS %i\n", i);
                        break;
@@ -2104,7 +2106,7 @@ err_ret:
        return ret;
 }
 
-static void __exit rivafb_remove(struct pci_dev *pd)
+static void __devexit rivafb_remove(struct pci_dev *pd)
 {
        struct fb_info *info = pci_get_drvdata(pd);
        struct riva_par *par = info->par;
@@ -2185,7 +2187,7 @@ static struct pci_driver rivafb_driver = {
        .name           = "rivafb",
        .id_table       = rivafb_pci_tbl,
        .probe          = rivafb_probe,
-       .remove         = __exit_p(rivafb_remove),
+       .remove         = __devexit_p(rivafb_remove),
 };
 
 
diff --git a/drivers/video/riva/nv4ref.h b/drivers/video/riva/nv4ref.h
deleted file mode 100644 (file)
index 3b5f911..0000000
+++ /dev/null
@@ -1,2445 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL licensing note -- nVidia is allowing a liberal interpretation of
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived
- * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
- */
-
- /***************************************************************************\
-|*            Modified 1999 by Fredrik Reite (fredrik@reite.com)             *|
- \***************************************************************************/
-
-
-#ifndef __NV4REF_H__
-#define __NV4REF_H__
-
-/* Magic values to lock/unlock extended regs */
-#define NV_CIO_SR_LOCK_INDEX                                0x0000001F /*       */
-#define NV_CIO_SR_UNLOCK_RW_VALUE                            0x00000057 /*       */
-#define NV_CIO_SR_UNLOCK_RO_VALUE                            0x00000075 /*       */
-#define NV_CIO_SR_LOCK_VALUE                                 0x00000099 /*       */
-
-#define UNLOCK_EXT_MAGIC 0x57
-#define LOCK_EXT_MAGIC 0x99 /* Any value other than 0x57 will do */
-
-#define LOCK_EXT_INDEX 0x6
-
-#define NV_PCRTC_HORIZ_TOTAL                                 0x00
-#define NV_PCRTC_HORIZ_DISPLAY_END                           0x01
-#define NV_PCRTC_HORIZ_BLANK_START                           0x02
-
-#define NV_PCRTC_HORIZ_BLANK_END                             0x03
-#define NV_PCRTC_HORIZ_BLANK_END_EVRA                        7:7
-#define NV_PCRTC_HORIZ_BLANK_END_DISPLAY_END_SKEW            6:5
-#define NV_PCRTC_HORIZ_BLANK_END_HORIZ_BLANK_END             4:0
-
-#define NV_PCRTC_HORIZ_RETRACE_START                         0x04
-
-#define NV_PCRTC_HORIZ_RETRACE_END                           0x05
-#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_BLANK_END_5         7:7
-#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_RETRACE_SKEW        6:5
-#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_RETRACE_END         4:0
-
-#define NV_PCRTC_VERT_TOTAL                                  0x06
-
-#define NV_PCRTC_OVERFLOW                                    0x07
-#define NV_PCRTC_OVERFLOW_VERT_RETRACE_START_9               7:7
-#define NV_PCRTC_OVERFLOW_VERT_DISPLAY_END_9                 6:6
-#define NV_PCRTC_OVERFLOW_VERT_TOTAL_9                       5:5
-#define NV_PCRTC_OVERFLOW_LINE_COMPARE_8                     4:4
-#define NV_PCRTC_OVERFLOW_VERT_BLANK_START_8                 3:3
-#define NV_PCRTC_OVERFLOW_VERT_RETRACE_START_8               2:2
-#define NV_PCRTC_OVERFLOW_VERT_DISPLAY_END_8                 1:1
-#define NV_PCRTC_OVERFLOW_VERT_TOTAL_8                       0:0
-
-#define NV_PCRTC_PRESET_ROW_SCAN                             0x08
-
-#define NV_PCRTC_MAX_SCAN_LINE                               0x09
-#define NV_PCRTC_MAX_SCAN_LINE_DOUBLE_SCAN                   7:7
-#define NV_PCRTC_MAX_SCAN_LINE_LINE_COMPARE_9                6:6
-#define NV_PCRTC_MAX_SCAN_LINE_VERT_BLANK_START_9            5:5
-#define NV_PCRTC_MAX_SCAN_LINE_MAX_SCAN_LINE                 4:0
-
-#define NV_PCRTC_CURSOR_START                                0x0A
-#define NV_PCRTC_CURSOR_END                                  0x0B
-#define NV_PCRTC_START_ADDR_HIGH                             0x0C
-#define NV_PCRTC_START_ADDR_LOW                              0x0D
-#define NV_PCRTC_CURSOR_LOCATION_HIGH                        0x0E
-#define NV_PCRTC_CURSOR_LOCATION_LOW                         0x0F
-
-#define NV_PCRTC_VERT_RETRACE_START                          0x10
-#define NV_PCRTC_VERT_RETRACE_END                            0x11
-#define NV_PCRTC_VERT_DISPLAY_END                            0x12
-#define NV_PCRTC_OFFSET                                      0x13
-#define NV_PCRTC_UNDERLINE_LOCATION                          0x14
-#define NV_PCRTC_VERT_BLANK_START                            0x15
-#define NV_PCRTC_VERT_BLANK_END                              0x16
-#define NV_PCRTC_MODE_CONTROL                                0x17
-#define NV_PCRTC_LINE_COMPARE                                0x18
-
-/* Extended offset and start address */
-#define NV_PCRTC_REPAINT0                                    0x19
-#define NV_PCRTC_REPAINT0_OFFSET_10_8                        7:5 
-#define NV_PCRTC_REPAINT0_START_ADDR_20_16                   4:0
-
-/* Horizonal extended bits */
-#define NV_PCRTC_HORIZ_EXTRA                                 0x2d
-#define NV_PCRTC_HORIZ_EXTRA_INTER_HALF_START_8              4:4
-#define NV_PCRTC_HORIZ_EXTRA_HORIZ_RETRACE_START_8           3:3
-#define NV_PCRTC_HORIZ_EXTRA_HORIZ_BLANK_START_8             2:2
-#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_END_8                   1:1
-#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_TOTAL_8                 0:0
-
-/* Assorted extra bits */
-#define NV_PCRTC_EXTRA                                       0x25
-#define NV_PCRTC_EXTRA_OFFSET_11                             5:5
-#define NV_PCRTC_EXTRA_HORIZ_BLANK_END_6                     4:4
-#define NV_PCRTC_EXTRA_VERT_BLANK_START_10                   3:3
-#define NV_PCRTC_EXTRA_VERT_RETRACE_START_10                 2:2
-#define NV_PCRTC_EXTRA_VERT_DISPLAY_END_10                   1:1
-#define NV_PCRTC_EXTRA_VERT_TOTAL_10                         0:0
-
-/* Controls how much data the refresh fifo requests */
-#define NV_PCRTC_FIFO_CONTROL                                0x1b
-#define NV_PCRTC_FIFO_CONTROL_UNDERFLOW_WARN                 7:7
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH                   2:0
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_8                 0x0
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_32                0x1
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_64                0x2
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_128               0x3
-#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_256               0x4
-
-/* When the fifo occupancy falls below *twice* the watermark,
- * the refresh fifo will start to be refilled. If this value is 
- * too low, you will get junk on the screen. Too high, and performance
- * will suffer. Watermark in units of 8 bytes
- */
-#define NV_PCRTC_FIFO                                        0x20
-#define NV_PCRTC_FIFO_RESET                                  7:7
-#define NV_PCRTC_FIFO_WATERMARK                              5:0
-
-/* Various flags */
-#define NV_PCRTC_REPAINT1                                    0x1a
-#define NV_PCRTC_REPAINT1_HSYNC                              7:7
-#define NV_PCRTC_REPAINT1_HYSNC_DISABLE                      0x01
-#define NV_PCRTC_REPAINT1_HYSNC_ENABLE                       0x00
-#define NV_PCRTC_REPAINT1_VSYNC                              6:6
-#define NV_PCRTC_REPAINT1_VYSNC_DISABLE                      0x01
-#define NV_PCRTC_REPAINT1_VYSNC_ENABLE                       0x00
-#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT                    4:4
-#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_ENABLE             0x01
-#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_DISABLE            0x00
-#define NV_PCRTC_REPAINT1_LARGE_SCREEN                       2:2 
-#define NV_PCRTC_REPAINT1_LARGE_SCREEN_DISABLE               0x01
-#define NV_PCRTC_REPAINT1_LARGE_SCREEN_ENABLE                0x00 /* >=1280 */
-#define NV_PCRTC_REPAINT1_PALETTE_WIDTH                      1:1
-#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_8BITS                0x00
-#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_6BITS                0x01
-
-#define NV_PCRTC_GRCURSOR0                                   0x30
-#define NV_PCRTC_GRCURSOR0_START_ADDR_21_16                  5:0
-
-#define NV_PCRTC_GRCURSOR1                                   0x31
-#define NV_PCRTC_GRCURSOR1_START_ADDR_15_11                  7:3
-#define NV_PCRTC_GRCURSOR1_SCAN_DBL                          1:1
-#define NV_PCRTC_GRCURSOR1_SCAN_DBL_DISABLE                  0
-#define NV_PCRTC_GRCURSOR1_SCAN_DBL_ENABLE                   1
-#define NV_PCRTC_GRCURSOR1_CURSOR                            0:0
-#define NV_PCRTC_GRCURSOR1_CURSOR_DISABLE                    0 
-#define NV_PCRTC_GRCURSOR1_CURSOR_ENABLE                     1
-
-/* Controls what the format of the framebuffer is */
-#define NV_PCRTC_PIXEL                       0x28
-#define NV_PCRTC_PIXEL_MODE                  7:7
-#define NV_PCRTC_PIXEL_MODE_TV               0x01
-#define NV_PCRTC_PIXEL_MODE_VGA              0x00
-#define NV_PCRTC_PIXEL_TV_MODE               6:6
-#define NV_PCRTC_PIXEL_TV_MODE_NTSC          0x00
-#define NV_PCRTC_PIXEL_TV_MODE_PAL           0x01
-#define NV_PCRTC_PIXEL_TV_HORIZ_ADJUST       5:3
-#define NV_PCRTC_PIXEL_FORMAT                1:0
-#define NV_PCRTC_PIXEL_FORMAT_VGA            0x00
-#define NV_PCRTC_PIXEL_FORMAT_8BPP           0x01
-#define NV_PCRTC_PIXEL_FORMAT_16BPP          0x02
-#define NV_PCRTC_PIXEL_FORMAT_32BPP          0x03
-
-/* RAMDAC registers and fields */
-#define NV_PRAMDAC                            0x00680FFF:0x00680000 /* RW--D */
-#define NV_PRAMDAC_GRCURSOR_START_POS                    0x00680300 /* RW-4R */
-#define NV_PRAMDAC_GRCURSOR_START_POS_X                        11:0 /* RWXSF */
-#define NV_PRAMDAC_GRCURSOR_START_POS_Y                       27:16 /* RWXSF */
-#define NV_PRAMDAC_NVPLL_COEFF                           0x00680500 /* RW-4R */
-#define NV_PRAMDAC_NVPLL_COEFF_MDIV                             7:0 /* RWIUF */
-#define NV_PRAMDAC_NVPLL_COEFF_NDIV                            15:8 /* RWIUF */
-#define NV_PRAMDAC_NVPLL_COEFF_PDIV                           18:16 /* RWIVF */
-#define NV_PRAMDAC_MPLL_COEFF                            0x00680504 /* RW-4R */
-#define NV_PRAMDAC_MPLL_COEFF_MDIV                              7:0 /* RWIUF */
-#define NV_PRAMDAC_MPLL_COEFF_NDIV                             15:8 /* RWIUF */
-#define NV_PRAMDAC_MPLL_COEFF_PDIV                            18:16 /* RWIVF */
-#define NV_PRAMDAC_VPLL_COEFF                            0x00680508 /* RW-4R */
-#define NV_PRAMDAC_VPLL_COEFF_MDIV                              7:0 /* RWIUF */
-#define NV_PRAMDAC_VPLL_COEFF_NDIV                             15:8 /* RWIUF */
-#define NV_PRAMDAC_VPLL_COEFF_PDIV                            18:16 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT                      0x0068050C /* RW-4R */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS                  4:4 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_FALSE     0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_TRUE      0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE                 8:8 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_DEFAULT  0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_PROG     0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS               12:12 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_FALSE    0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_TRUE     0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE               16:16 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_DEFAULT  0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_PROG     0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS               20:20 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_FALSE    0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_TRUE     0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE               25:24 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VPLL     0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VIP      0x00000001 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_XTALOSC  0x00000002 /* RW--V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO                28:28 /* RWIVF */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB1       0x00000000 /* RWI-V */
-#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2       0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL                       0x00680600 /* RW-4R */
-#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF                     1:0 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF_DEF          0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE                     4:4 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_GAMMA        0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_INDEX        0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE                    8:8 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_NOTSE       0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL         0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE                   12:12 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_NOTSEL       0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_SEL          0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL                 16:16 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_OFF        0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_ON         0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION                17:17 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_37OHM     0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM     0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_BPC                        20:20 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_BPC_6BITS             0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS             0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP                  24:24 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_DIS         0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_EN          0x00000001 /* RW--V */
-#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK                28:28 /* RWIVF */
-#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_EN        0x00000000 /* RWI-V */
-#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_DIS       0x00000001 /* RW--V */
-
-/* Master Control */
-#define NV_PMC                                0x00000FFF:0x00000000 /* RW--D */
-#define NV_PMC_BOOT_0                                    0x00000000 /* R--4R */
-#define NV_PMC_BOOT_0_MINOR_REVISION                            3:0 /* C--VF */
-#define NV_PMC_BOOT_0_MINOR_REVISION_0                   0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_MAJOR_REVISION                            7:4 /* C--VF */
-#define NV_PMC_BOOT_0_MAJOR_REVISION_A                   0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_MAJOR_REVISION_B                   0x00000001 /* ----V */
-#define NV_PMC_BOOT_0_IMPLEMENTATION                           11:8 /* C--VF */
-#define NV_PMC_BOOT_0_IMPLEMENTATION_NV4_0               0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_ARCHITECTURE                            15:12 /* C--VF */
-#define NV_PMC_BOOT_0_ARCHITECTURE_NV0                   0x00000000 /* ----V */
-#define NV_PMC_BOOT_0_ARCHITECTURE_NV1                   0x00000001 /* ----V */
-#define NV_PMC_BOOT_0_ARCHITECTURE_NV2                   0x00000002 /* ----V */
-#define NV_PMC_BOOT_0_ARCHITECTURE_NV3                   0x00000003 /* ----V */
-#define NV_PMC_BOOT_0_ARCHITECTURE_NV4                   0x00000004 /* C---V */
-#define NV_PMC_BOOT_0_FIB_REVISION                            19:16 /* C--VF */
-#define NV_PMC_BOOT_0_FIB_REVISION_0                     0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_MASK_REVISION                           23:20 /* C--VF */
-#define NV_PMC_BOOT_0_MASK_REVISION_A                    0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_MASK_REVISION_B                    0x00000001 /* ----V */
-#define NV_PMC_BOOT_0_MANUFACTURER                            27:24 /* C--UF */
-#define NV_PMC_BOOT_0_MANUFACTURER_NVIDIA                0x00000000 /* C---V */
-#define NV_PMC_BOOT_0_FOUNDRY                                 31:28 /* C--VF */
-#define NV_PMC_BOOT_0_FOUNDRY_SGS                        0x00000000 /* ----V */
-#define NV_PMC_BOOT_0_FOUNDRY_HELIOS                     0x00000001 /* ----V */
-#define NV_PMC_BOOT_0_FOUNDRY_TSMC                       0x00000002 /* C---V */
-#define NV_PMC_INTR_0                                    0x00000100 /* RW-4R */
-#define NV_PMC_INTR_0_PMEDIA                                    4:4 /* R--VF */
-#define NV_PMC_INTR_0_PMEDIA_NOT_PENDING                 0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PMEDIA_PENDING                     0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PFIFO                                     8:8 /* R--VF */
-#define NV_PMC_INTR_0_PFIFO_NOT_PENDING                  0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PFIFO_PENDING                      0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PGRAPH                                  12:12 /* R--VF */
-#define NV_PMC_INTR_0_PGRAPH_NOT_PENDING                 0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PGRAPH_PENDING                     0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PVIDEO                                  16:16 /* R--VF */
-#define NV_PMC_INTR_0_PVIDEO_NOT_PENDING                 0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PVIDEO_PENDING                     0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PTIMER                                  20:20 /* R--VF */
-#define NV_PMC_INTR_0_PTIMER_NOT_PENDING                 0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PTIMER_PENDING                     0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PCRTC                                   24:24 /* R--VF */
-#define NV_PMC_INTR_0_PCRTC_NOT_PENDING                  0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PCRTC_PENDING                      0x00000001 /* R---V */
-#define NV_PMC_INTR_0_PBUS                                    28:28 /* R--VF */
-#define NV_PMC_INTR_0_PBUS_NOT_PENDING                   0x00000000 /* R---V */
-#define NV_PMC_INTR_0_PBUS_PENDING                       0x00000001 /* R---V */
-#define NV_PMC_INTR_0_SOFTWARE                                31:31 /* RWIVF */
-#define NV_PMC_INTR_0_SOFTWARE_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PMC_INTR_0_SOFTWARE_PENDING                   0x00000001 /* RW--V */
-#define NV_PMC_INTR_EN_0                                 0x00000140 /* RW-4R */
-#define NV_PMC_INTR_EN_0_INTA                                   1:0 /* RWIVF */
-#define NV_PMC_INTR_EN_0_INTA_DISABLED                   0x00000000 /* RWI-V */
-#define NV_PMC_INTR_EN_0_INTA_HARDWARE                   0x00000001 /* RW--V */
-#define NV_PMC_INTR_EN_0_INTA_SOFTWARE                   0x00000002 /* RW--V */
-#define NV_PMC_INTR_READ_0                               0x00000160 /* R--4R */
-#define NV_PMC_INTR_READ_0_INTA                                 0:0 /* R--VF */
-#define NV_PMC_INTR_READ_0_INTA_LOW                      0x00000000 /* R---V */
-#define NV_PMC_INTR_READ_0_INTA_HIGH                     0x00000001 /* R---V */
-#define NV_PMC_ENABLE                                    0x00000200 /* RW-4R */
-#define NV_PMC_ENABLE_PMEDIA                                    4:4 /* RWIVF */
-#define NV_PMC_ENABLE_PMEDIA_DISABLED                    0x00000000 /* RWI-V */
-#define NV_PMC_ENABLE_PMEDIA_ENABLED                     0x00000001 /* RW--V */
-#define NV_PMC_ENABLE_PFIFO                                     8:8 /* RWIVF */
-#define NV_PMC_ENABLE_PFIFO_DISABLED                     0x00000000 /* RWI-V */
-#define NV_PMC_ENABLE_PFIFO_ENABLED                      0x00000001 /* RW--V */
-#define NV_PMC_ENABLE_PGRAPH                                  12:12 /* RWIVF */
-#define NV_PMC_ENABLE_PGRAPH_DISABLED                    0x00000000 /* RWI-V */
-#define NV_PMC_ENABLE_PGRAPH_ENABLED                     0x00000001 /* RW--V */
-#define NV_PMC_ENABLE_PPMI                                    16:16 /* RWIVF */
-#define NV_PMC_ENABLE_PPMI_DISABLED                      0x00000000 /* RWI-V */
-#define NV_PMC_ENABLE_PPMI_ENABLED                       0x00000001 /* RW--V */
-#define NV_PMC_ENABLE_PFB                                     20:20 /* RWIVF */
-#define NV_PMC_ENABLE_PFB_DISABLED                       0x00000000 /* RW--V */
-#define NV_PMC_ENABLE_PFB_ENABLED                        0x00000001 /* RWI-V */
-#define NV_PMC_ENABLE_PCRTC                                   24:24 /* RWIVF */
-#define NV_PMC_ENABLE_PCRTC_DISABLED                     0x00000000 /* RW--V */
-#define NV_PMC_ENABLE_PCRTC_ENABLED                      0x00000001 /* RWI-V */
-#define NV_PMC_ENABLE_PVIDEO                                  28:28 /* RWIVF */
-#define NV_PMC_ENABLE_PVIDEO_DISABLED                    0x00000000 /* RWI-V */
-#define NV_PMC_ENABLE_PVIDEO_ENABLED                     0x00000001 /* RW--V */
-
-/* dev_timer.ref */
-#define NV_PTIMER                             0x00009FFF:0x00009000 /* RW--D */
-#define NV_PTIMER_INTR_0                                 0x00009100 /* RW-4R */
-#define NV_PTIMER_INTR_0_ALARM                                  0:0 /* RWXVF */
-#define NV_PTIMER_INTR_0_ALARM_NOT_PENDING               0x00000000 /* R---V */
-#define NV_PTIMER_INTR_0_ALARM_PENDING                   0x00000001 /* R---V */
-#define NV_PTIMER_INTR_0_ALARM_RESET                     0x00000001 /* -W--V */
-#define NV_PTIMER_INTR_EN_0                              0x00009140 /* RW-4R */
-#define NV_PTIMER_INTR_EN_0_ALARM                               0:0 /* RWIVF */
-#define NV_PTIMER_INTR_EN_0_ALARM_DISABLED               0x00000000 /* RWI-V */
-#define NV_PTIMER_INTR_EN_0_ALARM_ENABLED                0x00000001 /* RW--V */
-#define NV_PTIMER_NUMERATOR                              0x00009200 /* RW-4R */
-#define NV_PTIMER_NUMERATOR_VALUE                              15:0 /* RWIUF */
-#define NV_PTIMER_NUMERATOR_VALUE_0                      0x00000000 /* RWI-V */
-#define NV_PTIMER_DENOMINATOR                            0x00009210 /* RW-4R */
-#define NV_PTIMER_DENOMINATOR_VALUE                            15:0 /* RWIUF */
-#define NV_PTIMER_DENOMINATOR_VALUE_0                    0x00000000 /* RWI-V */
-#define NV_PTIMER_TIME_0                                 0x00009400 /* RW-4R */
-#define NV_PTIMER_TIME_0_NSEC                                  31:5 /* RWXUF */
-#define NV_PTIMER_TIME_1                                 0x00009410 /* RW-4R */
-#define NV_PTIMER_TIME_1_NSEC                                  28:0 /* RWXUF */
-#define NV_PTIMER_ALARM_0                                0x00009420 /* RW-4R */
-#define NV_PTIMER_ALARM_0_NSEC                                 31:5 /* RWXUF */
-
-/* dev_fifo.ref */
-#define NV_PFIFO                              0x00003FFF:0x00002000 /* RW--D */
-#define NV_PFIFO_DELAY_0                                 0x00002040 /* RW-4R */
-#define NV_PFIFO_DELAY_0_WAIT_RETRY                             9:0 /* RWIUF */
-#define NV_PFIFO_DELAY_0_WAIT_RETRY_0                    0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_TIMESLICE                           0x00002044 /* RW-4R */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT                          16:0 /* RWIUF */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT_1                  0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT_16K                0x00003fff /* RW--V */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT_32K                0x00007fff /* RW--V */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT_64K                0x0000ffff /* RW--V */
-#define NV_PFIFO_DMA_TIMESLICE_SELECT_128K               0x0001ffff /* RW--V */
-#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT                        24:24 /* RWIUF */
-#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT_DISABLED          0x00000000 /* RW--V */
-#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT_ENABLED           0x00000001 /* RWI-V */
-#define NV_PFIFO_PIO_TIMESLICE                           0x00002048 /* RW-4R */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT                          16:0 /* RWIUF */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT_1                  0x00000000 /* RWI-V */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT_16K                0x00003fff /* RW--V */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT_32K                0x00007fff /* RW--V */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT_64K                0x0000ffff /* RW--V */
-#define NV_PFIFO_PIO_TIMESLICE_SELECT_128K               0x0001ffff /* RW--V */
-#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT                        24:24 /* RWIUF */
-#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT_DISABLED          0x00000000 /* RW--V */
-#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT_ENABLED           0x00000001 /* RWI-V */
-#define NV_PFIFO_TIMESLICE                               0x0000204C /* RW-4R */
-#define NV_PFIFO_TIMESLICE_TIMER                               17:0 /* RWIUF */
-#define NV_PFIFO_TIMESLICE_TIMER_EXPIRED                 0x0003FFFF /* RWI-V */
-#define NV_PFIFO_NEXT_CHANNEL                            0x00002050 /* RW-4R */
-#define NV_PFIFO_NEXT_CHANNEL_CHID                              3:0 /* RWXUF */
-#define NV_PFIFO_NEXT_CHANNEL_MODE                              8:8 /* RWXVF */
-#define NV_PFIFO_NEXT_CHANNEL_MODE_PIO                   0x00000000 /* RW--V */
-#define NV_PFIFO_NEXT_CHANNEL_MODE_DMA                   0x00000001 /* RW--V */
-#define NV_PFIFO_NEXT_CHANNEL_SWITCH                          12:12 /* RWIVF */
-#define NV_PFIFO_NEXT_CHANNEL_SWITCH_NOT_PENDING         0x00000000 /* RWI-V */
-#define NV_PFIFO_NEXT_CHANNEL_SWITCH_PENDING             0x00000001 /* RW--V */
-#define NV_PFIFO_DEBUG_0                                 0x00002080 /* R--4R */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR0                           0:0 /* R-XVF */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR0_NOT_PENDING        0x00000000 /* R---V */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR0_PENDING            0x00000001 /* R---V */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR1                           4:4 /* R-XVF */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR1_NOT_PENDING        0x00000000 /* R---V */
-#define NV_PFIFO_DEBUG_0_CACHE_ERROR1_PENDING            0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0                                  0x00002100 /* RW-4R */
-#define NV_PFIFO_INTR_0_CACHE_ERROR                             0:0 /* RWXVF */
-#define NV_PFIFO_INTR_0_CACHE_ERROR_NOT_PENDING          0x00000000 /* R---V */
-#define NV_PFIFO_INTR_0_CACHE_ERROR_PENDING              0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0_CACHE_ERROR_RESET                0x00000001 /* -W--V */
-#define NV_PFIFO_INTR_0_RUNOUT                                  4:4 /* RWXVF */
-#define NV_PFIFO_INTR_0_RUNOUT_NOT_PENDING               0x00000000 /* R---V */
-#define NV_PFIFO_INTR_0_RUNOUT_PENDING                   0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0_RUNOUT_RESET                     0x00000001 /* -W--V */
-#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW                         8:8 /* RWXVF */
-#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_NOT_PENDING      0x00000000 /* R---V */
-#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_PENDING          0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_RESET            0x00000001 /* -W--V */
-#define NV_PFIFO_INTR_0_DMA_PUSHER                            12:12 /* RWXVF */
-#define NV_PFIFO_INTR_0_DMA_PUSHER_NOT_PENDING           0x00000000 /* R---V */
-#define NV_PFIFO_INTR_0_DMA_PUSHER_PENDING               0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0_DMA_PUSHER_RESET                 0x00000001 /* -W--V */
-#define NV_PFIFO_INTR_0_DMA_PT                                16:16 /* RWXVF */
-#define NV_PFIFO_INTR_0_DMA_PT_NOT_PENDING               0x00000000 /* R---V */
-#define NV_PFIFO_INTR_0_DMA_PT_PENDING                   0x00000001 /* R---V */
-#define NV_PFIFO_INTR_0_DMA_PT_RESET                     0x00000001 /* -W--V */
-#define NV_PFIFO_INTR_EN_0                               0x00002140 /* RW-4R */
-#define NV_PFIFO_INTR_EN_0_CACHE_ERROR                          0:0 /* RWIVF */
-#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_DISABLED          0x00000000 /* RWI-V */
-#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_ENABLED           0x00000001 /* RW--V */
-#define NV_PFIFO_INTR_EN_0_RUNOUT                               4:4 /* RWIVF */
-#define NV_PFIFO_INTR_EN_0_RUNOUT_DISABLED               0x00000000 /* RWI-V */
-#define NV_PFIFO_INTR_EN_0_RUNOUT_ENABLED                0x00000001 /* RW--V */
-#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW                      8:8 /* RWIVF */
-#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_DISABLED      0x00000000 /* RWI-V */
-#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_ENABLED       0x00000001 /* RW--V */
-#define NV_PFIFO_INTR_EN_0_DMA_PUSHER                         12:12 /* RWIVF */
-#define NV_PFIFO_INTR_EN_0_DMA_PUSHER_DISABLED           0x00000000 /* RWI-V */
-#define NV_PFIFO_INTR_EN_0_DMA_PUSHER_ENABLED            0x00000001 /* RW--V */
-#define NV_PFIFO_INTR_EN_0_DMA_PT                             16:16 /* RWIVF */
-#define NV_PFIFO_INTR_EN_0_DMA_PT_DISABLED               0x00000000 /* RWI-V */
-#define NV_PFIFO_INTR_EN_0_DMA_PT_ENABLED                0x00000001 /* RW--V */
-#define NV_PFIFO_RAMHT                                   0x00002210 /* RW-4R */
-#define NV_PFIFO_RAMHT_BASE_ADDRESS                             8:4 /* RWIUF */
-#define NV_PFIFO_RAMHT_BASE_ADDRESS_10000                0x00000010 /* RWI-V */
-#define NV_PFIFO_RAMHT_SIZE                                   17:16 /* RWIUF */
-#define NV_PFIFO_RAMHT_SIZE_4K                           0x00000000 /* RWI-V */
-#define NV_PFIFO_RAMHT_SIZE_8K                           0x00000001 /* RW--V */
-#define NV_PFIFO_RAMHT_SIZE_16K                          0x00000002 /* RW--V */
-#define NV_PFIFO_RAMHT_SIZE_32K                          0x00000003 /* RW--V */
-#define NV_PFIFO_RAMHT_SEARCH                                 25:24 /* RWIUF */
-#define NV_PFIFO_RAMHT_SEARCH_16                         0x00000000 /* RWI-V */
-#define NV_PFIFO_RAMHT_SEARCH_32                         0x00000001 /* RW--V */
-#define NV_PFIFO_RAMHT_SEARCH_64                         0x00000002 /* RW--V */
-#define NV_PFIFO_RAMHT_SEARCH_128                        0x00000003 /* RW--V */
-#define NV_PFIFO_RAMFC                                   0x00002214 /* RW-4R */
-#define NV_PFIFO_RAMFC_BASE_ADDRESS                             8:1 /* RWIUF */
-#define NV_PFIFO_RAMFC_BASE_ADDRESS_11000                0x00000088 /* RWI-V */
-#define NV_PFIFO_RAMRO                                   0x00002218 /* RW-4R */
-#define NV_PFIFO_RAMRO_BASE_ADDRESS                             8:1 /* RWIUF */
-#define NV_PFIFO_RAMRO_BASE_ADDRESS_11200                0x00000089 /* RWI-V */
-#define NV_PFIFO_RAMRO_BASE_ADDRESS_12000                0x00000090 /* RW--V */
-#define NV_PFIFO_RAMRO_SIZE                                   16:16 /* RWIVF */
-#define NV_PFIFO_RAMRO_SIZE_512                          0x00000000 /* RWI-V */
-#define NV_PFIFO_RAMRO_SIZE_8K                           0x00000001 /* RW--V */
-#define NV_PFIFO_CACHES                                  0x00002500 /* RW-4R */
-#define NV_PFIFO_CACHES_REASSIGN                                0:0 /* RWIVF */
-#define NV_PFIFO_CACHES_REASSIGN_DISABLED                0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHES_REASSIGN_ENABLED                 0x00000001 /* RW--V */
-#define NV_PFIFO_CACHES_DMA_SUSPEND                             4:4 /* R--VF */
-#define NV_PFIFO_CACHES_DMA_SUSPEND_IDLE                 0x00000000 /* R---V */
-#define NV_PFIFO_CACHES_DMA_SUSPEND_BUSY                 0x00000001 /* R---V */
-#define NV_PFIFO_MODE                                    0x00002504 /* RW-4R */
-#define NV_PFIFO_MODE_CHANNEL_0                                 0:0 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_0_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_0_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_1                                 1:1 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_1_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_1_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_2                                 2:2 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_2_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_2_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_3                                 3:3 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_3_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_3_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_4                                 4:4 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_4_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_4_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_5                                 5:5 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_5_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_5_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_6                                 6:6 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_6_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_6_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_7                                 7:7 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_7_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_7_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_8                                 8:8 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_8_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_8_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_9                                 9:9 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_9_PIO                      0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_9_DMA                      0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_10                              10:10 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_10_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_10_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_11                              11:11 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_11_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_11_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_12                              12:12 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_12_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_12_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_13                              13:13 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_13_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_13_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_14                              14:14 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_14_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_14_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_MODE_CHANNEL_15                              15:15 /* RWIVF */
-#define NV_PFIFO_MODE_CHANNEL_15_PIO                     0x00000000 /* RWI-V */
-#define NV_PFIFO_MODE_CHANNEL_15_DMA                     0x00000001 /* RW--V */
-#define NV_PFIFO_DMA                                     0x00002508 /* RW-4R */
-#define NV_PFIFO_DMA_CHANNEL_0                                  0:0 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_0_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_0_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_1                                  1:1 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_1_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_1_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_2                                  2:2 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_2_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_2_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_3                                  3:3 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_3_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_3_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_4                                  4:4 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_4_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_4_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_5                                  5:5 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_5_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_5_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_6                                  6:6 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_6_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_6_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_7                                  7:7 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_7_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_7_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_8                                  8:8 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_8_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_8_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_9                                  9:9 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_9_NOT_PENDING               0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_9_PENDING                   0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_10                               10:10 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_10_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_10_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_11                               11:11 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_11_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_11_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_12                               12:12 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_12_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_12_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_13                               13:13 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_13_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_13_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_14                               14:14 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_14_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_14_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_DMA_CHANNEL_15                               15:15 /* RWIVF */
-#define NV_PFIFO_DMA_CHANNEL_15_NOT_PENDING              0x00000000 /* RWI-V */
-#define NV_PFIFO_DMA_CHANNEL_15_PENDING                  0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE                                    0x0000250C /* RW-4R */
-#define NV_PFIFO_SIZE_CHANNEL_0                                 0:0 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_0_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_0_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_1                                 1:1 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_1_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_1_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_2                                 2:2 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_2_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_2_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_3                                 3:3 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_3_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_3_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_4                                 4:4 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_4_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_4_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_5                                 5:5 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_5_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_5_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_6                                 6:6 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_6_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_6_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_7                                 7:7 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_7_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_7_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_8                                 8:8 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_8_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_8_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_9                                 9:9 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_9_124_BYTES                0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_9_512_BYTES                0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_10                              10:10 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_10_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_10_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_11                              11:11 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_11_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_11_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_12                              12:12 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_12_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_12_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_13                              13:13 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_13_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_13_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_14                              14:14 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_14_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_14_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_SIZE_CHANNEL_15                              15:15 /* RWIVF */
-#define NV_PFIFO_SIZE_CHANNEL_15_124_BYTES               0x00000000 /* RWI-V */
-#define NV_PFIFO_SIZE_CHANNEL_15_512_BYTES               0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_PUSH0                            0x00003000 /* RW-4R */
-#define NV_PFIFO_CACHE0_PUSH0_ACCESS                            0:0 /* RWIVF */
-#define NV_PFIFO_CACHE0_PUSH0_ACCESS_DISABLED            0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE0_PUSH0_ACCESS_ENABLED             0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_PUSH0                            0x00003200 /* RW-4R */
-#define NV_PFIFO_CACHE1_PUSH0_ACCESS                            0:0 /* RWIVF */
-#define NV_PFIFO_CACHE1_PUSH0_ACCESS_DISABLED            0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_PUSH0_ACCESS_ENABLED             0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_PUSH1                            0x00003004 /* RW-4R */
-#define NV_PFIFO_CACHE0_PUSH1_CHID                              3:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_PUSH1                            0x00003204 /* RW-4R */
-#define NV_PFIFO_CACHE1_PUSH1_CHID                              3:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_PUSH1_MODE                              8:8 /* RWIVF */
-#define NV_PFIFO_CACHE1_PUSH1_MODE_PIO                   0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_PUSH1_MODE_DMA                   0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_PUSH                         0x00003220 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS                         0:0 /* RWIVF */
-#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_DISABLED         0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_ENABLED          0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATE                          4:4 /* R--VF */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATE_IDLE              0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATE_BUSY              0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER                         8:8 /* R--VF */
-#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER_NOT_EMPTY        0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER_EMPTY            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS                       12:12 /* RWIVF */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS_RUNNING          0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS_SUSPENDED        0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH                        0x00003224 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG                          7:3 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES           0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES          0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES          0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES          0x00000003 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES          0x00000004 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES          0x00000005 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES          0x00000006 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES          0x00000007 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES          0x00000008 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES          0x00000009 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES          0x0000000A /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES          0x0000000B /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES         0x0000000C /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES         0x0000000D /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES         0x0000000E /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES         0x0000000F /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES         0x00000010 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES         0x00000011 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES         0x00000012 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES         0x00000013 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES         0x00000014 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES         0x00000015 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES         0x00000016 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES         0x00000017 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES         0x00000018 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES         0x00000019 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES         0x0000001A /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES         0x0000001B /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES         0x0000001C /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES         0x0000001D /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES         0x0000001E /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES         0x0000001F /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE                        15:13 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES          0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES          0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES          0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES         0x00000003 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES         0x00000004 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES         0x00000005 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES         0x00000006 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES         0x00000007 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS                    19:16 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0             0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1             0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2             0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3             0x00000003 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4             0x00000004 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5             0x00000005 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6             0x00000006 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7             0x00000007 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8             0x00000008 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9             0x00000009 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10            0x0000000A /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11            0x0000000B /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12            0x0000000C /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13            0x0000000D /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14            0x0000000E /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15            0x0000000F /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_PUT                          0x00003240 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_PUT_OFFSET                         28:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_GET                          0x00003244 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_GET_OFFSET                         28:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_STATE                        0x00003228 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_STATE_METHOD                       12:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL                  15:13 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT                28:18 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT_0         0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_STATE_ERROR                       31:30 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE             0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NON_CACHE        0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION       0x00000003 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_INSTANCE                     0x0000322C /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS                   15:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_CTL                          0x00003230 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_CTL_ADJUST                         11:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE                    12:12 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_NOT_PRESENT   0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_PRESENT       0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY                    13:13 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_NOT_LINEAR    0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_LINEAR        0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE                   17:16 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE_PCI          0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE_AGP          0x00000003 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO                       31:31 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO_INVALID          0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO_VALID            0x00000001 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_LIMIT                        0x00003234 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_LIMIT_OFFSET                       28:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_TLB_TAG                      0x00003238 /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_TLB_TAG_ADDRESS                   28:12 /* RWXUF */
-#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE                       0:0 /* RWIUF */
-#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE_INVALID        0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE_VALID          0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_DMA_TLB_PTE                      0x0000323C /* RW-4R */
-#define NV_PFIFO_CACHE1_DMA_TLB_PTE_FRAME_ADDRESS             31:12 /* RWXUF */
-#define NV_PFIFO_CACHE0_PULL0                            0x00003050 /* RW-4R */
-#define NV_PFIFO_CACHE0_PULL0_ACCESS                            0:0 /* RWIVF */
-#define NV_PFIFO_CACHE0_PULL0_ACCESS_DISABLED            0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE0_PULL0_ACCESS_ENABLED             0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_PULL0_HASH                              4:4 /* R-XVF */
-#define NV_PFIFO_CACHE0_PULL0_HASH_SUCCEEDED             0x00000000 /* R---V */
-#define NV_PFIFO_CACHE0_PULL0_HASH_FAILED                0x00000001 /* R---V */
-#define NV_PFIFO_CACHE0_PULL0_DEVICE                            8:8 /* R-XVF */
-#define NV_PFIFO_CACHE0_PULL0_DEVICE_HARDWARE            0x00000000 /* R---V */
-#define NV_PFIFO_CACHE0_PULL0_DEVICE_SOFTWARE            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE0_PULL0_HASH_STATE                      12:12 /* R-XVF */
-#define NV_PFIFO_CACHE0_PULL0_HASH_STATE_IDLE            0x00000000 /* R---V */
-#define NV_PFIFO_CACHE0_PULL0_HASH_STATE_BUSY            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0                            0x00003250 /* RW-4R */
-#define NV_PFIFO_CACHE1_PULL0_ACCESS                            0:0 /* RWIVF */
-#define NV_PFIFO_CACHE1_PULL0_ACCESS_DISABLED            0x00000000 /* RWI-V */
-#define NV_PFIFO_CACHE1_PULL0_ACCESS_ENABLED             0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_PULL0_HASH                              4:4 /* R-XVF */
-#define NV_PFIFO_CACHE1_PULL0_HASH_SUCCEEDED             0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0_HASH_FAILED                0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0_DEVICE                            8:8 /* R-XVF */
-#define NV_PFIFO_CACHE1_PULL0_DEVICE_HARDWARE            0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0_DEVICE_SOFTWARE            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0_HASH_STATE                      12:12 /* R-XVF */
-#define NV_PFIFO_CACHE1_PULL0_HASH_STATE_IDLE            0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_PULL0_HASH_STATE_BUSY            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE0_PULL1                            0x00003054 /* RW-4R */
-#define NV_PFIFO_CACHE0_PULL1_ENGINE                            1:0 /* RWXUF */
-#define NV_PFIFO_CACHE0_PULL1_ENGINE_SW                  0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_PULL1_ENGINE_GRAPHICS            0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_PULL1_ENGINE_DVD                 0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_PULL1                            0x00003254 /* RW-4R */
-#define NV_PFIFO_CACHE1_PULL1_ENGINE                            1:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_PULL1_ENGINE_SW                  0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_PULL1_ENGINE_GRAPHICS            0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_PULL1_ENGINE_DVD                 0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_HASH                             0x00003058 /* RW-4R */
-#define NV_PFIFO_CACHE0_HASH_INSTANCE                          15:0 /* RWXUF */
-#define NV_PFIFO_CACHE0_HASH_VALID                            16:16 /* RWXVF */
-#define NV_PFIFO_CACHE1_HASH                             0x00003258 /* RW-4R */
-#define NV_PFIFO_CACHE1_HASH_INSTANCE                          15:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_HASH_VALID                            16:16 /* RWXVF */
-#define NV_PFIFO_CACHE0_STATUS                           0x00003014 /* R--4R */
-#define NV_PFIFO_CACHE0_STATUS_LOW_MARK                         4:4 /* R--VF */
-#define NV_PFIFO_CACHE0_STATUS_LOW_MARK_NOT_EMPTY        0x00000000 /* R---V */
-#define NV_PFIFO_CACHE0_STATUS_LOW_MARK_EMPTY            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK                        8:8 /* R--VF */
-#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK_NOT_FULL        0x00000000 /* R---V */
-#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK_FULL            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS                           0x00003214 /* R--4R */
-#define NV_PFIFO_CACHE1_STATUS_LOW_MARK                         4:4 /* R--VF */
-#define NV_PFIFO_CACHE1_STATUS_LOW_MARK_NOT_EMPTY        0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS_LOW_MARK_EMPTY            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK                        8:8 /* R--VF */
-#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK_NOT_FULL        0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK_FULL            0x00000001 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS1                          0x00003218 /* R--4R */
-#define NV_PFIFO_CACHE1_STATUS1_RANOUT                          0:0 /* R-XVF */
-#define NV_PFIFO_CACHE1_STATUS1_RANOUT_FALSE             0x00000000 /* R---V */
-#define NV_PFIFO_CACHE1_STATUS1_RANOUT_TRUE              0x00000001 /* R---V */
-#define NV_PFIFO_CACHE0_PUT                              0x00003010 /* RW-4R */
-#define NV_PFIFO_CACHE0_PUT_ADDRESS                             2:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_PUT                              0x00003210 /* RW-4R */
-#define NV_PFIFO_CACHE1_PUT_ADDRESS                             9:2 /* RWXUF */
-#define NV_PFIFO_CACHE0_GET                              0x00003070 /* RW-4R */
-#define NV_PFIFO_CACHE0_GET_ADDRESS                             2:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_GET                              0x00003270 /* RW-4R */
-#define NV_PFIFO_CACHE1_GET_ADDRESS                             9:2 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE                           0x00003080 /* RW-4R */
-#define NV_PFIFO_CACHE0_ENGINE_0                                1:0 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_0_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_0_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_0_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_1                                5:4 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_1_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_1_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_1_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_2                                9:8 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_2_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_2_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_2_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_3                              13:12 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_3_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_3_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_3_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_4                              17:16 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_4_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_4_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_4_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_5                              21:20 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_5_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_5_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_5_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_6                              25:24 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_6_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_6_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_6_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_7                              29:28 /* RWXUF */
-#define NV_PFIFO_CACHE0_ENGINE_7_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_7_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE0_ENGINE_7_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE                           0x00003280 /* RW-4R */
-#define NV_PFIFO_CACHE1_ENGINE_0                                1:0 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_0_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_0_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_0_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_1                                5:4 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_1_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_1_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_1_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_2                                9:8 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_2_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_2_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_2_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_3                              13:12 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_3_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_3_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_3_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_4                              17:16 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_4_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_4_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_4_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_5                              21:20 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_5_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_5_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_5_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_6                              25:24 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_6_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_6_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_6_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_7                              29:28 /* RWXUF */
-#define NV_PFIFO_CACHE1_ENGINE_7_SW                      0x00000000 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_7_GRAPHICS                0x00000001 /* RW--V */
-#define NV_PFIFO_CACHE1_ENGINE_7_DVD                     0x00000002 /* RW--V */
-#define NV_PFIFO_CACHE0_METHOD(i)                (0x00003100+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE0_METHOD__SIZE_1                            1 /*       */
-#define NV_PFIFO_CACHE0_METHOD_ADDRESS                         12:2 /* RWXUF */
-#define NV_PFIFO_CACHE0_METHOD_SUBCHANNEL                     15:13 /* RWXUF */
-#define NV_PFIFO_CACHE1_METHOD(i)                (0x00003800+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE1_METHOD__SIZE_1                          128 /*       */
-#define NV_PFIFO_CACHE1_METHOD_ADDRESS                         12:2 /* RWXUF */
-#define NV_PFIFO_CACHE1_METHOD_SUBCHANNEL                     15:13 /* RWXUF */
-#define NV_PFIFO_CACHE1_METHOD_ALIAS(i)          (0x00003C00+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE1_METHOD_ALIAS__SIZE_1                    128 /*       */
-#define NV_PFIFO_CACHE0_DATA(i)                  (0x00003104+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE0_DATA__SIZE_1                              1 /*       */
-#define NV_PFIFO_CACHE0_DATA_VALUE                             31:0 /* RWXVF */
-#define NV_PFIFO_CACHE1_DATA(i)                  (0x00003804+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE1_DATA__SIZE_1                            128 /*       */
-#define NV_PFIFO_CACHE1_DATA_VALUE                             31:0 /* RWXVF */
-#define NV_PFIFO_CACHE1_DATA_ALIAS(i)            (0x00003C04+(i)*8) /* RW-4A */
-#define NV_PFIFO_CACHE1_DATA_ALIAS__SIZE_1                      128 /*       */
-#define NV_PFIFO_DEVICE(i)                       (0x00002800+(i)*4) /* R--4A */
-#define NV_PFIFO_DEVICE__SIZE_1                                 128 /*       */
-#define NV_PFIFO_DEVICE_CHID                                    3:0 /* R--UF */
-#define NV_PFIFO_DEVICE_SWITCH                                24:24 /* R--VF */
-#define NV_PFIFO_DEVICE_SWITCH_UNAVAILABLE               0x00000000 /* R---V */
-#define NV_PFIFO_DEVICE_SWITCH_AVAILABLE                 0x00000001 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS                           0x00002400 /* R--4R */
-#define NV_PFIFO_RUNOUT_STATUS_RANOUT                           0:0 /* R--VF */
-#define NV_PFIFO_RUNOUT_STATUS_RANOUT_FALSE              0x00000000 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS_RANOUT_TRUE               0x00000001 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK                         4:4 /* R--VF */
-#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK_NOT_EMPTY        0x00000000 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK_EMPTY            0x00000001 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK                        8:8 /* R--VF */
-#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK_NOT_FULL        0x00000000 /* R---V */
-#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK_FULL            0x00000001 /* R---V */
-#define NV_PFIFO_RUNOUT_PUT                              0x00002410 /* RW-4R */
-#define NV_PFIFO_RUNOUT_PUT_ADDRESS                            12:3 /* RWXUF */
-#define NV_PFIFO_RUNOUT_PUT_ADDRESS__SIZE_0                     8:3 /* RWXUF */
-#define NV_PFIFO_RUNOUT_PUT_ADDRESS__SIZE_1                    12:3 /* RWXUF */
-#define NV_PFIFO_RUNOUT_GET                              0x00002420 /* RW-4R */
-#define NV_PFIFO_RUNOUT_GET_ADDRESS                            13:3 /* RWXUF */
-/* dev_graphics.ref */
-#define NV_PGRAPH                             0x00401FFF:0x00400000 /* RW--D */
-#define NV_PGRAPH_DEBUG_0                                0x00400080 /* RW-4R */
-#define NV_PGRAPH_DEBUG_1                                0x00400084 /* RW-4R */
-#define NV_PGRAPH_DEBUG_2                                0x00400088 /* RW-4R */
-#define NV_PGRAPH_DEBUG_3                                0x0040008C /* RW-4R */
-#define NV_PGRAPH_INTR                                   0x00400100 /* RW-4R */
-#define NV_PGRAPH_INTR_NOTIFY                                   0:0 /* RWIVF */
-#define NV_PGRAPH_INTR_NOTIFY_NOT_PENDING                0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_NOTIFY_PENDING                    0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_NOTIFY_RESET                      0x00000001 /* -W--C */
-#define NV_PGRAPH_INTR_MISSING_HW                               4:4 /* RWIVF */
-#define NV_PGRAPH_INTR_MISSING_HW_NOT_PENDING            0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_MISSING_HW_PENDING                0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_MISSING_HW_RESET                  0x00000001 /* -W--C */
-#define NV_PGRAPH_INTR_TLB_PRESENT_A                            8:8 /* RWIVF */
-#define NV_PGRAPH_INTR_TLB_PRESENT_A_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_TLB_PRESENT_A_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_TLB_PRESENT_A_RESET               0x00000001 /* -W--C */
-#define NV_PGRAPH_INTR_TLB_PRESENT_B                            9:9 /* RWIVF */
-#define NV_PGRAPH_INTR_TLB_PRESENT_B_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_TLB_PRESENT_B_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_TLB_PRESENT_B_RESET               0x00000001 /* -W--C */
-#define NV_PGRAPH_INTR_CONTEXT_SWITCH                         12:12 /* RWIVF */
-#define NV_PGRAPH_INTR_CONTEXT_SWITCH_NOT_PENDING        0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_CONTEXT_SWITCH_PENDING            0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_CONTEXT_SWITCH_RESET              0x00000001 /* -W--C */
-#define NV_PGRAPH_INTR_BUFFER_NOTIFY                          16:16 /* RWIVF */
-#define NV_PGRAPH_INTR_BUFFER_NOTIFY_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_INTR_BUFFER_NOTIFY_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_BUFFER_NOTIFY_RESET               0x00000001 /* -W--C */
-#define NV_PGRAPH_NSTATUS                                0x00400104 /* RW-4R */
-#define NV_PGRAPH_NSTATUS_STATE_IN_USE                        11:11 /* RWIVF */
-#define NV_PGRAPH_NSTATUS_STATE_IN_USE_NOT_PENDING       0x00000000 /* RWI-V */
-#define NV_PGRAPH_NSTATUS_STATE_IN_USE_PENDING           0x00000001 /* RW--V */
-#define NV_PGRAPH_NSTATUS_INVALID_STATE                       12:12 /* RWIVF */
-#define NV_PGRAPH_NSTATUS_INVALID_STATE_NOT_PENDING      0x00000000 /* RWI-V */
-#define NV_PGRAPH_NSTATUS_INVALID_STATE_PENDING          0x00000001 /* RW--V */
-#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT                        13:13 /* RWIVF */
-#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT_NOT_PENDING       0x00000000 /* RWI-V */
-#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT_PENDING           0x00000001 /* RW--V */
-#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT                    14:14 /* RWIVF */
-#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT_NOT_PENDING   0x00000000 /* RWI-V */
-#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT_PENDING       0x00000001 /* RW--V */
-#define NV_PGRAPH_NSOURCE                                0x00400108 /* R--4R */
-#define NV_PGRAPH_NSOURCE_NOTIFICATION                          0:0 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_NOTIFICATION_NOT_PENDING       0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_NOTIFICATION_PENDING           0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_DATA_ERROR                            1:1 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_DATA_ERROR_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_DATA_ERROR_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR                      2:2 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR_NOT_PENDING   0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR_PENDING       0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION                       3:3 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION_NOT_PENDING    0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION_PENDING        0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_LIMIT_COLOR                           4:4 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_LIMIT_COLOR_NOT_PENDING        0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_LIMIT_COLOR_PENDING            0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_                           5:5 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD                          6:6 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD_NOT_PENDING       0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD_PENDING           0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION                      7:7 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION_NOT_PENDING   0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION_PENDING       0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION                      8:8 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION_NOT_PENDING   0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION_PENDING       0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION                      9:9 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION_NOT_PENDING   0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION_PENDING       0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION                     10:10 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION_NOT_PENDING    0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION_PENDING        0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_STATE_INVALID                       11:11 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_STATE_INVALID_NOT_PENDING      0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_STATE_INVALID_PENDING          0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY                       12:12 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY_NOT_PENDING      0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY_PENDING          0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE                       13:13 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE_NOT_PENDING      0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE_PENDING          0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_METHOD_CNT                          14:14 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_METHOD_CNT_NOT_PENDING         0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_METHOD_CNT_PENDING             0x00000001 /* R---V */
-#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION                    15:15 /* R-IVF */
-#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION_NOT_PENDING   0x00000000 /* R-I-V */
-#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION_PENDING       0x00000001 /* R---V */
-#define NV_PGRAPH_INTR_EN                                0x00400140 /* RW-4R */
-#define NV_PGRAPH_INTR_EN_NOTIFY                                0:0 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_NOTIFY_DISABLED                0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_NOTIFY_ENABLED                 0x00000001 /* RW--V */
-#define NV_PGRAPH_INTR_EN_MISSING_HW                            4:4 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_MISSING_HW_DISABLED            0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_MISSING_HW_ENABLED             0x00000001 /* RW--V */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A                         8:8 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A_DISABLED         0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A_ENABLED          0x00000001 /* RW--V */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B                         9:9 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B_DISABLED         0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B_ENABLED          0x00000001 /* RW--V */
-#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH                      12:12 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH_DISABLED        0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH_ENABLED         0x00000001 /* RW--V */
-#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY                       16:16 /* RWIVF */
-#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY_DISABLED         0x00000000 /* RWI-V */
-#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY_ENABLED          0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1                            0x00400160 /* RW-4R */
-#define NV_PGRAPH_CTX_SWITCH1_GRCLASS                           7:0 /* RWXVF */
-#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY                      12:12 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY_DISABLE         0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY_ENABLE          0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP                       13:13 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP_DISABLE          0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP_ENABLE           0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE                         14:14 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE_DISABLE            0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE_ENABLE             0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG                    17:15 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY_AND   0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_ROP_AND       0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_BLEND_AND     0x00000002 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY       0x00000003 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY_PRE   0x00000004 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_BLEND_PRE     0x00000005 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS                    24:24 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS_INVALID       0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS_VALID         0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE                 25:25 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE_INVALID    0x00000000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE_VALID      0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET                  31:31 /* CWIVF */
-#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET_IGNORE      0x00000000 /* CWI-V */
-#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET_ENABLED     0x00000001 /* -W--T */
-#define NV_PGRAPH_CTX_SWITCH2                            0x00400164 /* RW-4R */
-#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT                       1:0 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_INVALID              0x00 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_CGA6_M1              0x01 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_LE_M1                0x02 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT                     13:8 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_INVALID             0x00 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y8               0x01 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16A8Y8          0x02 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X24Y8            0x03 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A1R5G5B5         0x06 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X1R5G5B5         0x07 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16A1R5G5B5      0x08 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X17R5G5B5        0x09 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_R5G6B5           0x0A /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A16R5G6B5        0x0B /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16R5G6B5        0x0C /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A8R8G8B8         0x0D /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X8R8G8B8         0x0E /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y16              0x0F /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A16Y16           0x10 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16Y16           0x11 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_V8YB8U8YA8       0x12 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_YB8V8YA8U8       0x13 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y32              0x14 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH2_NOTIFY_INSTANCE                 31:16 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH2_NOTIFY_INSTANCE_INVALID        0x0000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH3                            0x00400168 /* RW-4R */
-#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_0                   15:0 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_0_INVALID         0x0000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_1                  31:16 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_1_INVALID         0x0000 /* RW--V */
-#define NV_PGRAPH_CTX_SWITCH4                            0x0040016C /* RW-4R */
-#define NV_PGRAPH_CTX_SWITCH4_USER_INSTANCE                    15:0 /* RWXUF */
-#define NV_PGRAPH_CTX_SWITCH4_USER_INSTANCE_INVALID          0x0000 /* RW--V */
-#define NV_PGRAPH_CTX_CACHE1(i)                  (0x00400180+(i)*4) /* RW-4A */
-#define NV_PGRAPH_CTX_CACHE1__SIZE_1                              8 /*       */
-#define NV_PGRAPH_CTX_CACHE1_GRCLASS                            7:0 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_CHROMA_KEY                       12:12 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_USER_CLIP                        13:13 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_SWIZZLE                          14:14 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_PATCH_CONFIG                     19:15 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_SPARE1                           20:20 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_PATCH_STATUS                     24:24 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE1_CONTEXT_SURFACE                  25:25 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE2(i)                  (0x004001a0+(i)*4) /* RW-4A */
-#define NV_PGRAPH_CTX_CACHE2__SIZE_1                              8 /*       */
-#define NV_PGRAPH_CTX_CACHE2_MONO_FORMAT                        1:0 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE2_COLOR_FORMAT                      13:8 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE2_NOTIFY_INSTANCE                  31:16 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE3(i)                  (0x004001c0+(i)*4) /* RW-4A */
-#define NV_PGRAPH_CTX_CACHE3__SIZE_1                              8 /*       */
-#define NV_PGRAPH_CTX_CACHE3_DMA_INSTANCE_0                    15:0 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE3_DMA_INSTANCE_1                   31:16 /* RWXVF */
-#define NV_PGRAPH_CTX_CACHE4(i)                  (0x004001e0+(i)*4) /* RW-4A */
-#define NV_PGRAPH_CTX_CACHE4__SIZE_1                              8 /*       */
-#define NV_PGRAPH_CTX_CACHE4_USER_INSTANCE                     15:0 /* RWXVF */
-#define NV_PGRAPH_CTX_CONTROL                            0x00400170 /* RW-4R */
-#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME                      1:0 /* RWIVF */
-#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_33US          0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_262US         0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_2MS           0x00000002 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_17MS          0x00000003 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_TIME                              8:8 /* RWIVF */
-#define NV_PGRAPH_CTX_CONTROL_TIME_EXPIRED               0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_CONTROL_TIME_NOT_EXPIRED           0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_CHID                            16:16 /* RWIVF */
-#define NV_PGRAPH_CTX_CONTROL_CHID_INVALID               0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_CONTROL_CHID_VALID                 0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_CHANGE                          20:20 /* R--VF */
-#define NV_PGRAPH_CTX_CONTROL_CHANGE_UNAVAILABLE         0x00000000 /* R---V */
-#define NV_PGRAPH_CTX_CONTROL_CHANGE_AVAILABLE           0x00000001 /* R---V */
-#define NV_PGRAPH_CTX_CONTROL_SWITCHING                       24:24 /* RWIVF */
-#define NV_PGRAPH_CTX_CONTROL_SWITCHING_IDLE             0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_CONTROL_SWITCHING_BUSY             0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_CONTROL_DEVICE                          28:28 /* RWIVF */
-#define NV_PGRAPH_CTX_CONTROL_DEVICE_DISABLED            0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED             0x00000001 /* RW--V */
-#define NV_PGRAPH_CTX_USER                               0x00400174 /* RW-4R */
-#define NV_PGRAPH_CTX_USER_SUBCH                              15:13 /* RWIVF */
-#define NV_PGRAPH_CTX_USER_SUBCH_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_CTX_USER_CHID                               27:24 /* RWIVF */
-#define NV_PGRAPH_CTX_USER_CHID_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_FIFO                                   0x00400720 /* RW-4R */
-#define NV_PGRAPH_FIFO_ACCESS                                   0:0 /* RWIVF */
-#define NV_PGRAPH_FIFO_ACCESS_DISABLED                   0x00000000 /* RW--V */
-#define NV_PGRAPH_FIFO_ACCESS_ENABLED                    0x00000001 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_FIFO_0(i)              (0x00400730+(i)*4) /* RW-4A */
-#define NV_PGRAPH_FFINTFC_FIFO_0__SIZE_1                          4 /*       */
-#define NV_PGRAPH_FFINTFC_FIFO_0_TAG                            0:0 /* RWXVF */
-#define NV_PGRAPH_FFINTFC_FIFO_0_TAG_MTHD                0x00000000 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_TAG_CHSW                0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH                          3:1 /* RWXVF */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_0                 0x00000000 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_1                 0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_2                 0x00000002 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_3                 0x00000003 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_4                 0x00000004 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_5                 0x00000005 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_6                 0x00000006 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_7                 0x00000007 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_0_MTHD                          14:4 /* RWXVF */
-#define NV_PGRAPH_FFINTFC_FIFO_0_MTHD_CTX_SWITCH         0x00000000 /* RW--V */
-#define NV_PGRAPH_FFINTFC_FIFO_1(i)              (0x00400740+(i)*4) /* RW-4A */
-#define NV_PGRAPH_FFINTFC_FIFO_1__SIZE_1                          4 /*       */
-#define NV_PGRAPH_FFINTFC_FIFO_1_ARGUMENT                      31:0 /* RWXVF */
-#define NV_PGRAPH_FFINTFC_FIFO_PTR                       0x00400750 /* RW-4R */
-#define NV_PGRAPH_FFINTFC_FIFO_PTR_WRITE                        2:0 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_FIFO_PTR_WRITE_0               0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_FIFO_PTR_READ                         6:4 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_FIFO_PTR_READ_0                0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2                            0x00400754 /* RW-4R */
-#define NV_PGRAPH_FFINTFC_ST2_STATUS                            0:0 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_STATUS_INVALID             0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2_STATUS_VALID               0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_MTHD                             11:1 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_MTHD_CTX_SWITCH            0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH                           14:12 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_0                    0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_1                    0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_2                    0x00000002 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_3                    0x00000003 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_4                    0x00000004 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_5                    0x00000005 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_6                    0x00000006 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_SUBCH_7                    0x00000007 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID                            18:15 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_1                     0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_2                     0x00000002 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_3                     0x00000003 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_4                     0x00000004 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_5                     0x00000005 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_6                     0x00000006 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_7                     0x00000007 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_8                     0x00000008 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_9                     0x00000009 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_10                    0x0000000A /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_11                    0x0000000B /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_12                    0x0000000C /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_13                    0x0000000D /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_14                    0x0000000E /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_15                    0x0000000F /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS                     19:19 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_INVALID        0x00000000 /* RWI-V */
-#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_VALID          0x00000001 /* RW--V */
-#define NV_PGRAPH_FFINTFC_ST2_D                          0x00400758 /* RW-4R */
-#define NV_PGRAPH_FFINTFC_ST2_D_ARGUMENT                       31:0 /* RWIVF */
-#define NV_PGRAPH_FFINTFC_ST2_D_ARGUMENT_0               0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATUS                                 0x00400700 /* R--4R */
-#define NV_PGRAPH_STATUS_STATE                                  0:0 /* R-IVF */
-#define NV_PGRAPH_STATUS_STATE_IDLE                      0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_STATE_BUSY                      0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_XY_LOGIC                               4:4 /* R-IVF */
-#define NV_PGRAPH_STATUS_XY_LOGIC_IDLE                   0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_XY_LOGIC_BUSY                   0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_FE                                     5:5 /* R-IVF */
-#define NV_PGRAPH_STATUS_FE_IDLE                         0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_FE_BUSY                         0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_RASTERIZER                             6:6 /* R-IVF */
-#define NV_PGRAPH_STATUS_RASTERIZER_IDLE                 0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_RASTERIZER_BUSY                 0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_PORT_NOTIFY                            8:8 /* R-IVF */
-#define NV_PGRAPH_STATUS_PORT_NOTIFY_IDLE                0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_PORT_NOTIFY_BUSY                0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_PORT_REGISTER                        12:12 /* R-IVF */
-#define NV_PGRAPH_STATUS_PORT_REGISTER_IDLE              0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_PORT_REGISTER_BUSY              0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_PORT_DMA                             16:16 /* R-IVF */
-#define NV_PGRAPH_STATUS_PORT_DMA_IDLE                   0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_PORT_DMA_BUSY                   0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_DMA_ENGINE                           17:17 /* R-IVF */
-#define NV_PGRAPH_STATUS_DMA_ENGINE_IDLE                 0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_DMA_ENGINE_BUSY                 0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_DMA_NOTIFY                           20:20 /* R-IVF */
-#define NV_PGRAPH_STATUS_DMA_NOTIFY_IDLE                 0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_DMA_NOTIFY_BUSY                 0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY                    21:21 /* R-IVF */
-#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY_IDLE          0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY_BUSY          0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_D3D                                  24:24 /* R-IVF */
-#define NV_PGRAPH_STATUS_D3D_IDLE                        0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_D3D_BUSY                        0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_CACHE                                25:25 /* R-IVF */
-#define NV_PGRAPH_STATUS_CACHE_IDLE                      0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_CACHE_BUSY                      0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_LIGHTING                             26:26 /* R-IVF */
-#define NV_PGRAPH_STATUS_LIGHTING_IDLE                   0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_LIGHTING_BUSY                   0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_PREROP                               27:27 /* R-IVF */
-#define NV_PGRAPH_STATUS_PREROP_IDLE                     0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_PREROP_BUSY                     0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_ROP                                  28:28 /* R-IVF */
-#define NV_PGRAPH_STATUS_ROP_IDLE                        0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_ROP_BUSY                        0x00000001 /* R---V */
-#define NV_PGRAPH_STATUS_PORT_USER                            29:29 /* R-IVF */
-#define NV_PGRAPH_STATUS_PORT_USER_IDLE                  0x00000000 /* R-I-V */
-#define NV_PGRAPH_STATUS_PORT_USER_BUSY                  0x00000001 /* R---V */
-#define NV_PGRAPH_TRAPPED_ADDR                           0x00400704 /* R--4R */
-#define NV_PGRAPH_TRAPPED_ADDR_MTHD                            12:2 /* R-XUF */
-#define NV_PGRAPH_TRAPPED_ADDR_SUBCH                          15:13 /* R-XUF */
-#define NV_PGRAPH_TRAPPED_ADDR_CHID                           27:24 /* R-XUF */
-#define NV_PGRAPH_TRAPPED_DATA                           0x00400708 /* R--4R */
-#define NV_PGRAPH_TRAPPED_DATA_VALUE                           31:0 /* R-XVF */
-#define NV_PGRAPH_SURFACE                                0x0040070C /* RW-4R */
-#define NV_PGRAPH_SURFACE_TYPE                                  1:0 /* RWIVF */
-#define NV_PGRAPH_SURFACE_TYPE_INVALID                   0x00000000 /* RWI-V */
-#define NV_PGRAPH_SURFACE_TYPE_NON_SWIZZLE               0x00000001 /* RW--V */
-#define NV_PGRAPH_SURFACE_TYPE_SWIZZLE                   0x00000002 /* RW--V */
-#define NV_PGRAPH_NOTIFY                                 0x00400714 /* RW-4R */
-#define NV_PGRAPH_NOTIFY_BUFFER_REQ                             0:0 /* RWIVF */
-#define NV_PGRAPH_NOTIFY_BUFFER_REQ_NOT_PENDING          0x00000000 /* RWI-V */
-#define NV_PGRAPH_NOTIFY_BUFFER_REQ_PENDING              0x00000001 /* RW--V */
-#define NV_PGRAPH_NOTIFY_BUFFER_STYLE                           8:8 /* RWIVF */
-#define NV_PGRAPH_NOTIFY_BUFFER_STYLE_WRITE_ONLY         0x00000000 /* RWI-V */
-#define NV_PGRAPH_NOTIFY_BUFFER_STYLE_WRITE_THEN_AWAKEN  0x00000001 /* RW--V */
-#define NV_PGRAPH_NOTIFY_REQ                                  16:16 /* RWIVF */
-#define NV_PGRAPH_NOTIFY_REQ_NOT_PENDING                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_NOTIFY_REQ_PENDING                     0x00000001 /* RW--V */
-#define NV_PGRAPH_NOTIFY_STYLE                                20:20 /* RWIVF */
-#define NV_PGRAPH_NOTIFY_STYLE_WRITE_ONLY                0x00000000 /* RWI-V */
-#define NV_PGRAPH_NOTIFY_STYLE_WRITE_THEN_AWAKEN         0x00000001 /* RW--V */
-#define NV_PGRAPH_BOFFSET(i)                     (0x00400640+(i)*4) /* RW-4A */
-#define NV_PGRAPH_BOFFSET__SIZE_1                                 6 /*       */
-#define NV_PGRAPH_BOFFSET_LINADRS                              23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET_LINADRS_0                      0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET0                               0x00400640 /* RW-4R */
-#define NV_PGRAPH_BOFFSET0__ALIAS_1            NV_PGRAPH_BOFFSET(0) /*       */
-#define NV_PGRAPH_BOFFSET0_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET0_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET1                               0x00400644 /* RW-4R */
-#define NV_PGRAPH_BOFFSET1__ALIAS_1            NV_PGRAPH_BOFFSET(1) /*       */
-#define NV_PGRAPH_BOFFSET1_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET1_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET2                               0x00400648 /* RW-4R */
-#define NV_PGRAPH_BOFFSET2__ALIAS_1            NV_PGRAPH_BOFFSET(2) /*       */
-#define NV_PGRAPH_BOFFSET2_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET2_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET3                               0x0040064C /* RW-4R */
-#define NV_PGRAPH_BOFFSET3__ALIAS_1            NV_PGRAPH_BOFFSET(3) /*       */
-#define NV_PGRAPH_BOFFSET3_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET3_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET4                               0x00400650 /* RW-4R */
-#define NV_PGRAPH_BOFFSET4__ALIAS_1            NV_PGRAPH_BOFFSET(4) /*       */
-#define NV_PGRAPH_BOFFSET4_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET4_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BOFFSET5                               0x00400654 /* RW-4R */
-#define NV_PGRAPH_BOFFSET5__ALIAS_1            NV_PGRAPH_BOFFSET(5) /*       */
-#define NV_PGRAPH_BOFFSET5_LINADRS                             23:0 /* RWIUF */
-#define NV_PGRAPH_BOFFSET5_LINADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE(i)                       (0x00400658+(i)*4) /* RW-4A */
-#define NV_PGRAPH_BBASE__SIZE_1                                   6 /*       */
-#define NV_PGRAPH_BBASE_LINADRS                                23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE_LINADRS_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE0                                 0x00400658 /* RW-4R */
-#define NV_PGRAPH_BBASE0__ALIAS_1                NV_PGRAPH_BBASE(0) /*       */
-#define NV_PGRAPH_BBASE0_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE0_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE1                                 0x0040065c /* RW-4R */
-#define NV_PGRAPH_BBASE1__ALIAS_1                NV_PGRAPH_BBASE(1) /*       */
-#define NV_PGRAPH_BBASE1_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE1_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE2                                 0x00400660 /* RW-4R */
-#define NV_PGRAPH_BBASE2__ALIAS_1                NV_PGRAPH_BBASE(2) /*       */
-#define NV_PGRAPH_BBASE2_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE2_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE3                                 0x00400664 /* RW-4R */
-#define NV_PGRAPH_BBASE3__ALIAS_1                NV_PGRAPH_BBASE(3) /*       */
-#define NV_PGRAPH_BBASE3_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE3_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE4                                 0x00400668 /* RW-4R */
-#define NV_PGRAPH_BBASE4__ALIAS_1                NV_PGRAPH_BBASE(4) /*       */
-#define NV_PGRAPH_BBASE4_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE4_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BBASE5                                 0x0040066C /* RW-4R */
-#define NV_PGRAPH_BBASE5__ALIAS_1                NV_PGRAPH_BBASE(5) /*       */
-#define NV_PGRAPH_BBASE5_LINADRS                               23:0 /* RWIUF */
-#define NV_PGRAPH_BBASE5_LINADRS_0                       0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH(i)                      (0x00400670+(i)*4) /* RW-4A */
-#define NV_PGRAPH_BPITCH__SIZE_1                                  5 /*       */
-#define NV_PGRAPH_BPITCH_VALUE                                 12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH_VALUE_0                         0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH0                                0x00400670 /* RW-4R */
-#define NV_PGRAPH_BPITCH0__ALIAS_1              NV_PGRAPH_BPITCH(0) /*       */
-#define NV_PGRAPH_BPITCH0_VALUE                                12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH0_VALUE_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH1                                0x00400674 /* RW-4R */
-#define NV_PGRAPH_BPITCH1__ALIAS_1              NV_PGRAPH_BPITCH(1) /*       */
-#define NV_PGRAPH_BPITCH1_VALUE                                12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH1_VALUE_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH2                                0x00400678 /* RW-4R */
-#define NV_PGRAPH_BPITCH2__ALIAS_1              NV_PGRAPH_BPITCH(2) /*       */
-#define NV_PGRAPH_BPITCH2_VALUE                                12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH2_VALUE_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH3                                0x0040067C /* RW-4R */
-#define NV_PGRAPH_BPITCH3__ALIAS_1              NV_PGRAPH_BPITCH(3) /*       */
-#define NV_PGRAPH_BPITCH3_VALUE                                12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH3_VALUE_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPITCH4                                0x00400680 /* RW-4R */
-#define NV_PGRAPH_BPITCH4__ALIAS_1              NV_PGRAPH_BPITCH(4) /*       */
-#define NV_PGRAPH_BPITCH4_VALUE                                12:0 /* RWIUF */
-#define NV_PGRAPH_BPITCH4_VALUE_0                        0x00000000 /* RWI-V */
-#define NV_PGRAPH_BLIMIT(i)                      (0x00400684+(i)*4) /* RW-4A */
-#define NV_PGRAPH_BLIMIT__SIZE_1                                  6 /*       */
-#define NV_PGRAPH_BLIMIT_VALUE                                 23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT_TYPE                                 31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT_TYPE_IN_MEMORY                  0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT_TYPE_NULL                       0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT0                                0x00400684 /* RW-4R */
-#define NV_PGRAPH_BLIMIT0__ALIAS_1              NV_PGRAPH_BLIMIT(0) /*       */
-#define NV_PGRAPH_BLIMIT0_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT0_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT0_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT0_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT1                                0x00400688 /* RW-4R */
-#define NV_PGRAPH_BLIMIT1__ALIAS_1              NV_PGRAPH_BLIMIT(1) /*       */
-#define NV_PGRAPH_BLIMIT1_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT1_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT1_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT1_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT2                                0x0040068c /* RW-4R */
-#define NV_PGRAPH_BLIMIT2__ALIAS_1              NV_PGRAPH_BLIMIT(2) /*       */
-#define NV_PGRAPH_BLIMIT2_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT2_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT2_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT2_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT3                                0x00400690 /* RW-4R */
-#define NV_PGRAPH_BLIMIT3__ALIAS_1              NV_PGRAPH_BLIMIT(3) /*       */
-#define NV_PGRAPH_BLIMIT3_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT3_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT3_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT3_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT4                                0x00400694 /* RW-4R */
-#define NV_PGRAPH_BLIMIT4__ALIAS_1              NV_PGRAPH_BLIMIT(4) /*       */
-#define NV_PGRAPH_BLIMIT4_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT4_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT4_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT4_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BLIMIT5                                0x00400698 /* RW-4R */
-#define NV_PGRAPH_BLIMIT5__ALIAS_1              NV_PGRAPH_BLIMIT(5) /*       */
-#define NV_PGRAPH_BLIMIT5_VALUE                                23:0 /* RWXUF */
-#define NV_PGRAPH_BLIMIT5_TYPE                                31:31 /* RWIVF */
-#define NV_PGRAPH_BLIMIT5_TYPE_IN_MEMORY                 0x00000000 /* RW--V */
-#define NV_PGRAPH_BLIMIT5_TYPE_NULL                      0x00000001 /* RWI-V */
-#define NV_PGRAPH_BSWIZZLE2                              0x0040069c /* RW-4R */
-#define NV_PGRAPH_BSWIZZLE2_WIDTH                             19:16 /* RWIUF */
-#define NV_PGRAPH_BSWIZZLE2_WIDTH_0                      0x00000000 /* RWI-V */
-#define NV_PGRAPH_BSWIZZLE2_HEIGHT                            27:24 /* RWIUF */
-#define NV_PGRAPH_BSWIZZLE2_HEIGHT_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BSWIZZLE5                              0x004006a0 /* RW-4R */
-#define NV_PGRAPH_BSWIZZLE5_WIDTH                             19:16 /* RWIUF */
-#define NV_PGRAPH_BSWIZZLE5_WIDTH_0                      0x00000000 /* RWI-V */
-#define NV_PGRAPH_BSWIZZLE5_HEIGHT                            27:24 /* RWIUF */
-#define NV_PGRAPH_BSWIZZLE5_HEIGHT_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL                                 0x00400724 /* RW-4R */
-#define NV_PGRAPH_BPIXEL_DEPTH0                                 3:0 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH0_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH0_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_BPIXEL_DEPTH1                                 7:4 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH1_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH1_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_BPIXEL_DEPTH2                                11:8 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH2_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH2_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_BPIXEL_DEPTH3                               15:12 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH3_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH3_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_BPIXEL_DEPTH4                               19:16 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH4_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH4_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_BPIXEL_DEPTH5                               23:20 /* RWIVF */
-#define NV_PGRAPH_BPIXEL_DEPTH5_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_Y8                       0x00000001 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X1R5G5B5_Z1R5G5B5        0x00000002 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X1R5G5B5_O1R5G5B5        0x00000003 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_A1R5G5B5                 0x00000004 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_R5G6B5                   0x00000005 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_Y16                      0x00000006 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_Z8R8G8B8        0x00000007 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_O1Z7R8G8B8      0x00000008 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X1A7R8G8B8_Z1A7R8G8B8    0x00000009 /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X1A7R8G8B8_O1A7R8G8B8    0x0000000a /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_O8R8G8B8        0x0000000b /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_A8R8G8B8                 0x0000000c /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_Y32                      0x0000000d /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_V8YB8U8YA8               0x0000000e /* RW--V */
-#define NV_PGRAPH_BPIXEL_DEPTH5_YB8V8YA8U8               0x0000000f /* RW--V */ 
-#define NV_PGRAPH_LIMIT_VIOL_PIX                         0x00400610 /* RW-4R */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_ADRS                          23:0 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_ADRS_0                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT                         29:29 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT_NO_VIOL            0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT_VIOL               0x00000001 /* RW--V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT                        30:30 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT_NO_VIOL           0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT_VIOL              0x00000001 /* RW--V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW                       31:31 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW_NO_VIOL          0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW_VIOL             0x00000001 /* RW--V */
-#define NV_PGRAPH_LIMIT_VIOL_Z                           0x00400614 /* RW-4R */
-#define NV_PGRAPH_LIMIT_VIOL_Z_ADRS                            23:0 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_Z_ADRS_0                    0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT                          30:30 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT_NO_VIOL             0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT_VIOL                0x00000001 /* RW--V */
-#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW                         31:31 /* RWIVF */
-#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW_NO_VIOL            0x00000000 /* RWI-V */
-#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW_VIOL               0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE                                  0x00400710 /* RW-4R */
-#define NV_PGRAPH_STATE_BUFFER_0                                0:0 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_0_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_0_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_BUFFER_1                                1:1 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_1_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_1_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_BUFFER_2                                2:2 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_2_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_2_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_BUFFER_3                                3:3 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_3_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_3_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_BUFFER_4                                4:4 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_4_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_4_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_BUFFER_5                                5:5 /* RWIVF */
-#define NV_PGRAPH_STATE_BUFFER_5_INVALID                 0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_BUFFER_5_VALID                   0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PITCH_0                                 8:8 /* RWIVF */
-#define NV_PGRAPH_STATE_PITCH_0_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PITCH_0_VALID                    0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PITCH_1                                 9:9 /* RWIVF */
-#define NV_PGRAPH_STATE_PITCH_1_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PITCH_1_VALID                    0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PITCH_2                               10:10 /* RWIVF */
-#define NV_PGRAPH_STATE_PITCH_2_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PITCH_2_VALID                    0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PITCH_3                               11:11 /* RWIVF */
-#define NV_PGRAPH_STATE_PITCH_3_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PITCH_3_VALID                    0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PITCH_4                               12:12 /* RWIVF */
-#define NV_PGRAPH_STATE_PITCH_4_INVALID                  0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PITCH_4_VALID                    0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_CHROMA_COLOR                          16:16 /* RWIVF */
-#define NV_PGRAPH_STATE_CHROMA_COLOR_INVALID             0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_CHROMA_COLOR_VALID               0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_CHROMA_COLORFMT                       17:17 /* RWIVF */
-#define NV_PGRAPH_STATE_CHROMA_COLORFMT_INVALID          0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_CHROMA_COLORFMT_VALID            0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_CPATTERN_COLORFMT                     20:20 /* RWIVF */
-#define NV_PGRAPH_STATE_CPATTERN_COLORFMT_INVALID        0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_CPATTERN_COLORFMT_VALID          0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_CPATTERN_MONOFMT                      21:21 /* RWIVF */
-#define NV_PGRAPH_STATE_CPATTERN_MONOFMT_INVALID         0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_CPATTERN_MONOFMT_VALID           0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_CPATTERN_SELECT                       22:22 /* RWIVF */
-#define NV_PGRAPH_STATE_CPATTERN_SELECT_INVALID          0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_CPATTERN_SELECT_VALID            0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PATTERN_COLOR0                        24:24 /* RWIVF */
-#define NV_PGRAPH_STATE_PATTERN_COLOR0_INVALID           0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PATTERN_COLOR0_VALID             0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PATTERN_COLOR1                        25:25 /* RWIVF */
-#define NV_PGRAPH_STATE_PATTERN_COLOR1_INVALID           0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PATTERN_COLOR1_VALID             0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PATTERN_PATT0                         26:26 /* RWIVF */
-#define NV_PGRAPH_STATE_PATTERN_PATT0_INVALID            0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PATTERN_PATT0_VALID              0x00000001 /* RW--V */
-#define NV_PGRAPH_STATE_PATTERN_PATT1                         27:27 /* RWIVF */
-#define NV_PGRAPH_STATE_PATTERN_PATT1_INVALID            0x00000000 /* RWI-V */
-#define NV_PGRAPH_STATE_PATTERN_PATT1_VALID              0x00000001 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX                            0x00400728 /* RW-4R */
-#define NV_PGRAPH_CACHE_INDEX_BANK                              2:2 /* RWXVF */
-#define NV_PGRAPH_CACHE_INDEX_BANK_10                    0x00000000 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_BANK_32                    0x00000001 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_ADRS                             12:3 /* RWXVF */
-#define NV_PGRAPH_CACHE_INDEX_ADRS_0                     0x00000000 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_ADRS_1024                  0x00000400 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_OP                              14:13 /* RWXVF */
-#define NV_PGRAPH_CACHE_INDEX_OP_WR_CACHE                0x00000000 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_OP_RD_CACHE                0x00000001 /* RW--V */
-#define NV_PGRAPH_CACHE_INDEX_OP_RD_INDEX                0x00000002 /* RW--V */
-#define NV_PGRAPH_CACHE_RAM                              0x0040072c /* RW-4R */
-#define NV_PGRAPH_CACHE_RAM_VALUE                              31:0 /* RWXVF */
-#define NV_PGRAPH_DMA_PITCH                              0x00400760 /* RW-4R */
-#define NV_PGRAPH_DMA_PITCH_S0                                 15:0 /* RWXSF */
-#define NV_PGRAPH_DMA_PITCH_S1                                31:16 /* RWXSF */
-#define NV_PGRAPH_DVD_COLORFMT                           0x00400764 /* RW-4R */
-#define NV_PGRAPH_DVD_COLORFMT_IMAGE                            5:0 /* RWNVF */
-#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_INVALID            0x00 /* RWN-V */
-#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_LE_V8YB8U8YA8      0x12 /* RW--V */
-#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_LE_YB8V8YA8U8      0x13 /* RW--V */
-#define NV_PGRAPH_DVD_COLORFMT_OVLY                             9:8 /* RWNVF */
-#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_INVALID             0x00 /* RWN-V */
-#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_LE_A8Y8U8V8         0x01 /* RW--V */
-#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_LE_A4V6YB6A4U6YA6   0x02 /* RW--V */
-#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_TRANSPARENT         0x03 /* RW--V */
-#define NV_PGRAPH_SCALED_FORMAT                          0x00400768 /* RW-4R */
-#define NV_PGRAPH_SCALED_FORMAT_ORIGIN                        17:16 /* RWIVF */
-#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_INVALID           0x00000000 /* RWI-V */
-#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_CENTER            0x00000001 /* RW--V */
-#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_CORNER            0x00000002 /* RW--V */
-#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR                  24:24 /* RWIVF */
-#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR_ZOH         0x00000000 /* RWI-V */
-#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR_FOH         0x00000001 /* RW--V */
-#define NV_PGRAPH_PATT_COLOR0                            0x00400800 /* RW-4R */
-#define NV_PGRAPH_PATT_COLOR0_VALUE                            31:0 /* RWXUF */
-#define NV_PGRAPH_PATT_COLOR1                            0x00400804 /* RW-4R */
-#define NV_PGRAPH_PATT_COLOR1_VALUE                            31:0 /* RWXUF */
-#define NV_PGRAPH_PATT_COLORRAM(i)               (0x00400900+(i)*4) /* R--4A */
-#define NV_PGRAPH_PATT_COLORRAM__SIZE_1                          64 /*       */
-#define NV_PGRAPH_PATT_COLORRAM_VALUE                          23:0 /* R--UF */
-#define NV_PGRAPH_PATTERN(i)                     (0x00400808+(i)*4) /* RW-4A */
-#define NV_PGRAPH_PATTERN__SIZE_1                                 2 /*       */
-#define NV_PGRAPH_PATTERN_BITMAP                               31:0 /* RWXVF */
-#define NV_PGRAPH_PATTERN_SHAPE                          0x00400810 /* RW-4R */
-#define NV_PGRAPH_PATTERN_SHAPE_VALUE                           1:0 /* RWXVF */
-#define NV_PGRAPH_PATTERN_SHAPE_VALUE_8X_8Y              0x00000000 /* RW--V */
-#define NV_PGRAPH_PATTERN_SHAPE_VALUE_64X_1Y             0x00000001 /* RW--V */
-#define NV_PGRAPH_PATTERN_SHAPE_VALUE_1X_64Y             0x00000002 /* RW--V */
-#define NV_PGRAPH_PATTERN_SHAPE_SELECT                          4:4 /* RWXVF */
-#define NV_PGRAPH_PATTERN_SHAPE_SELECT_2COLOR            0x00000000 /* RW--V */
-#define NV_PGRAPH_PATTERN_SHAPE_SELECT_FULLCOLOR         0x00000001 /* RW--V */
-#define NV_PGRAPH_MONO_COLOR0                            0x00400600 /* RW-4R */
-#define NV_PGRAPH_MONO_COLOR0_VALUE                            31:0 /* RWXUF */
-#define NV_PGRAPH_ROP3                                   0x00400604 /* RW-4R */
-#define NV_PGRAPH_ROP3_VALUE                                    7:0 /* RWXVF */
-#define NV_PGRAPH_CHROMA                                 0x00400814 /* RW-4R */
-#define NV_PGRAPH_CHROMA_VALUE                                 31:0 /* RWXUF */
-#define NV_PGRAPH_BETA_AND                               0x00400608 /* RW-4R */
-#define NV_PGRAPH_BETA_AND_VALUE_FRACTION                     30:23 /* RWXUF */
-#define NV_PGRAPH_BETA_PREMULT                           0x0040060c /* RW-4R */
-#define NV_PGRAPH_BETA_PREMULT_VALUE                           31:0 /* RWXUF */
-#define NV_PGRAPH_CONTROL0                               0x00400818 /* RW-4R */
-#define NV_PGRAPH_CONTROL1                               0x0040081c /* RW-4R */
-#define NV_PGRAPH_CONTROL2                               0x00400820 /* RW-4R */
-#define NV_PGRAPH_BLEND                                  0x00400824 /* RW-4R */
-#define NV_PGRAPH_DPRAM_INDEX                            0x00400828 /* RW-4R */
-#define NV_PGRAPH_DPRAM_INDEX_ADRS                              6:0 /* RWIVF */
-#define NV_PGRAPH_DPRAM_INDEX_ADRS_0                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT                           10:8 /* RWIVF */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_ADRS_0              0x00000000 /* RWI-V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_ADRS_1              0x00000001 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_DATA_0              0x00000002 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_DATA_1              0x00000003 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_WE_0                0x00000004 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_WE_1                0x00000005 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_ALPHA_0             0x00000006 /* RW--V */
-#define NV_PGRAPH_DPRAM_INDEX_SELECT_ALPHA_1             0x00000007 /* RW--V */
-#define NV_PGRAPH_DPRAM_DATA                             0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_DATA_VALUE                             31:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_ADRS_0                           0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_ADRS_0__ALIAS_1        NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_ADRS_0_VALUE                           19:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_ADRS_1                           0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_ADRS_1__ALIAS_1        NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_ADRS_1_VALUE                           19:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_DATA_0                           0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_DATA_0__ALIAS_1        NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_DATA_0_VALUE                           31:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_DATA_1                           0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_DATA_1__ALIAS_1        NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_DATA_1_VALUE                           31:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_WE_0                             0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_WE_0__ALIAS_1          NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_WE_0_VALUE                             23:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_WE_1                             0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_WE_1__ALIAS_1          NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_WE_1_VALUE                             23:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_ALPHA_0                          0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_ALPHA_0__ALIAS_1       NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_ALPHA_0_VALUE                          31:0 /* RWXVF */
-#define NV_PGRAPH_DPRAM_ALPHA_1                          0x0040082c /* RW-4R */
-#define NV_PGRAPH_DPRAM_ALPHA_1__ALIAS_1       NV_PGRAPH_DPRAM_DATA /*       */
-#define NV_PGRAPH_DPRAM_ALPHA_1_VALUE                          31:0 /* RWXVF */
-#define NV_PGRAPH_STORED_FMT                             0x00400830 /* RW-4R */
-#define NV_PGRAPH_STORED_FMT_MONO0                              5:0 /* RWXVF */
-#define NV_PGRAPH_STORED_FMT_PATT0                             13:8 /* RWXVF */
-#define NV_PGRAPH_STORED_FMT_PATT1                            21:16 /* RWXVF */
-#define NV_PGRAPH_STORED_FMT_CHROMA                           29:24 /* RWXVF */
-#define NV_PGRAPH_FORMATS                                0x00400618 /* RW-4R */
-#define NV_PGRAPH_FORMATS_ROP                                   2:0 /* R-XVF */
-#define NV_PGRAPH_FORMATS_ROP_Y8                         0x00000000 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_RGB15                      0x00000001 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_RGB16                      0x00000002 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_Y16                        0x00000003 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_INVALID                    0x00000004 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_RGB24                      0x00000005 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_RGB30                      0x00000006 /* -W--V */
-#define NV_PGRAPH_FORMATS_ROP_Y32                        0x00000007 /* -W--V */
-#define NV_PGRAPH_FORMATS_SRC                                   9:4 /* R-XVF */
-#define NV_PGRAPH_FORMATS_SRC_INVALID                    0x00000000 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_Y8                      0x00000001 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X16A8Y8                 0x00000002 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X24Y8                   0x00000003 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_A1R5G5B5                0x00000006 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X1R5G5B5                0x00000007 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X16A1R5G5B5             0x00000008 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X17R5G5B5               0x00000009 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_R5G6B5                  0x0000000A /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_A16R5G6B5               0x0000000B /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X16R5G6B5               0x0000000C /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_A8R8G8B8                0x0000000D /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X8R8G8B8                0x0000000E /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_Y16                     0x0000000F /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_A16Y16                  0x00000010 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_X16Y16                  0x00000011 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_V8YB8U8YA8              0x00000012 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_YB8V8YA8U8              0x00000013 /* RW--V */
-#define NV_PGRAPH_FORMATS_SRC_LE_Y32                     0x00000014 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB                                  15:12 /* R-XVF */
-#define NV_PGRAPH_FORMATS_FB_INVALID                     0x00000000 /* RWI-V */
-#define NV_PGRAPH_FORMATS_FB_Y8                          0x00000001 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X1R5G5B5_Z1R5G5B5           0x00000002 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X1R5G5B5_O1R5G5B5           0x00000003 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_A1R5G5B5                    0x00000004 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_R5G6B5                      0x00000005 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_Y16                         0x00000006 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_Z8R8G8B8           0x00000007 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_O1Z7R8G8B8         0x00000008 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X1A7R8G8B8_Z1A7R8G8B8       0x00000009 /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X1A7R8G8B8_O1A7R8G8B8       0x0000000a /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_O8R8G8B8           0x0000000b /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_A8R8G8B8                    0x0000000c /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_Y32                         0x0000000d /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_V8YB8U8YA8                  0x0000000e /* RW--V */
-#define NV_PGRAPH_FORMATS_FB_YB8V8YA8U8                  0x0000000f /* RW--V */ 
-#define NV_PGRAPH_ABS_X_RAM(i)                   (0x00400400+(i)*4) /* RW-4A */
-#define NV_PGRAPH_ABS_X_RAM__SIZE_1                              32 /*       */
-#define NV_PGRAPH_ABS_X_RAM_VALUE                              31:0 /* RWXUF */
-#define NV_PGRAPH_X_RAM_BPORT(i)                 (0x00400c00+(i)*4) /* R--4A */
-#define NV_PGRAPH_X_RAM_BPORT__SIZE_1                            32 /*       */
-#define NV_PGRAPH_X_RAM_BPORT_VALUE                            31:0 /* R--UF */
-#define NV_PGRAPH_ABS_Y_RAM(i)                   (0x00400480+(i)*4) /* RW-4A */
-#define NV_PGRAPH_ABS_Y_RAM__SIZE_1                              32 /*       */
-#define NV_PGRAPH_ABS_Y_RAM_VALUE                              31:0 /* RWXUF */
-#define NV_PGRAPH_Y_RAM_BPORT(i)                 (0x00400c80+(i)*4) /* R--4A */
-#define NV_PGRAPH_Y_RAM_BPORT__SIZE_1                            32 /*       */
-#define NV_PGRAPH_Y_RAM_BPORT_VALUE                            31:0 /* R--UF */
-#define NV_PGRAPH_XY_LOGIC_MISC0                         0x00400514 /* RW-4R */
-#define NV_PGRAPH_XY_LOGIC_MISC0_COUNTER                       17:0 /* RWBUF */
-#define NV_PGRAPH_XY_LOGIC_MISC0_COUNTER_0               0x00000000 /* RWB-V */
-#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION                    20:20 /* RWVVF */
-#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION_NONZERO       0x00000000 /* RWV-V */
-#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION_ZERO          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC0_INDEX                        31:28 /* RWBUF */
-#define NV_PGRAPH_XY_LOGIC_MISC0_INDEX_0                 0x00000000 /* RWB-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1                         0x00400518 /* RW-4R */
-#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL                        0:0 /* RWNVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL_NEEDED          0x00000000 /* RWN-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL_DONE            0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX                      4:4 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX_NOTNULL       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX_NULL          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY                      5:5 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY_NOTNULL       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY_NULL          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX                    12:12 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX_UUMAX         0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX                    16:16 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX_UUMAX         0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA                    20:20 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA_CLIPMAX       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2                         0x0040051C /* RW-4R */
-#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF                        0:0 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF_DISABLE         0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF_ENABLE          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX                      4:4 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX_NOTNULL       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX_NULL          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY                      5:5 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY_NOTNULL       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY_NULL          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX                    12:12 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX_UCMAX         0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX                    16:16 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX_UCMAX         0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA                    20:20 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA_CLIPMAX       0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA_IMAGEMAX      0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3                         0x00400520 /* RW-4R */
-#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0                     0:0 /* RWXVF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0_NULL         0x00000000 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0_TRUE         0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY                   4:4 /* RWXVF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY_NULL       0x00000000 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY_TRUE       0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX                      8:8 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX_NULL          0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX_TRUE          0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG                     12:12 /* RWIVF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG_NULL           0x00000000 /* RWI-V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG_TRUE           0x00000001 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_DIMX                    22:16 /* RWXUF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_DIMX_0             0x00000000 /* RW--V */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_WDIMX                   30:24 /* RWXUF */
-#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_WDIMX_0            0x00000000 /* RW--V */
-#define NV_PGRAPH_X_MISC                                 0x00400500 /* RW-4R */
-#define NV_PGRAPH_X_MISC_BIT33_0                                0:0 /* RWNVF */
-#define NV_PGRAPH_X_MISC_BIT33_0_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_BIT33_1                                1:1 /* RWNVF */
-#define NV_PGRAPH_X_MISC_BIT33_1_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_BIT33_2                                2:2 /* RWNVF */
-#define NV_PGRAPH_X_MISC_BIT33_2_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_BIT33_3                                3:3 /* RWNVF */
-#define NV_PGRAPH_X_MISC_BIT33_3_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_RANGE_0                                4:4 /* RWNVF */
-#define NV_PGRAPH_X_MISC_RANGE_0_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_RANGE_1                                5:5 /* RWNVF */
-#define NV_PGRAPH_X_MISC_RANGE_1_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_RANGE_2                                6:6 /* RWNVF */
-#define NV_PGRAPH_X_MISC_RANGE_2_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_RANGE_3                                7:7 /* RWNVF */
-#define NV_PGRAPH_X_MISC_RANGE_3_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_X_MISC_ADDER_OUTPUT                         29:28 /* RWXVF */
-#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_EQ_0               0x00000000 /* RW--V */
-#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_LT_0               0x00000001 /* RW--V */
-#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_GT_0               0x00000002 /* RW--V */
-#define NV_PGRAPH_Y_MISC                                 0x00400504 /* RW-4R */
-#define NV_PGRAPH_Y_MISC_BIT33_0                                0:0 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_BIT33_0_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_BIT33_1                                1:1 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_BIT33_1_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_BIT33_2                                2:2 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_BIT33_2_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_BIT33_3                                3:3 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_BIT33_3_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_RANGE_0                                4:4 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_RANGE_0_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_RANGE_1                                5:5 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_RANGE_1_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_RANGE_2                                6:6 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_RANGE_2_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_RANGE_3                                7:7 /* RWNVF */
-#define NV_PGRAPH_Y_MISC_RANGE_3_0                       0x00000000 /* RWN-V */
-#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT                         29:28 /* RWXVF */
-#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_EQ_0               0x00000000 /* RW--V */
-#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_LT_0               0x00000001 /* RW--V */
-#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_GT_0               0x00000002 /* RW--V */
-#define NV_PGRAPH_ABS_UCLIP_XMIN                         0x0040053C /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIP_XMIN_VALUE                         15:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIP_XMAX                         0x00400544 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIP_XMAX_VALUE                         17:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIP_YMIN                         0x00400540 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIP_YMIN_VALUE                         15:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIP_YMAX                         0x00400548 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIP_YMAX_VALUE                         17:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIPA_XMIN                        0x00400560 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIPA_XMIN_VALUE                        15:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIPA_XMAX                        0x00400568 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIPA_XMAX_VALUE                        17:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIPA_YMIN                        0x00400564 /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIPA_YMIN_VALUE                        15:0 /* RWXSF */
-#define NV_PGRAPH_ABS_UCLIPA_YMAX                        0x0040056C /* RW-4R */
-#define NV_PGRAPH_ABS_UCLIPA_YMAX_VALUE                        17:0 /* RWXSF */
-#define NV_PGRAPH_SOURCE_COLOR                           0x0040050C /* RW-4R */
-#define NV_PGRAPH_SOURCE_COLOR_VALUE                           31:0 /* RWNVF */
-#define NV_PGRAPH_SOURCE_COLOR_VALUE_0                   0x00000000 /* RWN-V */
-#define NV_PGRAPH_VALID1                                 0x00400508 /* RW-4R */
-#define NV_PGRAPH_VALID1_VLD                                   22:0 /* RWNVF */
-#define NV_PGRAPH_VALID1_VLD_0                           0x00000000 /* RWN-V */
-#define NV_PGRAPH_VALID1_CLIP_MIN                             28:28 /* RWIVF */
-#define NV_PGRAPH_VALID1_CLIP_MIN_NO_ERROR               0x00000000 /* RWI-V */
-#define NV_PGRAPH_VALID1_CLIP_MIN_ONLY                   0x00000001 /* RW--V */
-#define NV_PGRAPH_VALID1_CLIPA_MIN                            29:29 /* RWIVF */
-#define NV_PGRAPH_VALID1_CLIPA_MIN_NO_ERROR              0x00000000 /* RWI-V */
-#define NV_PGRAPH_VALID1_CLIPA_MIN_ONLY                  0x00000001 /* RW--V */
-#define NV_PGRAPH_VALID1_CLIP_MAX                             30:30 /* RWIVF */
-#define NV_PGRAPH_VALID1_CLIP_MAX_NO_ERROR               0x00000000 /* RWI-V */
-#define NV_PGRAPH_VALID1_CLIP_MAX_ONLY                   0x00000001 /* RW--V */
-#define NV_PGRAPH_VALID1_CLIPA_MAX                            31:31 /* RWIVF */
-#define NV_PGRAPH_VALID1_CLIPA_MAX_NO_ERROR              0x00000000 /* RWI-V */
-#define NV_PGRAPH_VALID1_CLIPA_MAX_ONLY                  0x00000001 /* RW--V */
-#define NV_PGRAPH_VALID2                                 0x00400578 /* RW-4R */
-#define NV_PGRAPH_VALID2_VLD2                                  28:0 /* RWNVF */
-#define NV_PGRAPH_VALID2_VLD2_0                          0x00000000 /* RWN-V */
-#define NV_PGRAPH_ABS_ICLIP_XMAX                         0x00400534 /* RW-4R */
-#define NV_PGRAPH_ABS_ICLIP_XMAX_VALUE                         17:0 /* RWXSF */
-#define NV_PGRAPH_ABS_ICLIP_YMAX                         0x00400538 /* RW-4R */
-#define NV_PGRAPH_ABS_ICLIP_YMAX_VALUE                         17:0 /* RWXSF */
-#define NV_PGRAPH_CLIPX_0                                0x00400524 /* RW-4R */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MIN                             1:0 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MAX                             3:2 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MIN                             5:4 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MAX                             7:6 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MIN                             9:8 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MAX                           11:10 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MIN                           13:12 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MAX                           15:14 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MIN                           17:16 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MAX                           19:18 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MIN                           21:20 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MAX                           23:22 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MIN                           25:24 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MAX                           27:26 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MIN                           29:28 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MAX                           31:30 /* RWNVF */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1                                0x00400528 /* RW-4R */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MIN                             1:0 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MAX                             3:2 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MIN                             5:4 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MAX                             7:6 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MIN                            9:8 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MAX                          11:10 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MIN                          13:12 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP11MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MAX                          15:14 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MIN                          17:16 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MAX                          19:18 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MIN                          21:20 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MAX                          23:22 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MIN                          25:24 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MAX                          27:26 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MIN                          29:28 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MAX                          31:30 /* RWNVF */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0                                0x0040052c /* RW-4R */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MIN                             1:0 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MAX                             3:2 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MIN                             5:4 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MAX                             7:6 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MIN                             9:8 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MAX                           11:10 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MIN                           13:12 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MAX                           15:14 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MIN                           17:16 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MAX                           19:18 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MIN                           21:20 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MAX                           23:22 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MIN                           25:24 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MAX                           27:26 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MIN                           29:28 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MAX                           31:30 /* RWNVF */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1                                0x00400530 /* RW-4R */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MIN                             1:0 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MAX                             3:2 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MIN                             5:4 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_GT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_LT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MAX                             7:6 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_LT                   0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_GT                   0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MIN                            9:8 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MAX                          11:10 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MIN                          13:12 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP11MIN_EQ                   0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MAX                          15:14 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MIN                          17:16 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MAX                          19:18 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MIN                          21:20 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MAX                          23:22 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MIN                          25:24 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MAX                          27:26 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MIN                          29:28 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_GT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_LT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MAX                          31:30 /* RWNVF */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_LT                  0x00000000 /* RW--V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_GT                  0x00000001 /* RWN-V */
-#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_EQ                  0x00000002 /* RW--V */
-#define NV_PGRAPH_MISC24_0                               0x00400510 /* RW-4R */
-#define NV_PGRAPH_MISC24_0_VALUE                               23:0 /* RWXUF */
-#define NV_PGRAPH_MISC24_1                               0x00400570 /* RW-4R */
-#define NV_PGRAPH_MISC24_1_VALUE                               23:0 /* RWXUF */
-#define NV_PGRAPH_MISC24_2                               0x00400574 /* RW-4R */
-#define NV_PGRAPH_MISC24_2_VALUE                               23:0 /* RWXUF */
-#define NV_PGRAPH_PASSTHRU_0                             0x0040057C /* RW-4R */
-#define NV_PGRAPH_PASSTHRU_0_VALUE                             31:0 /* RWXUF */
-#define NV_PGRAPH_PASSTHRU_1                             0x00400580 /* RW-4R */
-#define NV_PGRAPH_PASSTHRU_1_VALUE                             31:0 /* RWXUF */
-#define NV_PGRAPH_PASSTHRU_2                             0x00400584 /* RW-4R */
-#define NV_PGRAPH_PASSTHRU_2_VALUE                             31:0 /* RWXUF */
-#define NV_PGRAPH_U_RAM(i)                       (0x00400d00+(i)*4) /* RW-4A */
-#define NV_PGRAPH_U_RAM__SIZE_1                                  16 /*       */
-#define NV_PGRAPH_U_RAM_VALUE                                  31:6 /* RWXFF */
-#define NV_PGRAPH_V_RAM(i)                       (0x00400d40+(i)*4) /* RW-4A */
-#define NV_PGRAPH_V_RAM__SIZE_1                                  16 /*       */
-#define NV_PGRAPH_V_RAM_VALUE                                  31:6 /* RWXFF */
-#define NV_PGRAPH_M_RAM(i)                       (0x00400d80+(i)*4) /* RW-4A */
-#define NV_PGRAPH_M_RAM__SIZE_1                                  16 /*       */
-#define NV_PGRAPH_M_RAM_VALUE                                  31:6 /* RWXFF */
-#define NV_PGRAPH_DMA_START_0                            0x00401000 /* RW-4R */
-#define NV_PGRAPH_DMA_START_0_VALUE                            31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_START_1                            0x00401004 /* RW-4R */
-#define NV_PGRAPH_DMA_START_1_VALUE                            31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_LENGTH                             0x00401008 /* RW-4R */
-#define NV_PGRAPH_DMA_LENGTH_VALUE                             21:0 /* RWXUF */
-#define NV_PGRAPH_DMA_MISC                               0x0040100C /* RW-4R */
-#define NV_PGRAPH_DMA_MISC_COUNT                               15:0 /* RWXUF */
-#define NV_PGRAPH_DMA_MISC_FMT_SRC                            18:16 /* RWXVF */
-#define NV_PGRAPH_DMA_MISC_FMT_DST                            22:20 /* RWXVF */
-#define NV_PGRAPH_DMA_DATA_0                             0x00401020 /* RW-4R */
-#define NV_PGRAPH_DMA_DATA_0_VALUE                             31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_DATA_1                             0x00401024 /* RW-4R */
-#define NV_PGRAPH_DMA_DATA_1_VALUE                             31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_RM                                 0x00401030 /* RW-4R */
-#define NV_PGRAPH_DMA_RM_ASSIST_A                               0:0 /* RWIVF */
-#define NV_PGRAPH_DMA_RM_ASSIST_A_NOT_PENDING            0x00000000 /* R-I-V */
-#define NV_PGRAPH_DMA_RM_ASSIST_A_PENDING                0x00000001 /* R---V */
-#define NV_PGRAPH_DMA_RM_ASSIST_A_RESET                  0x00000001 /* -W--C */
-#define NV_PGRAPH_DMA_RM_ASSIST_B                               1:1 /* RWIVF */
-#define NV_PGRAPH_DMA_RM_ASSIST_B_NOT_PENDING            0x00000000 /* R-I-V */
-#define NV_PGRAPH_DMA_RM_ASSIST_B_PENDING                0x00000001 /* R---V */
-#define NV_PGRAPH_DMA_RM_ASSIST_B_RESET                  0x00000001 /* -W--C */
-#define NV_PGRAPH_DMA_RM_WRITE_REQ                              4:4 /* CWIVF */
-#define NV_PGRAPH_DMA_RM_WRITE_REQ_NOT_PENDING           0x00000000 /* CWI-V */
-#define NV_PGRAPH_DMA_RM_WRITE_REQ_PENDING               0x00000001 /* -W--T */
-#define NV_PGRAPH_DMA_A_XLATE_INST                       0x00401040 /* RW-4R */
-#define NV_PGRAPH_DMA_A_XLATE_INST_VALUE                       15:0 /* RWXUF */
-#define NV_PGRAPH_DMA_A_CONTROL                          0x00401044 /* RW-4R */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE                    12:12 /* RWIVF */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE_NOT_PRESENT   0x00000000 /* RWI-V */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE_PRESENT       0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY                    13:13 /* RWXVF */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY_NOT_LINEAR    0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY_LINEAR        0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE                   17:16 /* RWXUF */
-#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_NVM          0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_PCI          0x00000002 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_AGP          0x00000003 /* RW--V */
-#define NV_PGRAPH_DMA_A_CONTROL_ADJUST                        31:20 /* RWXUF */
-#define NV_PGRAPH_DMA_A_LIMIT                            0x00401048 /* RW-4R */
-#define NV_PGRAPH_DMA_A_LIMIT_OFFSET                           31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_A_TLB_PTE                          0x0040104C /* RW-4R */
-#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS                          1:1 /* RWXVF */
-#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS_READ_ONLY         0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS_READ_WRITE        0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_A_TLB_PTE_FRAME_ADDRESS                 31:12 /* RWXUF */
-#define NV_PGRAPH_DMA_A_TLB_TAG                          0x00401050 /* RW-4R */
-#define NV_PGRAPH_DMA_A_TLB_TAG_ADDRESS                       31:12 /* RWXUF */
-#define NV_PGRAPH_DMA_A_ADJ_OFFSET                       0x00401054 /* RW-4R */
-#define NV_PGRAPH_DMA_A_ADJ_OFFSET_VALUE                       31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_A_OFFSET                           0x00401058 /* RW-4R */
-#define NV_PGRAPH_DMA_A_OFFSET_VALUE                           31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_A_SIZE                             0x0040105C /* RW-4R */
-#define NV_PGRAPH_DMA_A_SIZE_VALUE                             24:0 /* RWXUF */
-#define NV_PGRAPH_DMA_A_Y_SIZE                           0x00401060 /* RW-4R */
-#define NV_PGRAPH_DMA_A_Y_SIZE_VALUE                           10:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_XLATE_INST                       0x00401080 /* RW-4R */
-#define NV_PGRAPH_DMA_B_XLATE_INST_VALUE                       15:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_CONTROL                          0x00401084 /* RW-4R */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE                    12:12 /* RWIVF */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE_NOT_PRESENT   0x00000000 /* RWI-V */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE_PRESENT       0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY                    13:13 /* RWXVF */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY_NOT_LINEAR    0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY_LINEAR        0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE                   17:16 /* RWXUF */
-#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_NVM          0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_PCI          0x00000002 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_AGP          0x00000003 /* RW--V */
-#define NV_PGRAPH_DMA_B_CONTROL_ADJUST                        31:20 /* RWXUF */
-#define NV_PGRAPH_DMA_B_LIMIT                            0x00401088 /* RW-4R */
-#define NV_PGRAPH_DMA_B_LIMIT_OFFSET                           31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_TLB_PTE                          0x0040108C /* RW-4R */
-#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS                          1:1 /* RWXVF */
-#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS_READ_ONLY         0x00000000 /* RW--V */
-#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS_READ_WRITE        0x00000001 /* RW--V */
-#define NV_PGRAPH_DMA_B_TLB_PTE_FRAME_ADDRESS                 31:12 /* RWXUF */
-#define NV_PGRAPH_DMA_B_TLB_TAG                          0x00401090 /* RW-4R */
-#define NV_PGRAPH_DMA_B_TLB_TAG_ADDRESS                       31:12 /* RWXUF */
-#define NV_PGRAPH_DMA_B_ADJ_OFFSET                       0x00401094 /* RW-4R */
-#define NV_PGRAPH_DMA_B_ADJ_OFFSET_VALUE                       31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_OFFSET                           0x00401098 /* RW-4R */
-#define NV_PGRAPH_DMA_B_OFFSET_VALUE                           31:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_SIZE                             0x0040109C /* RW-4R */
-#define NV_PGRAPH_DMA_B_SIZE_VALUE                             24:0 /* RWXUF */
-#define NV_PGRAPH_DMA_B_Y_SIZE                           0x004010A0 /* RW-4R */
-#define NV_PGRAPH_DMA_B_Y_SIZE_VALUE                           10:0 /* RWXUF */
-
-/* Framebuffer registers */
-#define NV_PFB                                0x00100FFF:0x00100000 /* RW--D */
-#define NV_PFB_BOOT_0                                    0x00100000 /* RW-4R */
-#define NV_PFB_BOOT_0_RAM_AMOUNT                                1:0 /* RW-VF */
-#define NV_PFB_BOOT_0_RAM_AMOUNT_32MB                    0x00000000 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_AMOUNT_4MB                     0x00000001 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_AMOUNT_8MB                     0x00000002 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_AMOUNT_16MB                    0x00000003 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_WIDTH_128                             2:2 /* RW-VF */
-#define NV_PFB_BOOT_0_RAM_WIDTH_128_OFF                  0x00000000 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_WIDTH_128_ON                   0x00000001 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_TYPE                                  4:3 /* RW-VF */
-#define NV_PFB_BOOT_0_RAM_TYPE_256K                      0x00000000 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_TYPE_512K_2BANK                0x00000001 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_TYPE_512K_4BANK                0x00000002 /* RW--V */
-#define NV_PFB_BOOT_0_RAM_TYPE_1024K_2BANK               0x00000003 /* RW--V */
-#define NV_PFB_CONFIG_0                                  0x00100200 /* RW-4R */
-#define NV_PFB_CONFIG_0_TYPE                                   14:0 /* RWIVF */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_8BPP          0x00000120 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_16BPP         0x00000220 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_32BPP         0x00000320 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_8BPP            0x00004120 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_16BPP           0x00004220 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_32BPP           0x00004320 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_TETRIS                      0x00002000 /* RW--V */
-#define NV_PFB_CONFIG_0_TYPE_NOTILING                    0x00001114 /* RWI-V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE                           17:15 /* RWI-F */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_PASS                 0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_1                    0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_2                    0x00000002 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_3                    0x00000003 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_4                    0x00000004 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_5                    0x00000005 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_6                    0x00000006 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_MODE_7                    0x00000007 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_SHIFT                          19:18 /* RWI-F */
-#define NV_PFB_CONFIG_0_TETRIS_SHIFT_0                   0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_0_TETRIS_SHIFT_1                   0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_TETRIS_SHIFT_2                   0x00000002 /* RW--V */
-#define NV_PFB_CONFIG_0_BANK_SWAP                             22:20 /* RWI-F */
-#define NV_PFB_CONFIG_0_BANK_SWAP_OFF                    0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_0_BANK_SWAP_1M                     0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_BANK_SWAP_2M                     0x00000005 /* RW--V */
-#define NV_PFB_CONFIG_0_BANK_SWAP_4M                     0x00000007 /* RW--V */
-#define NV_PFB_CONFIG_0_UNUSED                                23:23 /* RW-VF */
-#define NV_PFB_CONFIG_0_SCRAMBLE_EN                           29:29 /* RWIVF */
-#define NV_PFB_CONFIG_0_SCRAMBLE_EN_INIT                 0x00000000 /* RW--V */
-#define NV_PFB_CONFIG_0_SCRAMBLE_ACTIVE                  0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_PRAMIN_WR                             28:28 /* RWIVF */
-#define NV_PFB_CONFIG_0_PRAMIN_WR_INIT                   0x00000000 /* RW--V */
-#define NV_PFB_CONFIG_0_PRAMIN_WR_DISABLED               0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK                        27:24 /* RWIVF */
-#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK_INIT              0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK_CLEAR             0x0000000f /* RWI-V */
-#define NV_PFB_CONFIG_1                                  0x00100204 /* RW-4R */
-#define NV_PFB_RTL                                       0x00100300 /* RW-4R */
-#define NV_PFB_RTL_H                                            0:0 /* RWIUF */
-#define NV_PFB_RTL_H_DEFAULT                             0x00000000 /* RWI-V */
-#define NV_PFB_RTL_MC                                           1:1 /* RWIUF */
-#define NV_PFB_RTL_MC_DEFAULT                            0x00000000 /* RWI-V */
-#define NV_PFB_RTL_V                                            2:2 /* RWIUF */
-#define NV_PFB_RTL_V_DEFAULT                             0x00000000 /* RWI-V */
-#define NV_PFB_RTL_G                                            3:3 /* RWIUF */
-#define NV_PFB_RTL_G_DEFAULT                             0x00000000 /* RWI-V */
-#define NV_PFB_RTL_GB                                           4:4 /* RWIUF */
-#define NV_PFB_RTL_GB_DEFAULT                            0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_0_RESOLUTION                              5:0 /* RWIVF */
-#define NV_PFB_CONFIG_0_RESOLUTION_320_PIXELS            0x0000000a /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_400_PIXELS            0x0000000d /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_480_PIXELS            0x0000000f /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_512_PIXELS            0x00000010 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_640_PIXELS            0x00000014 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_800_PIXELS            0x00000019 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_960_PIXELS            0x0000001e /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_1024_PIXELS           0x00000020 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_1152_PIXELS           0x00000024 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_1280_PIXELS           0x00000028 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_1600_PIXELS           0x00000032 /* RW--V */
-#define NV_PFB_CONFIG_0_RESOLUTION_DEFAULT               0x00000014 /* RWI-V */
-#define NV_PFB_CONFIG_0_PIXEL_DEPTH                             9:8 /* RWIVF */
-#define NV_PFB_CONFIG_0_PIXEL_DEPTH_8_BITS               0x00000001 /* RW--V */
-#define NV_PFB_CONFIG_0_PIXEL_DEPTH_16_BITS              0x00000002 /* RW--V */
-#define NV_PFB_CONFIG_0_PIXEL_DEPTH_32_BITS              0x00000003 /* RW--V */
-#define NV_PFB_CONFIG_0_PIXEL_DEPTH_DEFAULT              0x00000001 /* RWI-V */
-#define NV_PFB_CONFIG_0_TILING                                12:12 /* RWIVF */
-#define NV_PFB_CONFIG_0_TILING_ENABLED                   0x00000000 /* RW--V */
-#define NV_PFB_CONFIG_0_TILING_DISABLED                  0x00000001 /* RWI-V */
-#define NV_PFB_CONFIG_1_SGRAM100                                3:3 /* RWIVF */
-#define NV_PFB_CONFIG_1_SGRAM100_ENABLED                 0x00000000 /* RWI-V */
-#define NV_PFB_CONFIG_1_SGRAM100_DISABLED                0x00000001 /* RW--V */
-#define NV_PFB_DEBUG_0_CKE_ALWAYSON                           29:29 /* RWIVF */
-#define NV_PFB_DEBUG_0_CKE_ALWAYSON_OFF                  0x00000000 /* RW--V */
-#define NV_PFB_DEBUG_0_CKE_ALWAYSON_ON                   0x00000001 /* RWI-V */
-
-#define NV_PEXTDEV                            0x00101FFF:0x00101000 /* RW--D */
-#define NV_PEXTDEV_BOOT_0                                0x00101000 /* R--4R */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED                       0:0 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED_33MHZ          0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED_66MHZ          0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR                      1:1 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR_NO_BIOS       0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR_BIOS          0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE                        3:2 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_256K      0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_512K_2BANK 0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_512K_4BANK 0x00000002 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_1024K_2BANK     0x00000003 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH                       4:4 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH_64             0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH_128            0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE                        5:5 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE_PCI             0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE_AGP             0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL                         6:6 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL_13500K           0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL_14318180         0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE                          8:7 /* R-XVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_SECAM             0x00000000 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_NTSC              0x00000001 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_PAL               0x00000002 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_DISABLED          0x00000003 /* R---V */
-#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE                     11:11 /* RWIVF */
-#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE_DISABLED       0x00000000 /* RWI-V */
-#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE_ENABLED        0x00000001 /* RW--V */
-
-/* Extras */
-#define NV_PRAMIN                             0x007FFFFF:0x00700000 /* RW--M */
-/*#define NV_PRAMIN                             0x00FFFFFF:0x00C00000*/
-#define NV_PNVM                               0x01FFFFFF:0x01000000 /* RW--M */
-/*#define NV_PNVM                               0x00BFFFFF:0x00800000*/
-#define NV_CHAN0                              0x0080ffff:0x00800000
-
-/* FIFO subchannels */
-#define NV_UROP                               0x43
-#define NV_UCHROMA                            0x57
-#define NV_UCLIP                              0x19
-#define NV_UPATT                              0x18
-#define NV_ULIN                               0x5C
-#define NV_UTRI                               0x5D
-#define NV_URECT                              0x5E
-#define NV_UBLIT                              0x5F
-#define NV_UGLYPH                             0x4B
-
-#endif /*__NV4REF_H__*/
-
index be630a0ccfd431f1d46bc7c27bf1707d6e8fc1bc..a11026812d1b6d169c66ba7badd923f01bd9a051 100644 (file)
@@ -231,12 +231,14 @@ unsigned long riva_get_memlen(struct riva_par *par)
        case NV_ARCH_30:
                if(chipset == NV_CHIP_IGEFORCE2) {
 
-                       dev = pci_find_slot(0, 1);
+                       dev = pci_get_bus_and_slot(0, 1);
                        pci_read_config_dword(dev, 0x7C, &amt);
+                       pci_dev_put(dev);
                        memlen = (((amt >> 6) & 31) + 1) * 1024;
                } else if (chipset == NV_CHIP_0x01F0) {
-                       dev = pci_find_slot(0, 1);
+                       dev = pci_get_bus_and_slot(0, 1);
                        pci_read_config_dword(dev, 0x84, &amt);
+                       pci_dev_put(dev);
                        memlen = (((amt >> 4) & 127) + 1) * 1024;
                } else {
                        switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) &
index e0b8c521cc9ca008a4c5e27459348a5a6497315f..70bfd78eca819a873ee35932e650bafb58d4b423 100644 (file)
@@ -1118,8 +1118,9 @@ static void nForceUpdateArbitrationSettings
     unsigned int uMClkPostDiv;
     struct pci_dev *dev;
 
-    dev = pci_find_slot(0, 3);
+    dev = pci_get_bus_and_slot(0, 3);
     pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+    pci_dev_put(dev);
     uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
 
     if(!uMClkPostDiv) uMClkPostDiv = 4;
@@ -1132,8 +1133,9 @@ static void nForceUpdateArbitrationSettings
     sim_data.enable_video   = 0;
     sim_data.enable_mp      = 0;
 
-    dev = pci_find_slot(0, 1);
+    dev = pci_get_bus_and_slot(0, 1);
     pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+    pci_dev_put(dev);
     sim_data.memory_type    = (sim_data.memory_type >> 12) & 1;
 
     sim_data.memory_width   = 64;
@@ -2112,12 +2114,14 @@ static void nv10GetConfig
      * Fill in chip configuration.
      */
     if(chipset == NV_CHIP_IGEFORCE2) {
-        dev = pci_find_slot(0, 1);
+        dev = pci_get_bus_and_slot(0, 1);
         pci_read_config_dword(dev, 0x7C, &amt);
+        pci_dev_put(dev);
         chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
     } else if(chipset == NV_CHIP_0x01F0) {
-        dev = pci_find_slot(0, 1);
+        dev = pci_get_bus_and_slot(0, 1);
         pci_read_config_dword(dev, 0x84, &amt);
+        pci_dev_put(dev);
         chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
     } else {
         switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 0x000000FF)
index 0405e839ff939f5dc9e13d33f02dd4f1cd51ca06..76e6ce353c8ea9c559d3668521ae184cd864eca6 100644 (file)
@@ -88,13 +88,16 @@ static int riva_gpio_getsda(void* data)
        return val;
 }
 
-static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
+static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan,
+                                       const char *name,
+                                       unsigned int i2c_class)
 {
        int rc;
 
        strcpy(chan->adapter.name, name);
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.id                = I2C_HW_B_RIVA;
+       chan->adapter.class             = i2c_class;
        chan->adapter.algo_data         = &chan->algo;
        chan->adapter.dev.parent        = &chan->par->pdev->dev;
        chan->algo.setsda               = riva_gpio_setsda;
@@ -124,42 +127,38 @@ static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
        return rc;
 }
 
-void riva_create_i2c_busses(struct riva_par *par)
+void __devinit riva_create_i2c_busses(struct riva_par *par)
 {
-       par->bus = 3;
-
        par->chan[0].par        = par;
        par->chan[1].par        = par;
        par->chan[2].par        = par;
 
-       par->chan[0].ddc_base = 0x3e;
-       par->chan[1].ddc_base = 0x36;
+       par->chan[0].ddc_base = 0x36;
+       par->chan[1].ddc_base = 0x3e;
        par->chan[2].ddc_base = 0x50;
-       riva_setup_i2c_bus(&par->chan[0], "BUS1");
-       riva_setup_i2c_bus(&par->chan[1], "BUS2");
-       riva_setup_i2c_bus(&par->chan[2], "BUS3");
+       riva_setup_i2c_bus(&par->chan[0], "BUS1", I2C_CLASS_HWMON);
+       riva_setup_i2c_bus(&par->chan[1], "BUS2", 0);
+       riva_setup_i2c_bus(&par->chan[2], "BUS3", 0);
 }
 
 void riva_delete_i2c_busses(struct riva_par *par)
 {
-       if (par->chan[0].par)
-               i2c_del_adapter(&par->chan[0].adapter);
-       par->chan[0].par = NULL;
-
-       if (par->chan[1].par)
-               i2c_del_adapter(&par->chan[1].adapter);
-       par->chan[1].par = NULL;
+       int i;
 
-       if (par->chan[2].par)
-               i2c_del_adapter(&par->chan[2].adapter);
-       par->chan[2].par = NULL;
+       for (i = 0; i < 3; i++) {
+               if (!par->chan[i].par)
+                       continue;
+               i2c_del_adapter(&par->chan[i].adapter);
+               par->chan[i].par = NULL;
+       }
 }
 
-int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
+int __devinit riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
 {
        u8 *edid = NULL;
 
-       edid = fb_ddc_read(&par->chan[conn-1].adapter);
+       if (par->chan[conn].par)
+               edid = fb_ddc_read(&par->chan[conn].adapter);
 
        if (out_edid)
                *out_edid = edid;
index 48ead6d72f24e9906e2dd33937357cce9687aa89..d9f107b704c6296feb52ee2ea83aa2aa11a1b9a4 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/fb.h>
 #include <video/vga.h>
 #include <linux/i2c.h>
-#include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
 
 #include "riva_hw.h"
@@ -61,7 +60,6 @@ struct riva_par {
        Bool SecondCRTC;
        int FlatPanel;
        struct pci_dev *pdev;
-       int bus;
        int cursor_reset;
 #ifdef CONFIG_MTRR
        struct { int vram; int vram_valid; } mtrr;
index 3091b20124b45eb94d609da9a9702a92e9e1c9c1..d11735895a01b7830b3ad89773f7300e364f02d2 100644 (file)
@@ -65,7 +65,7 @@ static const struct svga_fb_format s3fb_formats[] = {
 
 
 static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
-       60000, 240000, 14318};
+       35000, 240000, 14318};
 
 static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
 
@@ -164,7 +164,7 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau
 static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
 {
        const u8 *font = map->data;
-       u8* fb = (u8 *) info->screen_base;
+       u8 __iomem *fb = (u8 __iomem *) info->screen_base;
        int i, c;
 
        if ((map->width != 8) || (map->height != 16) ||
@@ -177,20 +177,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
        fb += 2;
        for (i = 0; i < map->height; i++) {
                for (c = 0; c < map->length; c++) {
-                       fb[c * 4] = font[c * map->height + i];
+                       fb_writeb(font[c * map->height + i], fb + c * 4);
                }
                fb += 1024;
        }
 }
 
-
-
 static struct fb_tile_ops s3fb_tile_ops = {
        .fb_settile     = svga_settile,
        .fb_tilecopy    = svga_tilecopy,
        .fb_tilefill    = svga_tilefill,
        .fb_tileblit    = svga_tileblit,
        .fb_tilecursor  = svga_tilecursor,
+       .fb_get_tilemax = svga_get_tilemax,
 };
 
 static struct fb_tile_ops s3fb_fast_tile_ops = {
@@ -199,6 +198,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = {
        .fb_tilefill    = svga_tilefill,
        .fb_tileblit    = svga_tileblit,
        .fb_tilecursor  = svga_tilecursor,
+       .fb_get_tilemax = svga_get_tilemax,
 };
 
 
@@ -326,8 +326,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
 {
        u16 m, n, r;
        u8 regval;
+       int rv;
 
-       svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+       rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+       if (rv < 0) {
+               printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
+               return;
+       }
 
        /* Set VGA misc register  */
        regval = vga_r(NULL, VGA_MIS_R);
@@ -449,6 +454,10 @@ static int s3fb_set_par(struct fb_info *info)
                info->flags &= ~FBINFO_MISC_TILEBLITTING;
                info->tileops = NULL;
 
+               /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+               info->pixmap.blit_y = ~(u32)0;
+
                offset_value = (info->var.xres_virtual * bpp) / 64;
                screen_size = info->var.yres_virtual * info->fix.line_length;
        } else {
@@ -458,6 +467,10 @@ static int s3fb_set_par(struct fb_info *info)
                info->flags |= FBINFO_MISC_TILEBLITTING;
                info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
 
+               /* supports 8x16 tiles only */
+               info->pixmap.blit_x = 1 << (8 - 1);
+               info->pixmap.blit_y = 1 << (16 - 1);
+
                offset_value = info->var.xres_virtual / 16;
                screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
        }
@@ -656,7 +669,7 @@ static int s3fb_set_par(struct fb_info *info)
        value = ((value * hmul) / 8) - 5;
        vga_wcrt(NULL, 0x3C, (value + 1) / 2);
 
-       memset((u8*)info->screen_base, 0x00, screen_size);
+       memset_io(info->screen_base, 0x00, screen_size);
        /* Device and screen back on */
        svga_wcrt_mask(0x17, 0x80, 0x80);
        svga_wseq_mask(0x01, 0x00, 0x20);
@@ -699,7 +712,7 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                break;
        case 16:
                if (regno >= 16)
-                       return -EINVAL;
+                       return 0;
 
                if (fb->var.green.length == 5)
                        ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
@@ -712,9 +725,9 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
        case 24:
        case 32:
                if (regno >= 16)
-                       return -EINVAL;
+                       return 0;
 
-               ((u32*)fb->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) |
+               ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
                        (green & 0xFF00) | ((blue & 0xFF00) >> 8);
                break;
        default:
@@ -767,12 +780,6 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 
        unsigned int offset;
 
-       /* Validate the offsets */
-       if ((var->xoffset + var->xres) > var->xres_virtual)
-               return -EINVAL;
-       if ((var->yoffset + var->yres) > var->yres_virtual)
-               return -EINVAL;
-
        /* Calculate the offset */
        if (var->bits_per_pixel == 0) {
                offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
@@ -805,6 +812,7 @@ static struct fb_ops s3fb_ops = {
        .fb_fillrect    = s3fb_fillrect,
        .fb_copyarea    = cfb_copyarea,
        .fb_imageblit   = s3fb_imageblit,
+       .fb_get_caps    = svga_get_caps,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1061,6 +1069,7 @@ static int s3_pci_resume(struct pci_dev* dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct s3fb_info *par = info->par;
+       int err;
 
        dev_info(&(dev->dev), "resume\n");
 
@@ -1075,7 +1084,13 @@ static int s3_pci_resume(struct pci_dev* dev)
 
        pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
-       pci_enable_device(dev);
+       err = pci_enable_device(dev);
+       if (err) {
+               mutex_unlock(&(par->open_lock));
+               release_console_sem();
+               dev_err(&(dev->dev), "error %d enabling device for resume\n", err);
+               return err;
+       }
        pci_set_master(dev);
 
        s3fb_set_par(info);
index 8db066ccca6b8ccd314120851f5e9245246199da..35c1ce62b216ac0aeb1ea3fd7cb9d2c1a35b59ca 100644 (file)
 #define SAVAGE4_I2C_SCL_IN     0x00000008
 #define SAVAGE4_I2C_SDA_IN     0x00000010
 
-#define SET_CR_IX(base, val)   writeb((val), base + 0x8000 + VGA_CR_IX)
-#define SET_CR_DATA(base, val) writeb((val), base + 0x8000 + VGA_CR_DATA)
-#define GET_CR_DATA(base)      readb(base + 0x8000 + VGA_CR_DATA)
-
 static void savage4_gpio_setscl(void *data, int val)
 {
        struct savagefb_i2c_chan *chan = data;
@@ -92,15 +88,15 @@ static void prosavage_gpio_setscl(void* data, int val)
        struct savagefb_i2c_chan *chan = data;
        u32                       r;
 
-       SET_CR_IX(chan->ioaddr, chan->reg);
-       r = GET_CR_DATA(chan->ioaddr);
+       r = VGArCR(chan->reg, chan->par);
        r |= PROSAVAGE_I2C_ENAB;
        if (val) {
                r |= PROSAVAGE_I2C_SCL_OUT;
        } else {
                r &= ~PROSAVAGE_I2C_SCL_OUT;
        }
-       SET_CR_DATA(chan->ioaddr, r);
+
+       VGAwCR(chan->reg, r, chan->par);
 }
 
 static void prosavage_gpio_setsda(void* data, int val)
@@ -108,31 +104,29 @@ static void prosavage_gpio_setsda(void* data, int val)
        struct savagefb_i2c_chan *chan = data;
        unsigned int r;
 
-       SET_CR_IX(chan->ioaddr, chan->reg);
-       r = GET_CR_DATA(chan->ioaddr);
+       r = VGArCR(chan->reg, chan->par);
        r |= PROSAVAGE_I2C_ENAB;
        if (val) {
                r |= PROSAVAGE_I2C_SDA_OUT;
        } else {
                r &= ~PROSAVAGE_I2C_SDA_OUT;
        }
-       SET_CR_DATA(chan->ioaddr, r);
+
+       VGAwCR(chan->reg, r, chan->par);
 }
 
 static int prosavage_gpio_getscl(void* data)
 {
        struct savagefb_i2c_chan *chan = data;
 
-       SET_CR_IX(chan->ioaddr, chan->reg);
-       return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN));
+       return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0;
 }
 
 static int prosavage_gpio_getsda(void* data)
 {
        struct savagefb_i2c_chan *chan = data;
 
-       SET_CR_IX(chan->ioaddr, chan->reg);
-       return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
+       return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0;
 }
 
 static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
index e648a6c0f6d9661ec47f8d29c6c758f1dadce2ae..8bfdfc3c52342232e8dff9b3fa0f07bb3252e0e6 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/mutex.h>
+#include <video/vga.h>
 #include "../edid.h"
 
 #ifdef SAVAGEFB_DEBUG
@@ -189,8 +191,12 @@ struct savagefb_par {
        struct savagefb_i2c_chan chan;
        struct savage_reg state;
        struct savage_reg save;
+       struct savage_reg initial;
+       struct vgastate vgastate;
+       struct mutex open_lock;
        unsigned char   *edid;
        u32 pseudo_palette[16];
+       u32 open_count;
        int paletteEnabled;
        int pm_state;
        int display_type;
@@ -203,7 +209,7 @@ struct savagefb_par {
        int clock[4];
        int MCLK, REFCLK, LCDclk;
        struct {
-               u8   __iomem *vbase;
+               void   __iomem *vbase;
                u32    pbase;
                u32    len;
 #ifdef CONFIG_MTRR
@@ -212,7 +218,7 @@ struct savagefb_par {
        } video;
 
        struct {
-               volatile u8  __iomem *vbase;
+               void  __iomem *vbase;
                u32           pbase;
                u32           len;
        } mmio;
index 0166ec2ccf32c1b59057cd61bf6d6f20a7997614..3d7507ad55f66570a6a05fd2757ba53ee9beb885 100644 (file)
@@ -1623,8 +1623,46 @@ static void savagefb_restore_state(struct fb_info *info)
        savagefb_blank(FB_BLANK_UNBLANK, info);
 }
 
+static int savagefb_open(struct fb_info *info, int user)
+{
+       struct savagefb_par *par = info->par;
+
+       mutex_lock(&par->open_lock);
+
+       if (!par->open_count) {
+               memset(&par->vgastate, 0, sizeof(par->vgastate));
+               par->vgastate.flags = VGA_SAVE_CMAP | VGA_SAVE_FONTS |
+                       VGA_SAVE_MODE;
+               par->vgastate.vgabase = par->mmio.vbase + 0x8000;
+               save_vga(&par->vgastate);
+               savage_get_default_par(par, &par->initial);
+       }
+
+       par->open_count++;
+       mutex_unlock(&par->open_lock);
+       return 0;
+}
+
+static int savagefb_release(struct fb_info *info, int user)
+{
+       struct savagefb_par *par = info->par;
+
+       mutex_lock(&par->open_lock);
+
+       if (par->open_count == 1) {
+               savage_set_default_par(par, &par->initial);
+               restore_vga(&par->vgastate);
+       }
+
+       par->open_count--;
+       mutex_unlock(&par->open_lock);
+       return 0;
+}
+
 static struct fb_ops savagefb_ops = {
        .owner          = THIS_MODULE,
+       .fb_open        = savagefb_open,
+       .fb_release     = savagefb_release,
        .fb_check_var   = savagefb_check_var,
        .fb_set_par     = savagefb_set_par,
        .fb_setcolreg   = savagefb_setcolreg,
@@ -2173,6 +2211,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
        if (!info)
                return -ENOMEM;
        par = info->par;
+       mutex_init(&par->open_lock);
        err = pci_enable_device(dev);
        if (err)
                goto failed_enable;
index d048bd39961b173312be5fc0aac46d24c92185df..c1492782cb182dadc2173afe01769ef9fe323b47 100644 (file)
@@ -58,9 +58,6 @@
 #define SIS_LINUX_KERNEL               /* Linux kernel framebuffer */
 #undef  SIS_XORG_XF86                  /* XFree86/X.org */
 
-#undef SIS_LINUX_KERNEL_24
-#undef SIS_LINUX_KERNEL_26
-
 #ifdef OutPortByte
 #undef OutPortByte
 #endif
 #define SIS315H
 #endif
 
-#define SIS_LINUX_KERNEL_26
-
 #if !defined(SIS300) && !defined(SIS315H)
 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
 #warning sisfb will not work!
index 7d5ee2145e21440af006df7e259e8aa77cef3184..d5e2d9c27847d5e261d89c2419ecddcdc9e7f919 100644 (file)
 #include <linux/version.h>
 
 #include "osdef.h"
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <video/sisfb.h>
-#else
-#include <linux/sisfb.h>
-#endif
 
 #include "vgatypes.h"
 #include "vstruct.h"
 #define VER_MINOR              8
 #define VER_LEVEL              9
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <linux/spinlock.h>
-#define SIS_PCI_GET_CLASS(a, b) pci_get_class(a, b)
-#define SIS_PCI_GET_DEVICE(a,b,c) pci_get_device(a,b,c)
-#define SIS_PCI_GET_SLOT(a,b) pci_get_slot(a,b)
-#define SIS_PCI_PUT_DEVICE(a) pci_dev_put(a)
+
 #ifdef CONFIG_COMPAT
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
 #include <linux/ioctl32.h>
 #define SIS_OLD_CONFIG_COMPAT
 #else
-#include <linux/smp_lock.h>
 #define SIS_NEW_CONFIG_COMPAT
 #endif
 #endif /* CONFIG_COMPAT */
-#else  /* 2.4 */
-#define SIS_PCI_GET_CLASS(a, b) pci_find_class(a, b)
-#define SIS_PCI_GET_DEVICE(a,b,c) pci_find_device(a,b,c)
-#define SIS_PCI_GET_SLOT(a,b) pci_find_slot(a,b)
-#define SIS_PCI_PUT_DEVICE(a)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
-#ifdef __x86_64__      /* Shouldn't we check for CONFIG_IA32_EMULATION here? */
-#include <asm/ioctl32.h>
-#define SIS_OLD_CONFIG_COMPAT
-#endif
-#endif
-#endif /* 2.4 */
+
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
 #define SIS_IOTYPE1 void __iomem
 #define SIS_IOTYPE2 __iomem
@@ -498,26 +478,8 @@ struct sis_video_info {
 
        struct fb_var_screeninfo default_var;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        struct fb_fix_screeninfo sisfb_fix;
        u32             pseudo_palette[17];
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       struct display           sis_disp;
-       struct display_switch    sisfb_sw;
-       struct {
-               u16 red, green, blue, pad;
-       }               sis_palette[256];
-       union {
-#ifdef FBCON_HAS_CFB16
-               u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-               u32 cfb32[16];
-#endif
-       }               sis_fbcon_cmap;
-#endif
 
        struct sisfb_monitor {
                u16 hmin;
@@ -538,10 +500,6 @@ struct sis_video_info {
 
        int             mni;    /* Mode number index */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       int             currcon;
-#endif
-
        unsigned long   video_size;
        unsigned long   video_base;
        unsigned long   mmio_size;
@@ -578,9 +536,6 @@ struct sis_video_info {
        int             sisfb_tvplug;
        int             sisfb_tvstd;
        int             sisfb_nocrt2rate;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       int             sisfb_inverse;
-#endif
 
        u32             heapstart;              /* offset  */
        SIS_IOTYPE1     *sisfb_heap_start;      /* address */
@@ -646,9 +601,7 @@ struct sis_video_info {
        int             modechanged;
        unsigned char   modeprechange;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        u8              sisfb_lastrates[128];
-#endif
 
        int             newrom;
        int             haveXGIROM;
index 01197d7402174a113ad103f40c2197be1c809d6d..a30e1e13d8be87c7c8135ed79c57a54f3e0c691e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -1948,7 +1947,7 @@ sisfb_get_northbridge(int basechipid)
        default:        return NULL;
        }
        for(i = 0; i < nbridgenum; i++) {
-               if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
+               if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
                                nbridgeids[nbridgeidx+i], NULL)))
                        break;
        }
@@ -4613,9 +4612,9 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
        unsigned short temp;
        int ret = 0;
 
-       while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
+       while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
                temp = pdev->vendor;
-               SIS_PCI_PUT_DEVICE(pdev);
+               pci_dev_put(pdev);
                if(temp == pcivendor) {
                        ret = 1;
                        break;
@@ -5154,24 +5153,24 @@ sisfb_post_xgi(struct pci_dev *pdev)
                        if(reg & 0x80) v2 |= 0x80;
                        v2 |= 0x01;
 
-                       if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
-                               SIS_PCI_PUT_DEVICE(mypdev);
+                       if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
+                               pci_dev_put(mypdev);
                                if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
                                        v2 &= 0xf9;
                                v2 |= 0x08;
                                v1 &= 0xfe;
                        } else {
-                               mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
+                               mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
                                if(!mypdev)
-                                       mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
+                                       mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
                                if(!mypdev)
-                                       mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
+                                       mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
                                if(mypdev) {
                                        pci_read_config_dword(mypdev, 0x94, &regd);
                                        regd &= 0xfffffeff;
                                        pci_write_config_dword(mypdev, 0x94, regd);
                                        v1 &= 0xfe;
-                                       SIS_PCI_PUT_DEVICE(mypdev);
+                                       pci_dev_put(mypdev);
                                } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
                                        v1 &= 0xfe;
                                } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
@@ -5194,13 +5193,13 @@ sisfb_post_xgi(struct pci_dev *pdev)
                        if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
                                setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
 
-                       if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
+                       if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
                                /* TODO: set CR5f &0xf1 | 0x01 for version 6570
                                 * of nforce 2 ROM
                                 */
                                if(0)
                                        setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
-                               SIS_PCI_PUT_DEVICE(mypdev);
+                               pci_dev_put(mypdev);
                        }
                }
 
@@ -5236,9 +5235,9 @@ sisfb_post_xgi(struct pci_dev *pdev)
                setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
                setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
                v1 = bios[0x501];
-               if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
+               if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
                        v1 = 0xf0;
-                       SIS_PCI_PUT_DEVICE(mypdev);
+                       pci_dev_put(mypdev);
                }
                outSISIDXREG(SISCR, 0x77, v1);
        }
@@ -5947,7 +5946,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if(!ivideo->sisvga_enabled) {
                if(pci_enable_device(pdev)) {
-                       if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+                       if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
                        pci_set_drvdata(pdev, NULL);
                        kfree(sis_fb_info);
                        return -EIO;
@@ -5974,7 +5973,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                        "requiring Chrontel/GPIO setup\n",
                                        mychswtable[i].vendorName,
                                        mychswtable[i].cardName);
-                               ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
+                               ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
                                break;
                        }
                        i++;
@@ -5984,7 +5983,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 #ifdef CONFIG_FB_SIS_315
        if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
-               ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
+               ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
        }
 #endif
 
@@ -6149,9 +6148,9 @@ error_1:  release_mem_region(ivideo->video_base, ivideo->video_size);
 error_2:       release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 error_3:       vfree(ivideo->bios_abase);
                if(ivideo->lpcdev)
-                       SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+                       pci_dev_put(ivideo->lpcdev);
                if(ivideo->nbridge)
-                       SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+                       pci_dev_put(ivideo->nbridge);
                pci_set_drvdata(pdev, NULL);
                if(!ivideo->sisvga_enabled)
                        pci_disable_device(pdev);
@@ -6331,70 +6330,6 @@ error_3: vfree(ivideo->bios_abase);
 
                sisfb_set_vparms(ivideo);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-               /* ---------------- For 2.4: Now switch the mode ------------------ */
-
-               printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
-                       ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
-                       ivideo->refresh_rate);
-
-               /* Determine whether or not acceleration is to be
-                * used. Need to know before pre/post_set_mode()
-                */
-               ivideo->accel = 0;
-               ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
-               if(ivideo->sisfb_accel) {
-                       ivideo->accel = -1;
-                       ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
-               }
-
-               /* Now switch the mode */
-               sisfb_pre_setmode(ivideo);
-
-               if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
-                       printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-                                                                       ivideo->mode_no);
-                       ret = -EINVAL;
-                       iounmap(ivideo->mmio_vbase);
-                       goto error_0;
-               }
-
-               outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
-               sisfb_post_setmode(ivideo);
-
-               /* Maximize regardless of sisfb_max at startup */
-               ivideo->default_var.yres_virtual = 32767;
-
-               /* Force reset of x virtual in crtc_to_var */
-               ivideo->default_var.xres_virtual = 0;
-
-               /* Copy mode timing to var */
-               sisfb_crtc_to_var(ivideo, &ivideo->default_var);
-
-               /* Find out about screen pitch */
-               sisfb_calc_pitch(ivideo, &ivideo->default_var);
-               sisfb_set_pitch(ivideo);
-
-               /* Init the accelerator (does nothing currently) */
-               sisfb_initaccel(ivideo);
-
-               /* Init some fbinfo entries */
-               sis_fb_info->node  = -1;
-               sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-               sis_fb_info->fbops = &sisfb_ops;
-               sis_fb_info->disp  = &ivideo->sis_disp;
-               sis_fb_info->blank = &sisfb_blank;
-               sis_fb_info->switch_con = &sisfb_switch;
-               sis_fb_info->updatevar  = &sisfb_update_var;
-               sis_fb_info->changevar  = NULL;
-               strcpy(sis_fb_info->fontname, sisfb_fontname);
-
-               sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
-
-#else          /* --------- For 2.6: Setup a somewhat sane default var ------------ */
-
                printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
                        ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
                        ivideo->refresh_rate);
@@ -6454,7 +6389,6 @@ error_3:  vfree(ivideo->bios_abase);
                sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
 
                fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
-#endif         /* 2.6 */
 
                printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
 
@@ -6564,10 +6498,10 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
        vfree(ivideo->bios_abase);
 
        if(ivideo->lpcdev)
-               SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+               pci_dev_put(ivideo->lpcdev);
 
        if(ivideo->nbridge)
-               SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+               pci_dev_put(ivideo->nbridge);
 
 #ifdef CONFIG_MTRR
        /* Release MTRR region */
index bb96cb65fdaa554204e104d7cb8fb12fd4e33e0f..836a612af977f167e67ff1a0f92fe4708bc6788d 100644 (file)
@@ -14,7 +14,7 @@
  *  of it. 
  *
  *  First the roles of struct fb_info and struct display have changed. Struct
- *  display will go away. The way the the new framebuffer console code will
+ *  display will go away. The way the new framebuffer console code will
  *  work is that it will act to translate data about the tty/console in 
  *  struct vc_data to data in a device independent way in struct fb_info. Then
  *  various functions in struct fb_ops will be called to store the device 
@@ -51,6 +51,7 @@
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
+#include <linux/pci.h>
 
     /*
      *  This is just simple sample code.
      *  Even less warranty that it actually works :-)
      */
 
+/*
+ * Driver data
+ */
+static char *mode_option __devinitdata;
+
 /*
  *  If your driver supports multiple boards, you should make the  
  *  below data types arrays, or allocate them dynamically (using kmalloc()). 
@@ -78,7 +84,7 @@ struct xxx_par;
  * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
  * to get a fb_var_screeninfo. Otherwise define a default var as well. 
  */
-static struct fb_fix_screeninfo xxxfb_fix __initdata = {
+static struct fb_fix_screeninfo xxxfb_fix __devinitdata = {
        .id =           "FB's name", 
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -142,7 +148,7 @@ int xxxfb_setup(char*);
  *
  *     Returns negative errno on error, or zero on success.
  */
-static int xxxfb_open(const struct fb_info *info, int user)
+static int xxxfb_open(struct fb_info *info, int user)
 {
     return 0;
 }
@@ -161,7 +167,7 @@ static int xxxfb_open(const struct fb_info *info, int user)
  *
  *     Returns negative errno on error, or zero on success.
  */
-static int xxxfb_release(const struct fb_info *info, int user)
+static int xxxfb_release(struct fb_info *info, int user)
 {
     return 0;
 }
@@ -278,7 +284,7 @@ static int xxxfb_set_par(struct fb_info *info)
  */
 static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                           unsigned blue, unsigned transp,
-                          const struct fb_info *info)
+                          struct fb_info *info)
 {
     if (regno >= 256)  /* no. of hw registers */
        return -EINVAL;
@@ -416,7 +422,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  *      Returns negative errno on error, or zero on success.
  */
 static int xxxfb_pan_display(struct fb_var_screeninfo *var,
-                            const struct fb_info *info)
+                            struct fb_info *info)
 {
     /*
      * If your hardware does not support panning, _do_ _not_ implement this
@@ -454,7 +460,7 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var,
  *      Return !0 for any modes that are unimplemented.
  *
  */
-static int xxxfb_blank(int blank_mode, const struct fb_info *info)
+static int xxxfb_blank(int blank_mode, struct fb_info *info)
 {
     /* ... */
     return 0;
@@ -483,7 +489,7 @@ static int xxxfb_blank(int blank_mode, const struct fb_info *info)
  *     depending on the rastering operation with the value of color which
  *     is in the current color depth format.
  */
-void xxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
+void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
 {
 /*     Meaning of struct fb_fillrect
  *
@@ -622,19 +628,6 @@ void xxxfb_rotate(struct fb_info *info, int angle)
 /* Will be deprecated */
 }
 
-/**
- *     xxxfb_poll - NOT a required function. The purpose of this
- *                  function is to provide a way for some process
- *                  to wait until a specific hardware event occurs
- *                  for the framebuffer device.
- *                              
- *      @info: frame buffer structure that represents a single frame buffer
- *     @wait: poll table where we store process that await a event.     
- */
-void xxxfb_poll(struct fb_info *info, poll_table *wait)
-{
-}
-
 /**
  *     xxxfb_sync - NOT a required function. Normally the accel engine 
  *                  for a graphics card take a specific amount of time.
@@ -647,21 +640,49 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait)
  *      If the driver has implemented its own hardware-based drawing function,
  *      implementing this function is highly recommended.
  */
-void xxxfb_sync(struct fb_info *info)
+int xxxfb_sync(struct fb_info *info)
 {
+       return 0;
 }
 
+    /*
+     *  Frame buffer operations
+     */
+
+static struct fb_ops xxxfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open        = xxxfb_open,
+       .fb_read        = xxxfb_read,
+       .fb_write       = xxxfb_write,
+       .fb_release     = xxxfb_release,
+       .fb_check_var   = xxxfb_check_var,
+       .fb_set_par     = xxxfb_set_par,
+       .fb_setcolreg   = xxxfb_setcolreg,
+       .fb_blank       = xxxfb_blank,
+       .fb_pan_display = xxxfb_pan_display,
+       .fb_fillrect    = xxxfb_fillrect,       /* Needed !!! */
+       .fb_copyarea    = xxxfb_copyarea,       /* Needed !!! */
+       .fb_imageblit   = xxxfb_imageblit,      /* Needed !!! */
+       .fb_cursor      = xxxfb_cursor,         /* Optional !!! */
+       .fb_rotate      = xxxfb_rotate,
+       .fb_sync        = xxxfb_sync,
+       .fb_ioctl       = xxxfb_ioctl,
+       .fb_mmap        = xxxfb_mmap,
+};
+
+/* ------------------------------------------------------------------------- */
+
     /*
      *  Initialization
      */
 
 /* static int __init xxfb_probe (struct device *device) -- for platform devs */
-static int __init xxxfb_probe(struct pci_dev *dev,
-                             const_struct pci_device_id *ent)
+static int __devinit xxxfb_probe(struct pci_dev *dev,
+                             const struct pci_device_id *ent)
 {
     struct fb_info *info;
     struct xxx_par *par;
-    struct device = &dev->dev; /* for pci drivers */
+    struct device* device = &dev->dev; /* for pci drivers */
     int cmap_len, retval;      
    
     /*
@@ -684,7 +705,7 @@ static int __init xxxfb_probe(struct pci_dev *dev,
     info->screen_base = framebuffer_virtual_memory;
     info->fbops = &xxxfb_ops;
     info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be
-                           * used, so mark it as __initdata
+                           * used, so mark it as __devinitdata
                            */
     info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
                                            * 16-member array
@@ -760,7 +781,7 @@ static int __init xxxfb_probe(struct pci_dev *dev,
      *
      * NOTE: This field is currently unused.
      */
-    info->pixmap.scan_align = 32
+    info->pixmap.scan_align = 32;
 /***************************** End optional stage ***************************/
 
     /*
@@ -770,13 +791,13 @@ static int __init xxxfb_probe(struct pci_dev *dev,
     if (!mode_option)
        mode_option = "640x480@60";             
 
-    retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8);
+    retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
   
     if (!retval || retval == 4)
        return -EINVAL;                 
 
     /* This has to been done !!! */    
-    fb_alloc_cmap(info->cmap, cmap_len, 0);
+    fb_alloc_cmap(&info->cmap, cmap_len, 0);
        
     /* 
      * The following is done in the case of having hardware with a static 
@@ -811,34 +832,77 @@ static int __init xxxfb_probe(struct pci_dev *dev,
     /*
      *  Cleanup
      */
-/* static void __exit xxxfb_remove(struct device *device) */
-static void __exit xxxfb_remove(struct pci_dev *dev)
+/* static void __devexit xxxfb_remove(struct device *device) */
+static void __devexit xxxfb_remove(struct pci_dev *dev)
 {
-       struct fb_info *info = pci_get_drv_data(dev);
-       /* or dev_get_drv_data(device); */
+       struct fb_info *info = pci_get_drvdata(dev);
+       /* or dev_get_drvdata(device); */
 
        if (info) {
                unregister_framebuffer(info);
-               fb_dealloc_cmap(&info.cmap);
+               fb_dealloc_cmap(&info->cmap);
                /* ... */
                framebuffer_release(info);
        }
+}
+
+#ifdef CONFIG_PCI
+#ifdef CONFIG_PM
+/**
+ *     xxxfb_suspend - Optional but recommended function. Suspend the device.
+ *     @dev: PCI device
+ *     @msg: the suspend event code.
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct xxxfb_par *par = info->par;
+
+       /* suspend here */
+       return 0;
+}
+
+/**
+ *     xxxfb_resume - Optional but recommended function. Resume the device.
+ *     @dev: PCI device
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_resume(struct pci_dev *dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct xxxfb_par *par = info->par;
 
+       /* resume here */
        return 0;
 }
+#else
+#define xxxfb_suspend NULL
+#define xxxfb_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id xxxfb_id_table[] = {
+       { PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+         PCI_CLASS_MASK, 0 },
+       { 0, }
+};
 
-#if CONFIG_PCI
 /* For PCI drivers */
 static struct pci_driver xxxfb_driver = {
        .name =         "xxxfb",
-       .id_table =     xxxfb_devices,
+       .id_table =     xxxfb_id_table,
        .probe =        xxxfb_probe,
        .remove =       __devexit_p(xxxfb_remove),
-       .suspend =      xxxfb_suspend, /* optional */
-       .resume =       xxxfb_resume,  /* optional */
+       .suspend =      xxxfb_suspend, /* optional but recommended */
+       .resume =       xxxfb_resume,  /* optional but recommended */
 };
 
-static int __init xxxfb_init(void)
+MODULE_DEVICE_TABLE(pci, xxxfb_id_table);
+
+int __init xxxfb_init(void)
 {
        /*
         *  For kernel boot options (in 'video=xxxfb:<options>' format)
@@ -858,16 +922,53 @@ static void __exit xxxfb_exit(void)
 {
        pci_unregister_driver(&xxxfb_driver);
 }
-#else
+#else /* non PCI, platform drivers */
 #include <linux/platform_device.h>
 /* for platform devices */
+
+#ifdef CONFIG_PM
+/**
+ *     xxxfb_suspend - Optional but recommended function. Suspend the device.
+ *     @dev: platform device
+ *     @msg: the suspend event code.
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct xxxfb_par *par = info->par;
+
+       /* suspend here */
+       return 0;
+}
+
+/**
+ *     xxxfb_resume - Optional but recommended function. Resume the device.
+ *     @dev: platform device
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_resume(struct platform_dev *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct xxxfb_par *par = info->par;
+
+       /* resume here */
+       return 0;
+}
+#else
+#define xxxfb_suspend NULL
+#define xxxfb_resume NULL
+#endif /* CONFIG_PM */
+
 static struct device_driver xxxfb_driver = {
        .name = "xxxfb",
        .bus  = &platform_bus_type,
        .probe = xxxfb_probe,
        .remove = xxxfb_remove,
-       .suspend = xxxfb_suspend, /* optional */
-       .resume = xxxfb_resume,   /* optional */
+       .suspend = xxxfb_suspend, /* optional but recommended */
+       .resume = xxxfb_resume,   /* optional but recommended */
 };
 
 static struct platform_device xxxfb_device = {
@@ -903,8 +1004,9 @@ static void __exit xxxfb_exit(void)
        platform_device_unregister(&xxxfb_device);
        driver_unregister(&xxxfb_driver);
 }
-#endif
+#endif /* CONFIG_PCI */
 
+#ifdef MODULE
     /*
      *  Setup
      */
@@ -917,34 +1019,7 @@ int __init xxxfb_setup(char *options)
 {
     /* Parse user speficied options (`video=xxxfb:') */
 }
-
-/* ------------------------------------------------------------------------- */
-
-    /*
-     *  Frame buffer operations
-     */
-
-static struct fb_ops xxxfb_ops = {
-       .owner          = THIS_MODULE,
-       .fb_open        = xxxfb_open,
-       .fb_read        = xxxfb_read,
-       .fb_write       = xxxfb_write,
-       .fb_release     = xxxfb_release,
-       .fb_check_var   = xxxfb_check_var,
-       .fb_set_par     = xxxfb_set_par,        
-       .fb_setcolreg   = xxxfb_setcolreg,
-       .fb_blank       = xxxfb_blank,
-       .fb_pan_display = xxxfb_pan_display,    
-       .fb_fillrect    = xxxfb_fillrect,       /* Needed !!! */ 
-       .fb_copyarea    = xxxfb_copyarea,       /* Needed !!! */ 
-       .fb_imageblit   = xxxfb_imageblit,      /* Needed !!! */
-       .fb_cursor      = xxxfb_cursor,         /* Optional !!! */
-       .fb_rotate      = xxxfb_rotate,
-       .fb_poll        = xxxfb_poll,
-       .fb_sync        = xxxfb_sync,
-       .fb_ioctl       = xxxfb_ioctl,
-       .fb_mmap        = xxxfb_mmap,   
-};
+#endif /* MODULE */
 
 /* ------------------------------------------------------------------------- */
 
@@ -954,6 +1029,6 @@ static struct fb_ops xxxfb_ops = {
      */
 
 module_init(xxxfb_init);
-module_exit(xxxfb_cleanup);
+module_exit(xxxfb_remove);
 
 MODULE_LICENSE("GPL");
index 0a44c44672c82855c0c3152f1c631ce0d2925fdc..c86df126f93a2870e8176d2a0dfc5b760eae109c 100644 (file)
@@ -989,7 +989,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
                        ((info->cmap.green[fg_col] & 0xFC) << 3) |
                        ((info->cmap.blue[fg_col] & 0xF8) >> 3);
 
-               dev_dbg(fbi->dev, "fgcol %08x, bgcol %08x\n", fg, bg);
+               dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
 
                writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
                writel(fg, base + SM501_OFF_HWC_COLOR_3);
index 4010492c692004a379ab64d754646df567a20131..4316c7fe8e21c52d92fa4cca203bb796d7594a54 100644 (file)
@@ -237,14 +237,14 @@ static void __devexit s3d_pci_unregister(struct pci_dev *pdev)
 }
 
 static struct pci_device_id s3d_pci_table[] = {
-       {       /* XVR-2500 */
-               PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032),
-               .driver_data = 1,
-       },
-       {       /* XVR-500 */
-               PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x07a2),
-               .driver_data = 0,
-       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002c),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002d),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002e),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002f),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0030),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0031),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0033),       },
        { 0, }
 };
 
index 68b30d9eac587dfdf1b939eeedbc08f7c1304089..25df928d37d841317dee63632b08179b2fa4accf 100644 (file)
@@ -194,7 +194,7 @@ void svga_dump_var(struct fb_var_screeninfo *var, int node)
 void svga_settile(struct fb_info *info, struct fb_tilemap *map)
 {
        const u8 *font = map->data;
-       u8* fb = (u8 *) info->screen_base;
+       u8 __iomem *fb = (u8 __iomem *)info->screen_base;
        int i, c;
 
        if ((map->width != 8) || (map->height != 16) ||
@@ -207,7 +207,8 @@ void svga_settile(struct fb_info *info, struct fb_tilemap *map)
        fb += 2;
        for (c = 0; c < map->length; c++) {
                for (i = 0; i < map->height; i++) {
-                       fb[i * 4] = font[i];
+                       fb_writeb(font[i], fb + i * 4);
+//                     fb[i * 4] = font[i];
                }
                fb += 128;
                font += map->height;
@@ -221,8 +222,8 @@ void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
        /*  colstride is halved in this function because u16 are used */
        int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
        int rowstride = colstride * (info->var.xres_virtual / 8);
-       u16 *fb = (u16 *) info->screen_base;
-       u16 *src, *dst;
+       u16 __iomem *fb = (u16 __iomem *) info->screen_base;
+       u16 __iomem *src, *dst;
 
        if ((area->sy > area->dy) ||
            ((area->sy == area->dy) && (area->sx > area->dx))) {
@@ -239,10 +240,11 @@ void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
            }
 
        for (dy = 0; dy < area->height; dy++) {
-               u16src2 = src;
-               u16dst2 = dst;
+               u16 __iomem *src2 = src;
+               u16 __iomem *dst2 = dst;
                for (dx = 0; dx < area->width; dx++) {
-                       *dst2 = *src2;
+                       fb_writew(fb_readw(src2), dst2);
+//                     *dst2 = *src2;
                        src2 += colstride;
                        dst2 += colstride;
                }
@@ -258,14 +260,14 @@ void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
        int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
        int rowstride = colstride * (info->var.xres_virtual / 8);
        int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
-       u8  *fb = (u8 *) info->screen_base;
+       u8 __iomem *fb = (u8 __iomem *)info->screen_base;
        fb += rect->sx * colstride + rect->sy * rowstride;
 
        for (dy = 0; dy < rect->height; dy++) {
-               u8fb2 = fb;
+               u8 __iomem *fb2 = fb;
                for (dx = 0; dx < rect->width; dx++) {
-                       fb2[0] = rect->index;
-                       fb2[1] = attr;
+                       fb_writeb(rect->index, fb2);
+                       fb_writeb(attr, fb2 + 1);
                        fb2 += colstride;
                }
                fb += rowstride;
@@ -279,15 +281,15 @@ void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
        int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
        int rowstride = colstride * (info->var.xres_virtual / 8);
        int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
-       u8* fb = (u8 *) info->screen_base;
+       u8 __iomem *fb = (u8 __iomem *)info->screen_base;
        fb += blit->sx * colstride + blit->sy * rowstride;
 
        i=0;
        for (dy=0; dy < blit->height; dy ++) {
-               u8fb2 = fb;
+               u8 __iomem *fb2 = fb;
                for (dx = 0; dx < blit->width; dx ++) {
-                       fb2[0] = blit->indices[i];
-                       fb2[1] = attr;
+                       fb_writeb(blit->indices[i], fb2);
+                       fb_writeb(attr, fb2 + 1);
                        fb2 += colstride;
                        i ++;
                        if (i == blit->length) return;
@@ -340,6 +342,28 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
        vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */
 }
 
+int svga_get_tilemax(struct fb_info *info)
+{
+       return 256;
+}
+
+/* Get capabilities of accelerator based on the mode */
+
+void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
+                  struct fb_var_screeninfo *var)
+{
+       if (var->bits_per_pixel == 0) {
+               /* can only support 256 8x16 bitmap */
+               caps->x = 1 << (8 - 1);
+               caps->y = 1 << (16 - 1);
+               caps->len = 256;
+       } else {
+               caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0;
+               caps->y = ~(u32)0;
+               caps->len = ~(u32)0;
+       }
+}
+EXPORT_SYMBOL(svga_get_caps);
 
 /* ------------------------------------------------------------------------- */
 
@@ -621,6 +645,7 @@ EXPORT_SYMBOL(svga_tilecopy);
 EXPORT_SYMBOL(svga_tilefill);
 EXPORT_SYMBOL(svga_tileblit);
 EXPORT_SYMBOL(svga_tilecursor);
+EXPORT_SYMBOL(svga_get_tilemax);
 
 EXPORT_SYMBOL(svga_compute_pll);
 EXPORT_SYMBOL(svga_check_timings);
diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c
new file mode 100644 (file)
index 0000000..37af10a
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *  Generic Bit Block Transfer for frame buffers located in system RAM with
+ *  packed pixels of any depth.
+ *
+ *  Based almost entirely from cfbcopyarea.c (which is based almost entirely
+ *  on Geert Uytterhoeven's copyarea routine)
+ *
+ *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/slab.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include "fb_draw.h"
+
+    /*
+     *  Generic bitwise copy algorithm
+     */
+
+static void
+bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
+       int src_idx, int bits, unsigned n)
+{
+       unsigned long first, last;
+       int const shift = dst_idx-src_idx;
+       int left, right;
+
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+
+       if (!shift) {
+               /* Same alignment for source and dest */
+               if (dst_idx+n <= bits) {
+                       /* Single word */
+                       if (last)
+                               first &= last;
+                       *dst = comp(*src, *dst, first);
+               } else {
+                       /* Multiple destination words */
+                       /* Leading bits */
+                       if (first != ~0UL) {
+                               *dst = comp(*src, *dst, first);
+                               dst++;
+                               src++;
+                               n -= bits - dst_idx;
+                       }
+
+                       /* Main chunk */
+                       n /= bits;
+                       while (n >= 8) {
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               *dst++ = *src++;
+                               n -= 8;
+                       }
+                       while (n--)
+                               *dst++ = *src++;
+
+                       /* Trailing bits */
+                       if (last)
+                               *dst = comp(*src, *dst, last);
+               }
+       } else {
+               unsigned long d0, d1;
+               int m;
+
+               /* Different alignment for source and dest */
+               right = shift & (bits - 1);
+               left = -shift & (bits - 1);
+
+               if (dst_idx+n <= bits) {
+                       /* Single destination word */
+                       if (last)
+                               first &= last;
+                       if (shift > 0) {
+                               /* Single source word */
+                               *dst = comp(*src >> right, *dst, first);
+                       } else if (src_idx+n <= bits) {
+                               /* Single source word */
+                               *dst = comp(*src << left, *dst, first);
+                       } else {
+                               /* 2 source words */
+                               d0 = *src++;
+                               d1 = *src;
+                               *dst = comp(d0 << left | d1 >> right, *dst,
+                                           first);
+                       }
+               } else {
+                       /* Multiple destination words */
+                       /** We must always remember the last value read,
+                           because in case SRC and DST overlap bitwise (e.g.
+                           when moving just one pixel in 1bpp), we always
+                           collect one full long for DST and that might
+                           overlap with the current long from SRC. We store
+                           this value in 'd0'. */
+                       d0 = *src++;
+                       /* Leading bits */
+                       if (shift > 0) {
+                               /* Single source word */
+                               *dst = comp(d0 >> right, *dst, first);
+                               dst++;
+                               n -= bits - dst_idx;
+                       } else {
+                               /* 2 source words */
+                               d1 = *src++;
+                               *dst = comp(d0 << left | *dst >> right, *dst, first);
+                               d0 = d1;
+                               dst++;
+                               n -= bits - dst_idx;
+                       }
+
+                       /* Main chunk */
+                       m = n % bits;
+                       n /= bits;
+                       while (n >= 4) {
+                               d1 = *src++;
+                               *dst++ = d0 << left | d1 >> right;
+                               d0 = d1;
+                               d1 = *src++;
+                               *dst++ = d0 << left | d1 >> right;
+                               d0 = d1;
+                               d1 = *src++;
+                               *dst++ = d0 << left | d1 >> right;
+                               d0 = d1;
+                               d1 = *src++;
+                               *dst++ = d0 << left | d1 >> right;
+                               d0 = d1;
+                               n -= 4;
+                       }
+                       while (n--) {
+                               d1 = *src++;
+                               *dst++ = d0 << left | d1 >> right;
+                               d0 = d1;
+                       }
+
+                       /* Trailing bits */
+                       if (last) {
+                               if (m <= right) {
+                                       /* Single source word */
+                                       *dst = comp(d0 << left, *dst, last);
+                               } else {
+                                       /* 2 source words */
+                                       d1 = *src;
+                                       *dst = comp(d0 << left | d1 >> right,
+                                                   *dst, last);
+                               }
+                       }
+               }
+       }
+}
+
+    /*
+     *  Generic bitwise copy algorithm, operating backward
+     */
+
+static void
+bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src,
+          int src_idx, int bits, unsigned n)
+{
+       unsigned long first, last;
+       int shift;
+
+       dst += (n-1)/bits;
+       src += (n-1)/bits;
+       if ((n-1) % bits) {
+               dst_idx += (n-1) % bits;
+               dst += dst_idx >> (ffs(bits) - 1);
+               dst_idx &= bits - 1;
+               src_idx += (n-1) % bits;
+               src += src_idx >> (ffs(bits) - 1);
+               src_idx &= bits - 1;
+       }
+
+       shift = dst_idx-src_idx;
+
+       first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
+       last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
+
+       if (!shift) {
+               /* Same alignment for source and dest */
+               if ((unsigned long)dst_idx+1 >= n) {
+                       /* Single word */
+                       if (last)
+                               first &= last;
+                       *dst = comp(*src, *dst, first);
+               } else {
+                       /* Multiple destination words */
+
+                       /* Leading bits */
+                       if (first != ~0UL) {
+                               *dst = comp(*src, *dst, first);
+                               dst--;
+                               src--;
+                               n -= dst_idx+1;
+                       }
+
+                       /* Main chunk */
+                       n /= bits;
+                       while (n >= 8) {
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               *dst-- = *src--;
+                               n -= 8;
+                       }
+                       while (n--)
+                               *dst-- = *src--;
+                       /* Trailing bits */
+                       if (last)
+                               *dst = comp(*src, *dst, last);
+               }
+       } else {
+               /* Different alignment for source and dest */
+
+               int const left = -shift & (bits-1);
+               int const right = shift & (bits-1);
+
+               if ((unsigned long)dst_idx+1 >= n) {
+                       /* Single destination word */
+                       if (last)
+                               first &= last;
+                       if (shift < 0) {
+                               /* Single source word */
+                               *dst = comp(*src << left, *dst, first);
+                       } else if (1+(unsigned long)src_idx >= n) {
+                               /* Single source word */
+                               *dst = comp(*src >> right, *dst, first);
+                       } else {
+                               /* 2 source words */
+                               *dst = comp(*src >> right | *(src-1) << left,
+                                           *dst, first);
+                       }
+               } else {
+                       /* Multiple destination words */
+                       /** We must always remember the last value read,
+                           because in case SRC and DST overlap bitwise (e.g.
+                           when moving just one pixel in 1bpp), we always
+                           collect one full long for DST and that might
+                           overlap with the current long from SRC. We store
+                           this value in 'd0'. */
+                       unsigned long d0, d1;
+                       int m;
+
+                       d0 = *src--;
+                       /* Leading bits */
+                       if (shift < 0) {
+                               /* Single source word */
+                               *dst = comp(d0 << left, *dst, first);
+                       } else {
+                               /* 2 source words */
+                               d1 = *src--;
+                               *dst = comp(d0 >> right | d1 << left, *dst,
+                                           first);
+                               d0 = d1;
+                       }
+                       dst--;
+                       n -= dst_idx+1;
+
+                       /* Main chunk */
+                       m = n % bits;
+                       n /= bits;
+                       while (n >= 4) {
+                               d1 = *src--;
+                               *dst-- = d0 >> right | d1 << left;
+                               d0 = d1;
+                               d1 = *src--;
+                               *dst-- = d0 >> right | d1 << left;
+                               d0 = d1;
+                               d1 = *src--;
+                               *dst-- = d0 >> right | d1 << left;
+                               d0 = d1;
+                               d1 = *src--;
+                               *dst-- = d0 >> right | d1 << left;
+                               d0 = d1;
+                               n -= 4;
+                       }
+                       while (n--) {
+                               d1 = *src--;
+                               *dst-- = d0 >> right | d1 << left;
+                               d0 = d1;
+                       }
+
+                       /* Trailing bits */
+                       if (last) {
+                               if (m <= left) {
+                                       /* Single source word */
+                                       *dst = comp(d0 >> right, *dst, last);
+                               } else {
+                                       /* 2 source words */
+                                       d1 = *src;
+                                       *dst = comp(d0 >> right | d1 << left,
+                                                   *dst, last);
+                               }
+                       }
+               }
+       }
+}
+
+void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+       u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+       u32 height = area->height, width = area->width;
+       unsigned long const bits_per_line = p->fix.line_length*8u;
+       unsigned long *dst = NULL, *src = NULL;
+       int bits = BITS_PER_LONG, bytes = bits >> 3;
+       int dst_idx = 0, src_idx = 0, rev_copy = 0;
+
+       if (p->state != FBINFO_STATE_RUNNING)
+               return;
+
+       /* if the beginning of the target area might overlap with the end of
+       the source area, be have to copy the area reverse. */
+       if ((dy == sy && dx > sx) || (dy > sy)) {
+               dy += height;
+               sy += height;
+               rev_copy = 1;
+       }
+
+       /* split the base of the framebuffer into a long-aligned address and
+          the index of the first bit */
+       dst = src = (unsigned long *)((unsigned long)p->screen_base &
+                                     ~(bytes-1));
+       dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+       /* add offset of source and target area */
+       dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+       src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+
+       if (p->fbops->fb_sync)
+               p->fbops->fb_sync(p);
+
+       if (rev_copy) {
+               while (height--) {
+                       dst_idx -= bits_per_line;
+                       src_idx -= bits_per_line;
+                       dst += dst_idx >> (ffs(bits) - 1);
+                       dst_idx &= (bytes - 1);
+                       src += src_idx >> (ffs(bits) - 1);
+                       src_idx &= (bytes - 1);
+                       bitcpy_rev(dst, dst_idx, src, src_idx, bits,
+                               width*p->var.bits_per_pixel);
+               }
+       } else {
+               while (height--) {
+                       dst += dst_idx >> (ffs(bits) - 1);
+                       dst_idx &= (bytes - 1);
+                       src += src_idx >> (ffs(bits) - 1);
+                       src_idx &= (bytes - 1);
+                       bitcpy(dst, dst_idx, src, src_idx, bits,
+                               width*p->var.bits_per_pixel);
+                       dst_idx += bits_per_line;
+                       src_idx += bits_per_line;
+               }
+       }
+}
+
+EXPORT_SYMBOL(sys_copyarea);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c
new file mode 100644 (file)
index 0000000..a261e9e
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ *  Generic fillrect for frame buffers in system RAM with packed pixels of
+ *  any depth.
+ *
+ *  Based almost entirely from cfbfillrect.c (which is based almost entirely
+ *  on Geert Uytterhoeven's fillrect routine)
+ *
+ *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include "fb_draw.h"
+
+    /*
+     *  Aligned pattern fill using 32/64-bit memory accesses
+     */
+
+static void
+bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat,
+               unsigned n, int bits)
+{
+       unsigned long first, last;
+
+       if (!n)
+               return;
+
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+
+       if (dst_idx+n <= bits) {
+               /* Single word */
+               if (last)
+                       first &= last;
+               *dst = comp(pat, *dst, first);
+       } else {
+               /* Multiple destination words */
+
+               /* Leading bits */
+               if (first!= ~0UL) {
+                       *dst = comp(pat, *dst, first);
+                       dst++;
+                       n -= bits - dst_idx;
+               }
+
+               /* Main chunk */
+               n /= bits;
+               while (n >= 8) {
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       *dst++ = pat;
+                       n -= 8;
+               }
+               while (n--)
+                       *dst++ = pat;
+               /* Trailing bits */
+               if (last)
+                       *dst = comp(pat, *dst, last);
+       }
+}
+
+
+    /*
+     *  Unaligned generic pattern fill using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat,
+                 int left, int right, unsigned n, int bits)
+{
+       unsigned long first, last;
+
+       if (!n)
+               return;
+
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+
+       if (dst_idx+n <= bits) {
+               /* Single word */
+               if (last)
+                       first &= last;
+               *dst = comp(pat, *dst, first);
+       } else {
+               /* Multiple destination words */
+               /* Leading bits */
+               if (first) {
+                       *dst = comp(pat, *dst, first);
+                       dst++;
+                       pat = pat << left | pat >> right;
+                       n -= bits - dst_idx;
+               }
+
+               /* Main chunk */
+               n /= bits;
+               while (n >= 4) {
+                       *dst++ = pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ = pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ = pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ = pat;
+                       pat = pat << left | pat >> right;
+                       n -= 4;
+               }
+               while (n--) {
+                       *dst++ = pat;
+                       pat = pat << left | pat >> right;
+               }
+
+               /* Trailing bits */
+               if (last)
+                       *dst = comp(pat, *dst, first);
+       }
+}
+
+    /*
+     *  Aligned pattern invert using 32/64-bit memory accesses
+     */
+static void
+bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+                   unsigned n, int bits)
+{
+       unsigned long val = pat;
+       unsigned long first, last;
+
+       if (!n)
+               return;
+
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+
+       if (dst_idx+n <= bits) {
+               /* Single word */
+               if (last)
+                       first &= last;
+               *dst = comp(*dst ^ val, *dst, first);
+       } else {
+               /* Multiple destination words */
+               /* Leading bits */
+               if (first!=0UL) {
+                       *dst = comp(*dst ^ val, *dst, first);
+                       dst++;
+                       n -= bits - dst_idx;
+               }
+
+               /* Main chunk */
+               n /= bits;
+               while (n >= 8) {
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       *dst++ ^= val;
+                       n -= 8;
+               }
+               while (n--)
+                       *dst++ ^= val;
+               /* Trailing bits */
+               if (last)
+                       *dst = comp(*dst ^ val, *dst, last);
+       }
+}
+
+
+    /*
+     *  Unaligned generic pattern invert using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+                       int left, int right, unsigned n, int bits)
+{
+       unsigned long first, last;
+
+       if (!n)
+               return;
+
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+
+       if (dst_idx+n <= bits) {
+               /* Single word */
+               if (last)
+                       first &= last;
+               *dst = comp(*dst ^ pat, *dst, first);
+       } else {
+               /* Multiple destination words */
+
+               /* Leading bits */
+               if (first != 0UL) {
+                       *dst = comp(*dst ^ pat, *dst, first);
+                       dst++;
+                       pat = pat << left | pat >> right;
+                       n -= bits - dst_idx;
+               }
+
+               /* Main chunk */
+               n /= bits;
+               while (n >= 4) {
+                       *dst++ ^= pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ ^= pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ ^= pat;
+                       pat = pat << left | pat >> right;
+                       *dst++ ^= pat;
+                       pat = pat << left | pat >> right;
+                       n -= 4;
+               }
+               while (n--) {
+                       *dst ^= pat;
+                       pat = pat << left | pat >> right;
+               }
+
+               /* Trailing bits */
+               if (last)
+                       *dst = comp(*dst ^ pat, *dst, last);
+       }
+}
+
+void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+       unsigned long pat, fg;
+       unsigned long width = rect->width, height = rect->height;
+       int bits = BITS_PER_LONG, bytes = bits >> 3;
+       u32 bpp = p->var.bits_per_pixel;
+       unsigned long *dst;
+       int dst_idx, left;
+
+       if (p->state != FBINFO_STATE_RUNNING)
+               return;
+
+       if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+           p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+               fg = ((u32 *) (p->pseudo_palette))[rect->color];
+       else
+               fg = rect->color;
+
+       pat = pixel_to_pat( bpp, fg);
+
+       dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
+       dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
+       dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
+       /* FIXME For now we support 1-32 bpp only */
+       left = bits % bpp;
+       if (p->fbops->fb_sync)
+               p->fbops->fb_sync(p);
+       if (!left) {
+               void (*fill_op32)(unsigned long *dst, int dst_idx,
+                                 unsigned long pat, unsigned n, int bits) =
+                       NULL;
+
+               switch (rect->rop) {
+               case ROP_XOR:
+                       fill_op32 = bitfill_aligned_rev;
+                       break;
+               case ROP_COPY:
+                       fill_op32 = bitfill_aligned;
+                       break;
+               default:
+                       printk( KERN_ERR "cfb_fillrect(): unknown rop, "
+                               "defaulting to ROP_COPY\n");
+                       fill_op32 = bitfill_aligned;
+                       break;
+               }
+               while (height--) {
+                       dst += dst_idx >> (ffs(bits) - 1);
+                       dst_idx &= (bits - 1);
+                       fill_op32(dst, dst_idx, pat, width*bpp, bits);
+                       dst_idx += p->fix.line_length*8;
+               }
+       } else {
+               int right;
+               int r;
+               int rot = (left-dst_idx) % bpp;
+               void (*fill_op)(unsigned long *dst, int dst_idx,
+                               unsigned long pat, int left, int right,
+                               unsigned n, int bits) = NULL;
+
+               /* rotate pattern to correct start position */
+               pat = pat << rot | pat >> (bpp-rot);
+
+               right = bpp-left;
+               switch (rect->rop) {
+               case ROP_XOR:
+                       fill_op = bitfill_unaligned_rev;
+                       break;
+               case ROP_COPY:
+                       fill_op = bitfill_unaligned;
+                       break;
+               default:
+                       printk(KERN_ERR "cfb_fillrect(): unknown rop, "
+                               "defaulting to ROP_COPY\n");
+                       fill_op = bitfill_unaligned;
+                       break;
+               }
+               while (height--) {
+                       dst += dst_idx >> (ffs(bits) - 1);
+                       dst_idx &= (bits - 1);
+                       fill_op(dst, dst_idx, pat, left, right,
+                               width*bpp, bits);
+                       r = (p->fix.line_length*8) % bpp;
+                       pat = pat << (bpp-r) | pat >> r;
+                       dst_idx += p->fix.line_length*8;
+               }
+       }
+}
+
+EXPORT_SYMBOL(sys_fillrect);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c
new file mode 100644 (file)
index 0000000..bd7e7e9
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ *  Generic 1-bit or 8-bit source to 1-32 bit destination expansion
+ *  for frame buffer located in system RAM with packed pixels of any depth.
+ *
+ *  Based almost entirely on cfbimgblt.c
+ *
+ *      Copyright (C)  April 2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static const u32 cfb_tab8[] = {
+#if defined(__BIG_ENDIAN)
+    0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+    0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+    0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+    0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+#elif defined(__LITTLE_ENDIAN)
+    0x00000000,0xff000000,0x00ff0000,0xffff0000,
+    0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+    0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+    0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+#else
+#error FIXME: No endianness??
+#endif
+};
+
+static const u32 cfb_tab16[] = {
+#if defined(__BIG_ENDIAN)
+    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
+#elif defined(__LITTLE_ENDIAN)
+    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+#else
+#error FIXME: No endianness??
+#endif
+};
+
+static const u32 cfb_tab32[] = {
+       0x00000000, 0xffffffff
+};
+
+static void color_imageblit(const struct fb_image *image, struct fb_info *p,
+                           void *dst1, u32 start_index, u32 pitch_index)
+{
+       /* Draw the penguin */
+       u32 *dst, *dst2;
+       u32 color = 0, val, shift;
+       int i, n, bpp = p->var.bits_per_pixel;
+       u32 null_bits = 32 - bpp;
+       u32 *palette = (u32 *) p->pseudo_palette;
+       const u8 *src = image->data;
+
+       dst2 = dst1;
+       for (i = image->height; i--; ) {
+               n = image->width;
+               dst = dst1;
+               shift = 0;
+               val = 0;
+
+               if (start_index) {
+                       u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,
+                                                        start_index));
+                       val = *dst & start_mask;
+                       shift = start_index;
+               }
+               while (n--) {
+                       if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+                           p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+                               color = palette[*src];
+                       else
+                               color = *src;
+                       color <<= FB_LEFT_POS(bpp);
+                       val |= FB_SHIFT_HIGH(color, shift);
+                       if (shift >= null_bits) {
+                               *dst++ = val;
+
+                               val = (shift == null_bits) ? 0 :
+                                       FB_SHIFT_LOW(color, 32 - shift);
+                       }
+                       shift += bpp;
+                       shift &= (32 - 1);
+                       src++;
+               }
+               if (shift) {
+                       u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
+
+                       *dst &= end_mask;
+                       *dst |= val;
+               }
+               dst1 += p->fix.line_length;
+               if (pitch_index) {
+                       dst2 += p->fix.line_length;
+                       dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+
+                       start_index += pitch_index;
+                       start_index &= 32 - 1;
+               }
+       }
+}
+
+static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+                                 void *dst1, u32 fgcolor, u32 bgcolor,
+                                 u32 start_index, u32 pitch_index)
+{
+       u32 shift, color = 0, bpp = p->var.bits_per_pixel;
+       u32 *dst, *dst2;
+       u32 val, pitch = p->fix.line_length;
+       u32 null_bits = 32 - bpp;
+       u32 spitch = (image->width+7)/8;
+       const u8 *src = image->data, *s;
+       u32 i, j, l;
+
+       dst2 = dst1;
+       fgcolor <<= FB_LEFT_POS(bpp);
+       bgcolor <<= FB_LEFT_POS(bpp);
+
+       for (i = image->height; i--; ) {
+               shift = val = 0;
+               l = 8;
+               j = image->width;
+               dst = dst1;
+               s = src;
+
+               /* write leading bits */
+               if (start_index) {
+                       u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index));
+                       val = *dst & start_mask;
+                       shift = start_index;
+               }
+
+               while (j--) {
+                       l--;
+                       color = (*s & (1 << l)) ? fgcolor : bgcolor;
+                       val |= FB_SHIFT_HIGH(color, shift);
+
+                       /* Did the bitshift spill bits to the next long? */
+                       if (shift >= null_bits) {
+                               *dst++ = val;
+                               val = (shift == null_bits) ? 0 :
+                                       FB_SHIFT_LOW(color,32 - shift);
+                       }
+                       shift += bpp;
+                       shift &= (32 - 1);
+                       if (!l) { l = 8; s++; };
+               }
+
+               /* write trailing bits */
+               if (shift) {
+                       u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
+
+                       *dst &= end_mask;
+                       *dst |= val;
+               }
+
+               dst1 += pitch;
+               src += spitch;
+               if (pitch_index) {
+                       dst2 += pitch;
+                       dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+                       start_index += pitch_index;
+                       start_index &= 32 - 1;
+               }
+
+       }
+}
+
+/*
+ * fast_imageblit - optimized monochrome color expansion
+ *
+ * Only if:  bits_per_pixel == 8, 16, or 32
+ *           image->width is divisible by pixel/dword (ppw);
+ *           fix->line_legth is divisible by 4;
+ *           beginning and end of a scanline is dword aligned
+ */
+static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+                                 void *dst1, u32 fgcolor, u32 bgcolor)
+{
+       u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
+       u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
+       u32 bit_mask, end_mask, eorx, shift;
+       const char *s = image->data, *src;
+       u32 *dst;
+       const u32 *tab = NULL;
+       int i, j, k;
+
+       switch (bpp) {
+       case 8:
+               tab = cfb_tab8;
+               break;
+       case 16:
+               tab = cfb_tab16;
+               break;
+       case 32:
+       default:
+               tab = cfb_tab32;
+               break;
+       }
+
+       for (i = ppw-1; i--; ) {
+               fgx <<= bpp;
+               bgx <<= bpp;
+               fgx |= fgcolor;
+               bgx |= bgcolor;
+       }
+
+       bit_mask = (1 << ppw) - 1;
+       eorx = fgx ^ bgx;
+       k = image->width/ppw;
+
+       for (i = image->height; i--; ) {
+               dst = dst1;
+               shift = 8;
+               src = s;
+
+               for (j = k; j--; ) {
+                       shift -= ppw;
+                       end_mask = tab[(*src >> shift) & bit_mask];
+                       *dst++ = (end_mask & eorx) ^ bgx;
+                       if (!shift) {
+                               shift = 8;
+                               src++;
+                       }
+               }
+               dst1 += p->fix.line_length;
+               s += spitch;
+       }
+}
+
+void sys_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+       u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+       u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
+       u32 width = image->width;
+       u32 dx = image->dx, dy = image->dy;
+       void *dst1;
+
+       if (p->state != FBINFO_STATE_RUNNING)
+               return;
+
+       bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
+       start_index = bitstart & (32 - 1);
+       pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+
+       bitstart /= 8;
+       bitstart &= ~(bpl - 1);
+       dst1 = (void __force *)p->screen_base + bitstart;
+
+       if (p->fbops->fb_sync)
+               p->fbops->fb_sync(p);
+
+       if (image->depth == 1) {
+               if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+                   p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+                       fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
+                       bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
+               } else {
+                       fgcolor = image->fg_color;
+                       bgcolor = image->bg_color;
+               }
+
+               if (32 % bpp == 0 && !start_index && !pitch_index &&
+                   ((width & (32/bpp-1)) == 0) &&
+                   bpp >= 8 && bpp <= 32)
+                       fast_imageblit(image, p, dst1, fgcolor, bgcolor);
+               else
+                       slow_imageblit(image, p, dst1, fgcolor, bgcolor,
+                                       start_index, pitch_index);
+       } else
+               color_imageblit(image, p, dst1, start_index, pitch_index);
+}
+
+EXPORT_SYMBOL(sys_imageblit);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
+MODULE_LICENSE("GPL");
+
index 7478d0e3e21153e998dc23800bd4c31bd44dc9cd..f0fde6ea7c36e252f5f6dec8d205664d5ce8b023 100644 (file)
@@ -5,27 +5,45 @@
  *     Copyright (C) 1997 Geert Uytterhoeven
  *     Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
  *     Copyright (C) 2002 Richard Henderson
+ *     Copyright (C) 2006 Maciej W. Rozycki
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/bitrev.h>
 #include <linux/delay.h>
-#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
 #include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/selection.h>
-#include <linux/bitrev.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+
 #include <asm/io.h>
+
 #include <video/tgafb.h>
 
+#ifdef CONFIG_PCI
+#define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type)
+#else
+#define TGA_BUS_PCI(dev) 0
+#endif
+
+#ifdef CONFIG_TC
+#define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
+#else
+#define TGA_BUS_TC(dev) 0
+#endif
+
 /*
  * Local functions.
  */
@@ -41,14 +59,19 @@ static void tgafb_init_fix(struct fb_info *);
 static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
 static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 
-static int __devinit tgafb_pci_register(struct pci_dev *,
-                                       const struct pci_device_id *);
-static void __devexit tgafb_pci_unregister(struct pci_dev *);
+static int __devinit tgafb_register(struct device *dev);
+static void __devexit tgafb_unregister(struct device *dev);
 
-static const char *mode_option = "640x480@60";
+static const char *mode_option;
+static const char *mode_option_pci = "640x480@60";
+static const char *mode_option_tc = "1280x1024@72";
 
 
+static struct pci_driver tgafb_pci_driver;
+static struct tc_driver tgafb_tc_driver;
+
 /*
  *  Frame buffer operations
  */
@@ -59,15 +82,20 @@ static struct fb_ops tgafb_ops = {
        .fb_set_par             = tgafb_set_par,
        .fb_setcolreg           = tgafb_setcolreg,
        .fb_blank               = tgafb_blank,
+       .fb_pan_display         = tgafb_pan_display,
        .fb_fillrect            = tgafb_fillrect,
        .fb_copyarea            = tgafb_copyarea,
        .fb_imageblit           = tgafb_imageblit,
 };
 
 
+#ifdef CONFIG_PCI
 /*
  *  PCI registration operations
  */
+static int __devinit tgafb_pci_register(struct pci_dev *,
+                                       const struct pci_device_id *);
+static void __devexit tgafb_pci_unregister(struct pci_dev *);
 
 static struct pci_device_id const tgafb_pci_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
@@ -75,13 +103,68 @@ static struct pci_device_id const tgafb_pci_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
 
-static struct pci_driver tgafb_driver = {
+static struct pci_driver tgafb_pci_driver = {
        .name                   = "tgafb",
        .id_table               = tgafb_pci_table,
        .probe                  = tgafb_pci_register,
        .remove                 = __devexit_p(tgafb_pci_unregister),
 };
 
+static int __devinit
+tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       return tgafb_register(&pdev->dev);
+}
+
+static void __devexit
+tgafb_pci_unregister(struct pci_dev *pdev)
+{
+       tgafb_unregister(&pdev->dev);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_TC
+/*
+ *  TC registration operations
+ */
+static int __devinit tgafb_tc_register(struct device *);
+static int __devexit tgafb_tc_unregister(struct device *);
+
+static struct tc_device_id const tgafb_tc_table[] = {
+       { "DEC     ", "PMAGD-AA" },
+       { "DEC     ", "PMAGD   " },
+       { }
+};
+MODULE_DEVICE_TABLE(tc, tgafb_tc_table);
+
+static struct tc_driver tgafb_tc_driver = {
+       .id_table               = tgafb_tc_table,
+       .driver                 = {
+               .name           = "tgafb",
+               .bus            = &tc_bus_type,
+               .probe          = tgafb_tc_register,
+               .remove         = __devexit_p(tgafb_tc_unregister),
+       },
+};
+
+static int __devinit
+tgafb_tc_register(struct device *dev)
+{
+       int status = tgafb_register(dev);
+       if (!status)
+               get_device(dev);
+       return status;
+}
+
+static int __devexit
+tgafb_tc_unregister(struct device *dev)
+{
+       put_device(dev);
+       tgafb_unregister(dev);
+       return 0;
+}
+#endif /* CONFIG_TC */
+
 
 /**
  *      tgafb_check_var - Optional function.  Validates a var passed in.
@@ -132,10 +215,10 @@ static int
 tgafb_set_par(struct fb_info *info)
 {
        static unsigned int const deep_presets[4] = {
-               0x00014000,
-               0x0001440d,
+               0x00004000,
+               0x0000440d,
                0xffffffff,
-               0x0001441d
+               0x0000441d
        };
        static unsigned int const rasterop_presets[4] = {
                0x00000003,
@@ -157,6 +240,8 @@ tgafb_set_par(struct fb_info *info)
        };
 
        struct tga_par *par = (struct tga_par *) info->par;
+       int tga_bus_pci = TGA_BUS_PCI(par->dev);
+       int tga_bus_tc = TGA_BUS_TC(par->dev);
        u32 htimings, vtimings, pll_freq;
        u8 tga_type;
        int i;
@@ -221,7 +306,7 @@ tgafb_set_par(struct fb_info *info)
        TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
 
        /* Initalise RAMDAC. */
-       if (tga_type == TGA_TYPE_8PLANE) {
+       if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
 
                /* Init BT485 RAMDAC registers.  */
                BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
@@ -236,21 +321,7 @@ tgafb_set_par(struct fb_info *info)
                BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
                TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
 
-#ifdef CONFIG_HW_CONSOLE
-               for (i = 0; i < 16; i++) {
-                       int j = color_table[i];
-
-                       TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-               }
-               for (i = 0; i < 240 * 3; i += 4) {
-#else
                for (i = 0; i < 256 * 3; i += 4) {
-#endif
                        TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
                                      TGA_RAMDAC_REG);
                        TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
@@ -261,6 +332,27 @@ tgafb_set_par(struct fb_info *info)
                                      TGA_RAMDAC_REG);
                }
 
+       } else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
+
+               /* Init BT459 RAMDAC registers.  */
+               BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40);
+               BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00);
+               BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2,
+                           (par->sync_on_green ? 0xc0 : 0x40));
+
+               BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00);
+
+               /* Fill the palette.  */
+               BT459_LOAD_ADDR(par, 0x0000);
+               TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+
+               for (i = 0; i < 256 * 3; i += 4) {
+                       TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
+                       TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+                       TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+                       TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+               }
+
        } else { /* 24-plane or 24plusZ */
 
                /* Init BT463 RAMDAC registers.  */
@@ -431,6 +523,8 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
                unsigned transp, struct fb_info *info)
 {
        struct tga_par *par = (struct tga_par *) info->par;
+       int tga_bus_pci = TGA_BUS_PCI(par->dev);
+       int tga_bus_tc = TGA_BUS_TC(par->dev);
 
        if (regno > 255)
                return 1;
@@ -438,12 +532,18 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
        green >>= 8;
        blue >>= 8;
 
-       if (par->tga_type == TGA_TYPE_8PLANE) {
+       if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
                BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
                TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
                TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
                TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
                TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+       } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
+               BT459_LOAD_ADDR(par, regno);
+               TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+               TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
+               TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
+               TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
        } else {
                if (regno < 16) {
                        u32 value = (regno << 16) | (regno << 8) | regno;
@@ -523,16 +623,8 @@ tgafb_blank(int blank, struct fb_info *info)
  *  Acceleration.
  */
 
-/**
- *      tgafb_imageblit - REQUIRED function. Can use generic routines if
- *                        non acclerated hardware and packed pixel based.
- *                        Copies a image from system memory to the screen. 
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @image: structure defining the image.
- */
 static void
-tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct tga_par *par = (struct tga_par *) info->par;
        u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
@@ -542,6 +634,17 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
        void __iomem *regs_base;
        void __iomem *fb_base;
 
+       is8bpp = info->var.bits_per_pixel == 8;
+
+       /* For copies that aren't pixel expansion, there's little we
+          can do better than the generic code.  */
+       /* ??? There is a DMA write mode; I wonder if that could be
+          made to pull the data from the image buffer...  */
+       if (image->depth > 1) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
        dx = image->dx;
        dy = image->dy;
        width = image->width;
@@ -559,18 +662,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
        if (dy + height > vyres)
                height = vyres - dy;
 
-       /* For copies that aren't pixel expansion, there's little we
-          can do better than the generic code.  */
-       /* ??? There is a DMA write mode; I wonder if that could be
-          made to pull the data from the image buffer...  */
-       if (image->depth > 1) {
-               cfb_imageblit(info, image);
-               return;
-       }
-
        regs_base = par->tga_regs_base;
        fb_base = par->tga_fb_base;
-       is8bpp = info->var.bits_per_pixel == 8;
 
        /* Expand the color values to fill 32-bits.  */
        /* ??? Would be nice to notice colour changes elsewhere, so
@@ -748,6 +841,85 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                     regs_base + TGA_MODE_REG);
 }
 
+static void
+tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct tga_par *par = (struct tga_par *) info->par;
+       u32 color, dx, dy, width, height, vxres, vyres;
+       u32 *palette = ((u32 *)info->pseudo_palette);
+       unsigned long pos, line_length, i, j;
+       const unsigned char *data;
+       void *regs_base, *fb_base;
+
+       dx = image->dx;
+       dy = image->dy;
+       width = image->width;
+       height = image->height;
+       vxres = info->var.xres_virtual;
+       vyres = info->var.yres_virtual;
+       line_length = info->fix.line_length;
+
+       /* Crop the image to the screen.  */
+       if (dx > vxres || dy > vyres)
+               return;
+       if (dx + width > vxres)
+               width = vxres - dx;
+       if (dy + height > vyres)
+               height = vyres - dy;
+
+       regs_base = par->tga_regs_base;
+       fb_base = par->tga_fb_base;
+
+       pos = dy * line_length + (dx * 4);
+       data = image->data;
+
+       /* Now copy the image, color_expanding via the palette. */
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j++) {
+                       color = palette[*data++];
+                       __raw_writel(color, fb_base + pos + j*4);
+               }
+               pos += line_length;
+       }
+}
+
+/**
+ *      tgafb_imageblit - REQUIRED function. Can use generic routines if
+ *                        non acclerated hardware and packed pixel based.
+ *                        Copies a image from system memory to the screen.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @image: structure defining the image.
+ */
+static void
+tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       unsigned int is8bpp = info->var.bits_per_pixel == 8;
+
+       /* If a mono image, regardless of FB depth, go do it. */
+       if (image->depth == 1) {
+               tgafb_mono_imageblit(info, image);
+               return;
+       }
+
+       /* For copies that aren't pixel expansion, there's little we
+          can do better than the generic code.  */
+       /* ??? There is a DMA write mode; I wonder if that could be
+          made to pull the data from the image buffer...  */
+       if (image->depth == info->var.bits_per_pixel) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
+       /* If 24-plane FB and the image is 8-plane with CLUT, we can do it. */
+       if (!is8bpp && image->depth == 8) {
+               tgafb_clut_imageblit(info, image);
+               return;
+       }
+
+       /* Silently return... */
+}
+
 /**
  *      tgafb_fillrect - REQUIRED function. Can use generic routines if 
  *                       non acclerated hardware and packed pixel based.
@@ -1309,18 +1481,29 @@ static void
 tgafb_init_fix(struct fb_info *info)
 {
        struct tga_par *par = (struct tga_par *)info->par;
+       int tga_bus_pci = TGA_BUS_PCI(par->dev);
+       int tga_bus_tc = TGA_BUS_TC(par->dev);
        u8 tga_type = par->tga_type;
-       const char *tga_type_name;
+       const char *tga_type_name = NULL;
 
        switch (tga_type) {
        case TGA_TYPE_8PLANE:
-               tga_type_name = "Digital ZLXp-E1";
+               if (tga_bus_pci)
+                       tga_type_name = "Digital ZLXp-E1";
+               if (tga_bus_tc)
+                       tga_type_name = "Digital ZLX-E1";
                break;
        case TGA_TYPE_24PLANE:
-               tga_type_name = "Digital ZLXp-E2";
+               if (tga_bus_pci)
+                       tga_type_name = "Digital ZLXp-E2";
+               if (tga_bus_tc)
+                       tga_type_name = "Digital ZLX-E2";
                break;
        case TGA_TYPE_24PLUSZ:
-               tga_type_name = "Digital ZLXp-E3";
+               if (tga_bus_pci)
+                       tga_type_name = "Digital ZLXp-E3";
+               if (tga_bus_tc)
+                       tga_type_name = "Digital ZLX-E3";
                break;
        default:
                tga_type_name = "Unknown";
@@ -1346,11 +1529,37 @@ tgafb_init_fix(struct fb_info *info)
        info->fix.ywrapstep = 0;
 
        info->fix.accel = FB_ACCEL_DEC_TGA;
+
+       /*
+        * These are needed by fb_set_logo_truepalette(), so we
+        * set them here for 24-plane cards.
+        */
+       if (tga_type != TGA_TYPE_8PLANE) {
+               info->var.red.length = 8;
+               info->var.green.length = 8;
+               info->var.blue.length = 8;
+               info->var.red.offset = 16;
+               info->var.green.offset = 8;
+               info->var.blue.offset = 0;
+       }
 }
 
-static __devinit int
-tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       /* We just use this to catch switches out of graphics mode. */
+       tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */
+       return 0;
+}
+
+static int __devinit
+tgafb_register(struct device *dev)
 {
+       static const struct fb_videomode modedb_tc = {
+               /* 1280x1024 @ 72 Hz, 76.8 kHz hsync */
+               "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
+               FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED
+       };
+
        static unsigned int const fb_offset_presets[4] = {
                TGA_8PLANE_FB_OFFSET,
                TGA_24PLANE_FB_OFFSET,
@@ -1358,40 +1567,51 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                TGA_24PLUSZ_FB_OFFSET
        };
 
+       const struct fb_videomode *modedb_tga = NULL;
+       resource_size_t bar0_start = 0, bar0_len = 0;
+       const char *mode_option_tga = NULL;
+       int tga_bus_pci = TGA_BUS_PCI(dev);
+       int tga_bus_tc = TGA_BUS_TC(dev);
+       unsigned int modedbsize_tga = 0;
        void __iomem *mem_base;
-       unsigned long bar0_start, bar0_len;
        struct fb_info *info;
        struct tga_par *par;
        u8 tga_type;
-       int ret;
+       int ret = 0;
 
        /* Enable device in PCI config.  */
-       if (pci_enable_device(pdev)) {
+       if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {
                printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
                return -ENODEV;
        }
 
        /* Allocate the fb and par structures.  */
-       info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev);
+       info = framebuffer_alloc(sizeof(struct tga_par), dev);
        if (!info) {
                printk(KERN_ERR "tgafb: Cannot allocate memory\n");
                return -ENOMEM;
        }
 
        par = info->par;
-       pci_set_drvdata(pdev, info);
+       dev_set_drvdata(dev, info);
 
        /* Request the mem regions.  */
-       bar0_start = pci_resource_start(pdev, 0);
-       bar0_len = pci_resource_len(pdev, 0);
        ret = -ENODEV;
+       if (tga_bus_pci) {
+               bar0_start = pci_resource_start(to_pci_dev(dev), 0);
+               bar0_len = pci_resource_len(to_pci_dev(dev), 0);
+       }
+       if (tga_bus_tc) {
+               bar0_start = to_tc_dev(dev)->resource.start;
+               bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
+       }
        if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
                printk(KERN_ERR "tgafb: cannot reserve FB region\n");
                goto err0;
        }
 
        /* Map the framebuffer.  */
-       mem_base = ioremap(bar0_start, bar0_len);
+       mem_base = ioremap_nocache(bar0_start, bar0_len);
        if (!mem_base) {
                printk(KERN_ERR "tgafb: Cannot map MMIO\n");
                goto err1;
@@ -1399,12 +1619,16 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* Grab info about the card.  */
        tga_type = (readl(mem_base) >> 12) & 0x0f;
-       par->pdev = pdev;
+       par->dev = dev;
        par->tga_mem_base = mem_base;
        par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
        par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
        par->tga_type = tga_type;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev);
+       if (tga_bus_pci)
+               pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID,
+                                    &par->tga_chip_rev);
+       if (tga_bus_tc)
+               par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
 
        /* Setup framebuffer.  */
        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
@@ -1414,8 +1638,17 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        info->pseudo_palette = (void *)(par + 1);
 
        /* This should give a reasonable default video mode.  */
-
-       ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL,
+       if (tga_bus_pci) {
+               mode_option_tga = mode_option_pci;
+       }
+       if (tga_bus_tc) {
+               mode_option_tga = mode_option_tc;
+               modedb_tga = &modedb_tc;
+               modedbsize_tga = 1;
+       }
+       ret = fb_find_mode(&info->var, info,
+                          mode_option ? mode_option : mode_option_tga,
+                          modedb_tga, modedbsize_tga, NULL,
                           tga_type == TGA_TYPE_8PLANE ? 8 : 32);
        if (ret == 0 || ret == 4) {
                printk(KERN_ERR "tgafb: Could not find valid video mode\n");
@@ -1438,13 +1671,19 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err1;
        }
 
-       printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
-              par->tga_chip_rev);
-       printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
-              pdev->bus->number, PCI_SLOT(pdev->devfn),
-              PCI_FUNC(pdev->devfn));
-       printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
-              info->node, info->fix.id, bar0_start);
+       if (tga_bus_pci) {
+               pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
+                       par->tga_chip_rev);
+               pr_info("tgafb: at PCI bus %d, device %d, function %d\n",
+                       to_pci_dev(dev)->bus->number,
+                       PCI_SLOT(to_pci_dev(dev)->devfn),
+                       PCI_FUNC(to_pci_dev(dev)->devfn));
+       }
+       if (tga_bus_tc)
+               pr_info("tgafb: SFB+ detected, rev=0x%02x\n",
+                       par->tga_chip_rev);
+       pr_info("fb%d: %s frame buffer device at 0x%lx\n",
+               info->node, info->fix.id, (long)bar0_start);
 
        return 0;
 
@@ -1458,25 +1697,39 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 }
 
 static void __devexit
-tgafb_pci_unregister(struct pci_dev *pdev)
+tgafb_unregister(struct device *dev)
 {
-       struct fb_info *info = pci_get_drvdata(pdev);
-       struct tga_par *par = info->par;
+       resource_size_t bar0_start = 0, bar0_len = 0;
+       int tga_bus_pci = TGA_BUS_PCI(dev);
+       int tga_bus_tc = TGA_BUS_TC(dev);
+       struct fb_info *info = NULL;
+       struct tga_par *par;
 
+       info = dev_get_drvdata(dev);
        if (!info)
                return;
+
+       par = info->par;
        unregister_framebuffer(info);
        fb_dealloc_cmap(&info->cmap);
        iounmap(par->tga_mem_base);
-       release_mem_region(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0));
+       if (tga_bus_pci) {
+               bar0_start = pci_resource_start(to_pci_dev(dev), 0);
+               bar0_len = pci_resource_len(to_pci_dev(dev), 0);
+       }
+       if (tga_bus_tc) {
+               bar0_start = to_tc_dev(dev)->resource.start;
+               bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
+       }
+       release_mem_region(bar0_start, bar0_len);
        framebuffer_release(info);
 }
 
 static void __devexit
 tgafb_exit(void)
 {
-       pci_unregister_driver(&tgafb_driver);
+       tc_unregister_driver(&tgafb_tc_driver);
+       pci_unregister_driver(&tgafb_pci_driver);
 }
 
 #ifndef MODULE
@@ -1505,6 +1758,7 @@ tgafb_setup(char *arg)
 static int __devinit
 tgafb_init(void)
 {
+       int status;
 #ifndef MODULE
        char *option = NULL;
 
@@ -1512,7 +1766,10 @@ tgafb_init(void)
                return -ENODEV;
        tgafb_setup(option);
 #endif
-       return pci_register_driver(&tgafb_driver);
+       status = pci_register_driver(&tgafb_pci_driver);
+       if (!status)
+               status = tc_register_driver(&tgafb_tc_driver);
+       return status;
 }
 
 /*
@@ -1522,5 +1779,5 @@ tgafb_init(void)
 module_init(tgafb_init);
 module_exit(tgafb_exit);
 
-MODULE_DESCRIPTION("framebuffer driver for TGA chipset");
+MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/vermilion/Makefile b/drivers/video/vermilion/Makefile
new file mode 100644 (file)
index 0000000..cc21a65
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_FB_LE80578) += vmlfb.o
+obj-$(CONFIG_FB_CARILLO_RANCH) += crvml.o
+
+vmlfb-objs := vermilion.o
+crvml-objs := cr_pll.o
diff --git a/drivers/video/vermilion/cr_pll.c b/drivers/video/vermilion/cr_pll.c
new file mode 100644 (file)
index 0000000..ebc6e6e
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Carillo Ranch video subsystem driver.
+ * The Carillo Ranch video subsystem driver 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.
+ *
+ * The Carillo Ranch video subsystem driver 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 driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include "vermilion.h"
+
+/* The PLL Clock register sits on Host bridge */
+#define CRVML_DEVICE_MCH   0x5001
+#define CRVML_REG_MCHBAR   0x44
+#define CRVML_REG_MCHEN    0x54
+#define CRVML_MCHEN_BIT    (1 << 28)
+#define CRVML_MCHMAP_SIZE  4096
+#define CRVML_REG_CLOCK    0xc3c
+#define CRVML_CLOCK_SHIFT  8
+#define CRVML_CLOCK_MASK   0x00000f00
+
+static struct pci_dev *mch_dev;
+static u32 mch_bar;
+static void __iomem *mch_regs_base;
+static u32 saved_clock;
+
+static const unsigned crvml_clocks[] = {
+       6750,
+       13500,
+       27000,
+       29700,
+       37125,
+       54000,
+       59400,
+       74250,
+       120000
+           /*
+            * There are more clocks, but they are disabled on the CR board.
+            */
+};
+
+static const u32 crvml_clock_bits[] = {
+       0x0a,
+       0x09,
+       0x08,
+       0x07,
+       0x06,
+       0x05,
+       0x04,
+       0x03,
+       0x0b
+};
+
+static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
+
+static int crvml_sys_restore(struct vml_sys *sys)
+{
+       void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+
+       iowrite32(saved_clock, clock_reg);
+       ioread32(clock_reg);
+
+       return 0;
+}
+
+static int crvml_sys_save(struct vml_sys *sys)
+{
+       void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+
+       saved_clock = ioread32(clock_reg);
+
+       return 0;
+}
+
+static int crvml_nearest_index(const struct vml_sys *sys, int clock)
+{
+       int i;
+       int cur_index = 0;
+       int cur_diff;
+       int diff;
+
+       cur_diff = clock - crvml_clocks[0];
+       cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
+       for (i = 1; i < crvml_num_clocks; ++i) {
+               diff = clock - crvml_clocks[i];
+               diff = (diff < 0) ? -diff : diff;
+               if (diff < cur_diff) {
+                       cur_index = i;
+                       cur_diff = diff;
+               }
+       }
+       return cur_index;
+}
+
+static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
+{
+       return crvml_clocks[crvml_nearest_index(sys, clock)];
+}
+
+static int crvml_set_clock(struct vml_sys *sys, int clock)
+{
+       void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+       int index;
+       u32 clock_val;
+
+       index = crvml_nearest_index(sys, clock);
+
+       if (crvml_clocks[index] != clock)
+               return -EINVAL;
+
+       clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
+       clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
+       iowrite32(clock_val, clock_reg);
+       ioread32(clock_reg);
+
+       return 0;
+}
+
+static struct vml_sys cr_pll_ops = {
+       .name = "Carillo Ranch",
+       .save = crvml_sys_save,
+       .restore = crvml_sys_restore,
+       .set_clock = crvml_set_clock,
+       .nearest_clock = crvml_nearest_clock,
+};
+
+static int __init cr_pll_init(void)
+{
+       int err;
+       u32 dev_en;
+
+       mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                       CRVML_DEVICE_MCH, NULL);
+       if (!mch_dev) {
+               printk(KERN_ERR
+                      "Could not find Carillo Ranch MCH device.\n");
+               return -ENODEV;
+       }
+
+       pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
+       if (!(dev_en & CRVML_MCHEN_BIT)) {
+               printk(KERN_ERR
+                      "Carillo Ranch MCH device was not enabled.\n");
+               pci_dev_put(mch_dev);
+               return -ENODEV;
+       }
+
+       pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
+                             &mch_bar);
+       mch_regs_base =
+           ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
+       if (!mch_regs_base) {
+               printk(KERN_ERR
+                      "Carillo Ranch MCH device was not enabled.\n");
+               pci_dev_put(mch_dev);
+               return -ENODEV;
+       }
+
+       err = vmlfb_register_subsys(&cr_pll_ops);
+       if (err) {
+               printk(KERN_ERR
+                      "Carillo Ranch failed to initialize vml_sys.\n");
+               pci_dev_put(mch_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+static void __exit cr_pll_exit(void)
+{
+       vmlfb_unregister_subsys(&cr_pll_ops);
+
+       iounmap(mch_regs_base);
+       pci_dev_put(mch_dev);
+}
+
+module_init(cr_pll_init);
+module_exit(cr_pll_exit);
+
+MODULE_AUTHOR("Tungsten Graphics Inc.");
+MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
new file mode 100644 (file)
index 0000000..de531c9
--- /dev/null
@@ -0,0 +1,1195 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Vermilion Range fb driver.
+ * The Vermilion Range fb driver 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.
+ *
+ * The Vermilion Range fb driver 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 driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *   Michel Dänzer <michel-at-tungstengraphics-dot-com>
+ *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <linux/mmzone.h>
+#include <asm/uaccess.h>
+
+/* #define VERMILION_DEBUG */
+
+#include "vermilion.h"
+
+#define MODULE_NAME "vmlfb"
+
+#define VML_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+static struct mutex vml_mutex;
+static struct list_head global_no_mode;
+static struct list_head global_has_mode;
+static struct fb_ops vmlfb_ops;
+static struct vml_sys *subsys = NULL;
+static char *vml_default_mode = "1024x768@60";
+static struct fb_videomode defaultmode = {
+       NULL, 60, 1024, 768, 12896, 144, 24, 29, 3, 136, 6,
+       0, FB_VMODE_NONINTERLACED
+};
+
+static u32 vml_mem_requested = (10 * 1024 * 1024);
+static u32 vml_mem_contig = (4 * 1024 * 1024);
+static u32 vml_mem_min = (4 * 1024 * 1024);
+
+static u32 vml_clocks[] = {
+       6750,
+       13500,
+       27000,
+       29700,
+       37125,
+       54000,
+       59400,
+       74250,
+       120000,
+       148500
+};
+
+static u32 vml_num_clocks = ARRAY_SIZE(vml_clocks);
+
+/*
+ * Allocate a contiguous vram area and make its linear kernel map
+ * uncached.
+ */
+
+static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order,
+                                unsigned min_order)
+{
+       gfp_t flags;
+       unsigned long i;
+       pgprot_t wc_pageprot;
+
+       wc_pageprot = PAGE_KERNEL_NOCACHE;
+       max_order++;
+       do {
+               /*
+                * Really try hard to get the needed memory.
+                * We need memory below the first 32MB, so we
+                * add the __GFP_DMA flag that guarantees that we are
+                * below the first 16MB.
+                */
+
+               flags = __GFP_DMA | __GFP_HIGH;
+               va->logical =
+                        __get_free_pages(flags, --max_order);
+       } while (va->logical == 0 && max_order > min_order);
+
+       if (!va->logical)
+               return -ENOMEM;
+
+       va->phys = virt_to_phys((void *)va->logical);
+       va->size = PAGE_SIZE << max_order;
+       va->order = max_order;
+
+       /*
+        * It seems like __get_free_pages only ups the usage count
+        * of the first page. This doesn't work with nopage mapping, so
+        * up the usage count once more.
+        */
+
+       memset((void *)va->logical, 0x00, va->size);
+       for (i = va->logical; i < va->logical + va->size; i += PAGE_SIZE) {
+               get_page(virt_to_page(i));
+       }
+
+       /*
+        * Change caching policy of the linear kernel map to avoid
+        * mapping type conflicts with user-space mappings.
+        * The first global_flush_tlb() is really only there to do a global
+        * wbinvd().
+        */
+
+       global_flush_tlb();
+       change_page_attr(virt_to_page(va->logical), va->size >> PAGE_SHIFT,
+                        wc_pageprot);
+       global_flush_tlb();
+
+       printk(KERN_DEBUG MODULE_NAME
+              ": Allocated %ld bytes vram area at 0x%08lx\n",
+              va->size, va->phys);
+
+       return 0;
+}
+
+/*
+ * Free a contiguous vram area and reset its linear kernel map
+ * mapping type.
+ */
+
+static void vmlfb_free_vram_area(struct vram_area *va)
+{
+       unsigned long j;
+
+       if (va->logical) {
+
+               /*
+                * Reset the linear kernel map caching policy.
+                */
+
+               change_page_attr(virt_to_page(va->logical),
+                                va->size >> PAGE_SHIFT, PAGE_KERNEL);
+               global_flush_tlb();
+
+               /*
+                * Decrease the usage count on the pages we've used
+                * to compensate for upping when allocating.
+                */
+
+               for (j = va->logical; j < va->logical + va->size;
+                    j += PAGE_SIZE) {
+                       (void)put_page_testzero(virt_to_page(j));
+               }
+
+               printk(KERN_DEBUG MODULE_NAME
+                      ": Freeing %ld bytes vram area at 0x%08lx\n",
+                      va->size, va->phys);
+               free_pages(va->logical, va->order);
+
+               va->logical = 0;
+       }
+}
+
+/*
+ * Free allocated vram.
+ */
+
+static void vmlfb_free_vram(struct vml_info *vinfo)
+{
+       int i;
+
+       for (i = 0; i < vinfo->num_areas; ++i) {
+               vmlfb_free_vram_area(&vinfo->vram[i]);
+       }
+       vinfo->num_areas = 0;
+}
+
+/*
+ * Allocate vram. Currently we try to allocate contiguous areas from the
+ * __GFP_DMA zone and puzzle them together. A better approach would be to
+ * allocate one contiguous area for scanout and use one-page allocations for
+ * offscreen areas. This requires user-space and GPU virtual mappings.
+ */
+
+static int vmlfb_alloc_vram(struct vml_info *vinfo,
+                           size_t requested,
+                           size_t min_total, size_t min_contig)
+{
+       int i, j;
+       int order;
+       int contiguous;
+       int err;
+       struct vram_area *va;
+       struct vram_area *va2;
+
+       vinfo->num_areas = 0;
+       for (i = 0; i < VML_VRAM_AREAS; ++i) {
+               va = &vinfo->vram[i];
+               order = 0;
+
+               while (requested > (PAGE_SIZE << order) && order < MAX_ORDER)
+                       order++;
+
+               err = vmlfb_alloc_vram_area(va, order, 0);
+
+               if (err)
+                       break;
+
+               if (i == 0) {
+                       vinfo->vram_start = va->phys;
+                       vinfo->vram_logical = (void __iomem *) va->logical;
+                       vinfo->vram_contig_size = va->size;
+                       vinfo->num_areas = 1;
+               } else {
+                       contiguous = 0;
+
+                       for (j = 0; j < i; ++j) {
+                               va2 = &vinfo->vram[j];
+                               if (va->phys + va->size == va2->phys ||
+                                   va2->phys + va2->size == va->phys) {
+                                       contiguous = 1;
+                                       break;
+                               }
+                       }
+
+                       if (contiguous) {
+                               vinfo->num_areas++;
+                               if (va->phys < vinfo->vram_start) {
+                                       vinfo->vram_start = va->phys;
+                                       vinfo->vram_logical =
+                                               (void __iomem *)va->logical;
+                               }
+                               vinfo->vram_contig_size += va->size;
+                       } else {
+                               vmlfb_free_vram_area(va);
+                               break;
+                       }
+               }
+
+               if (requested < va->size)
+                       break;
+               else
+                       requested -= va->size;
+       }
+
+       if (vinfo->vram_contig_size > min_total &&
+           vinfo->vram_contig_size > min_contig) {
+
+               printk(KERN_DEBUG MODULE_NAME
+                      ": Contiguous vram: %ld bytes at physical 0x%08lx.\n",
+                      (unsigned long)vinfo->vram_contig_size,
+                      (unsigned long)vinfo->vram_start);
+
+               return 0;
+       }
+
+       printk(KERN_ERR MODULE_NAME
+              ": Could not allocate requested minimal amount of vram.\n");
+
+       vmlfb_free_vram(vinfo);
+
+       return -ENOMEM;
+}
+
+/*
+ * Find the GPU to use with our display controller.
+ */
+
+static int vmlfb_get_gpu(struct vml_par *par)
+{
+       mutex_lock(&vml_mutex);
+
+       par->gpu = pci_get_device(PCI_VENDOR_ID_INTEL, VML_DEVICE_GPU, NULL);
+
+       if (!par->gpu) {
+               mutex_unlock(&vml_mutex);
+               return -ENODEV;
+       }
+
+       mutex_unlock(&vml_mutex);
+
+       if (pci_enable_device(par->gpu) < 0)
+               return -ENODEV;
+
+       return 0;
+}
+
+/*
+ * Find a contiguous vram area that contains a given offset from vram start.
+ */
+static int vmlfb_vram_offset(struct vml_info *vinfo, unsigned long offset)
+{
+       unsigned long aoffset;
+       unsigned i;
+
+       for (i = 0; i < vinfo->num_areas; ++i) {
+               aoffset = offset - (vinfo->vram[i].phys - vinfo->vram_start);
+
+               if (aoffset < vinfo->vram[i].size) {
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * Remap the MMIO register spaces of the VDC and the GPU.
+ */
+
+static int vmlfb_enable_mmio(struct vml_par *par)
+{
+       int err;
+
+       par->vdc_mem_base = pci_resource_start(par->vdc, 0);
+       par->vdc_mem_size = pci_resource_len(par->vdc, 0);
+       if (!request_mem_region(par->vdc_mem_base, par->vdc_mem_size, "vmlfb")) {
+               printk(KERN_ERR MODULE_NAME
+                      ": Could not claim display controller MMIO.\n");
+               return -EBUSY;
+       }
+       par->vdc_mem = ioremap_nocache(par->vdc_mem_base, par->vdc_mem_size);
+       if (par->vdc_mem == NULL) {
+               printk(KERN_ERR MODULE_NAME
+                      ": Could not map display controller MMIO.\n");
+               err = -ENOMEM;
+               goto out_err_0;
+       }
+
+       par->gpu_mem_base = pci_resource_start(par->gpu, 0);
+       par->gpu_mem_size = pci_resource_len(par->gpu, 0);
+       if (!request_mem_region(par->gpu_mem_base, par->gpu_mem_size, "vmlfb")) {
+               printk(KERN_ERR MODULE_NAME ": Could not claim GPU MMIO.\n");
+               err = -EBUSY;
+               goto out_err_1;
+       }
+       par->gpu_mem = ioremap_nocache(par->gpu_mem_base, par->gpu_mem_size);
+       if (par->gpu_mem == NULL) {
+               printk(KERN_ERR MODULE_NAME ": Could not map GPU MMIO.\n");
+               err = -ENOMEM;
+               goto out_err_2;
+       }
+
+       return 0;
+
+out_err_2:
+       release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
+out_err_1:
+       iounmap(par->vdc_mem);
+out_err_0:
+       release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
+       return err;
+}
+
+/*
+ * Unmap the VDC and GPU register spaces.
+ */
+
+static void vmlfb_disable_mmio(struct vml_par *par)
+{
+       iounmap(par->gpu_mem);
+       release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
+       iounmap(par->vdc_mem);
+       release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
+}
+
+/*
+ * Release and uninit the VDC and GPU.
+ */
+
+static void vmlfb_release_devices(struct vml_par *par)
+{
+       if (atomic_dec_and_test(&par->refcount)) {
+               pci_set_drvdata(par->vdc, NULL);
+               pci_disable_device(par->gpu);
+               pci_disable_device(par->vdc);
+       }
+}
+
+/*
+ * Free up allocated resources for a device.
+ */
+
+static void __devexit vml_pci_remove(struct pci_dev *dev)
+{
+       struct fb_info *info;
+       struct vml_info *vinfo;
+       struct vml_par *par;
+
+       info = pci_get_drvdata(dev);
+       if (info) {
+               vinfo = container_of(info, struct vml_info, info);
+               par = vinfo->par;
+               mutex_lock(&vml_mutex);
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+               vmlfb_free_vram(vinfo);
+               vmlfb_disable_mmio(par);
+               vmlfb_release_devices(par);
+               kfree(vinfo);
+               kfree(par);
+               mutex_unlock(&vml_mutex);
+       }
+}
+
+static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo *var)
+{
+       switch (var->bits_per_pixel) {
+       case 16:
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->green.offset = 5;
+               var->green.length = 5;
+               var->red.offset = 10;
+               var->red.length = 5;
+               var->transp.offset = 15;
+               var->transp.length = 1;
+               break;
+       case 32:
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->transp.offset = 24;
+               var->transp.length = 0;
+               break;
+       default:
+               break;
+       }
+
+       var->blue.msb_right = var->green.msb_right =
+           var->red.msb_right = var->transp.msb_right = 0;
+}
+
+/*
+ * Device initialization.
+ * We initialize one vml_par struct per device and one vml_info
+ * struct per pipe. Currently we have only one pipe.
+ */
+
+static int __devinit vml_pci_probe(struct pci_dev *dev,
+                                  const struct pci_device_id *id)
+{
+       struct vml_info *vinfo;
+       struct fb_info *info;
+       struct vml_par *par;
+       int err = 0;
+
+       par = kzalloc(sizeof(*par), GFP_KERNEL);
+       if (par == NULL)
+               return -ENOMEM;
+
+       vinfo = kzalloc(sizeof(*vinfo), GFP_KERNEL);
+       if (vinfo == NULL) {
+               err = -ENOMEM;
+               goto out_err_0;
+       }
+
+       vinfo->par = par;
+       par->vdc = dev;
+       atomic_set(&par->refcount, 1);
+
+       switch (id->device) {
+       case VML_DEVICE_VDC:
+               if ((err = vmlfb_get_gpu(par)))
+                       goto out_err_1;
+               pci_set_drvdata(dev, &vinfo->info);
+               break;
+       default:
+               err = -ENODEV;
+               goto out_err_1;
+               break;
+       }
+
+       info = &vinfo->info;
+       info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK;
+
+       err = vmlfb_enable_mmio(par);
+       if (err)
+               goto out_err_2;
+
+       err = vmlfb_alloc_vram(vinfo, vml_mem_requested,
+                              vml_mem_contig, vml_mem_min);
+       if (err)
+               goto out_err_3;
+
+       strcpy(info->fix.id, "Vermilion Range");
+       info->fix.mmio_start = 0;
+       info->fix.mmio_len = 0;
+       info->fix.smem_start = vinfo->vram_start;
+       info->fix.smem_len = vinfo->vram_contig_size;
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_TRUECOLOR;
+       info->fix.ypanstep = 1;
+       info->fix.xpanstep = 1;
+       info->fix.ywrapstep = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+       info->screen_base = vinfo->vram_logical;
+       info->pseudo_palette = vinfo->pseudo_palette;
+       info->par = par;
+       info->fbops = &vmlfb_ops;
+       info->device = &dev->dev;
+
+       INIT_LIST_HEAD(&vinfo->head);
+       vinfo->pipe_disabled = 1;
+       vinfo->cur_blank_mode = FB_BLANK_UNBLANK;
+
+       info->var.grayscale = 0;
+       info->var.bits_per_pixel = 16;
+       vmlfb_set_pref_pixel_format(&info->var);
+
+       if (!fb_find_mode
+           (&info->var, info, vml_default_mode, NULL, 0, &defaultmode, 16)) {
+               printk(KERN_ERR MODULE_NAME ": Could not find initial mode\n");
+       }
+
+       if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
+               err = -ENOMEM;
+               goto out_err_4;
+       }
+
+       err = register_framebuffer(info);
+       if (err) {
+               printk(KERN_ERR MODULE_NAME ": Register framebuffer error.\n");
+               goto out_err_5;
+       }
+
+       printk("Initialized vmlfb\n");
+
+       return 0;
+
+out_err_5:
+       fb_dealloc_cmap(&info->cmap);
+out_err_4:
+       vmlfb_free_vram(vinfo);
+out_err_3:
+       vmlfb_disable_mmio(par);
+out_err_2:
+       vmlfb_release_devices(par);
+out_err_1:
+       kfree(vinfo);
+out_err_0:
+       kfree(par);
+       return err;
+}
+
+static int vmlfb_open(struct fb_info *info, int user)
+{
+       /*
+        * Save registers here?
+        */
+       return 0;
+}
+
+static int vmlfb_release(struct fb_info *info, int user)
+{
+       /*
+        * Restore registers here.
+        */
+
+       return 0;
+}
+
+static int vml_nearest_clock(int clock)
+{
+
+       int i;
+       int cur_index;
+       int cur_diff;
+       int diff;
+
+       cur_index = 0;
+       cur_diff = clock - vml_clocks[0];
+       cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
+       for (i = 1; i < vml_num_clocks; ++i) {
+               diff = clock - vml_clocks[i];
+               diff = (diff < 0) ? -diff : diff;
+               if (diff < cur_diff) {
+                       cur_index = i;
+                       cur_diff = diff;
+               }
+       }
+       return vml_clocks[cur_index];
+}
+
+static int vmlfb_check_var_locked(struct fb_var_screeninfo *var,
+                                 struct vml_info *vinfo)
+{
+       u32 pitch;
+       u64 mem;
+       int nearest_clock;
+       int clock;
+       int clock_diff;
+       struct fb_var_screeninfo v;
+
+       v = *var;
+       clock = PICOS2KHZ(var->pixclock);
+
+       if (subsys && subsys->nearest_clock) {
+               nearest_clock = subsys->nearest_clock(subsys, clock);
+       } else {
+               nearest_clock = vml_nearest_clock(clock);
+       }
+
+       /*
+        * Accept a 20% diff.
+        */
+
+       clock_diff = nearest_clock - clock;
+       clock_diff = (clock_diff < 0) ? -clock_diff : clock_diff;
+       if (clock_diff > clock / 5) {
+#if 0
+               printk(KERN_DEBUG MODULE_NAME ": Diff failure. %d %d\n",clock_diff,clock);
+#endif
+               return -EINVAL;
+       }
+
+       v.pixclock = KHZ2PICOS(nearest_clock);
+
+       if (var->xres > VML_MAX_XRES || var->yres > VML_MAX_YRES) {
+               printk(KERN_DEBUG MODULE_NAME ": Resolution failure.\n");
+               return -EINVAL;
+       }
+       if (var->xres_virtual > VML_MAX_XRES_VIRTUAL) {
+               printk(KERN_DEBUG MODULE_NAME
+                      ": Virtual resolution failure.\n");
+               return -EINVAL;
+       }
+       switch (v.bits_per_pixel) {
+       case 0 ... 16:
+               v.bits_per_pixel = 16;
+               break;
+       case 17 ... 32:
+               v.bits_per_pixel = 32;
+               break;
+       default:
+               printk(KERN_DEBUG MODULE_NAME ": Invalid bpp: %d.\n",
+                      var->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F);
+       mem = pitch * var->yres_virtual;
+       if (mem > vinfo->vram_contig_size) {
+               return -ENOMEM;
+       }
+
+       switch (v.bits_per_pixel) {
+       case 16:
+               if (var->blue.offset != 0 ||
+                   var->blue.length != 5 ||
+                   var->green.offset != 5 ||
+                   var->green.length != 5 ||
+                   var->red.offset != 10 ||
+                   var->red.length != 5 ||
+                   var->transp.offset != 15 || var->transp.length != 1) {
+                       vmlfb_set_pref_pixel_format(&v);
+               }
+               break;
+       case 32:
+               if (var->blue.offset != 0 ||
+                   var->blue.length != 8 ||
+                   var->green.offset != 8 ||
+                   var->green.length != 8 ||
+                   var->red.offset != 16 ||
+                   var->red.length != 8 ||
+                   (var->transp.length != 0 && var->transp.length != 8) ||
+                   (var->transp.length == 8 && var->transp.offset != 24)) {
+                       vmlfb_set_pref_pixel_format(&v);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       *var = v;
+
+       return 0;
+}
+
+static int vmlfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct vml_info *vinfo = container_of(info, struct vml_info, info);
+       int ret;
+
+       mutex_lock(&vml_mutex);
+       ret = vmlfb_check_var_locked(var, vinfo);
+       mutex_unlock(&vml_mutex);
+
+       return ret;
+}
+
+static void vml_wait_vblank(struct vml_info *vinfo)
+{
+       /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
+       mdelay(20);
+}
+
+static void vmlfb_disable_pipe(struct vml_info *vinfo)
+{
+       struct vml_par *par = vinfo->par;
+
+       /* Disable the MDVO pad */
+       VML_WRITE32(par, VML_RCOMPSTAT, 0);
+       while (!(VML_READ32(par, VML_RCOMPSTAT) & VML_MDVO_VDC_I_RCOMP)) ;
+
+       /* Disable display planes */
+       VML_WRITE32(par, VML_DSPCCNTR,
+                   VML_READ32(par, VML_DSPCCNTR) & ~VML_GFX_ENABLE);
+       (void)VML_READ32(par, VML_DSPCCNTR);
+       /* Wait for vblank for the disable to take effect */
+       vml_wait_vblank(vinfo);
+
+       /* Next, disable display pipes */
+       VML_WRITE32(par, VML_PIPEACONF, 0);
+       (void)VML_READ32(par, VML_PIPEACONF);
+
+       vinfo->pipe_disabled = 1;
+}
+
+#ifdef VERMILION_DEBUG
+static void vml_dump_regs(struct vml_info *vinfo)
+{
+       struct vml_par *par = vinfo->par;
+
+       printk(KERN_DEBUG MODULE_NAME ": Modesetting register dump:\n");
+       printk(KERN_DEBUG MODULE_NAME ": \tHTOTAL_A         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_HTOTAL_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tHBLANK_A         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_HBLANK_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tHSYNC_A          : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_HSYNC_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tVTOTAL_A         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_VTOTAL_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tVBLANK_A         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_VBLANK_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tVSYNC_A          : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_VSYNC_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPCSTRIDE       : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPCSTRIDE));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPCSIZE         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPCSIZE));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPCPOS          : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPCPOS));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPARB           : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPARB));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPCADDR         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPCADDR));
+       printk(KERN_DEBUG MODULE_NAME ": \tBCLRPAT_A        : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_BCLRPAT_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tCANVSCLR_A       : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_CANVSCLR_A));
+       printk(KERN_DEBUG MODULE_NAME ": \tPIPEASRC         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_PIPEASRC));
+       printk(KERN_DEBUG MODULE_NAME ": \tPIPEACONF        : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_PIPEACONF));
+       printk(KERN_DEBUG MODULE_NAME ": \tDSPCCNTR         : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_DSPCCNTR));
+       printk(KERN_DEBUG MODULE_NAME ": \tRCOMPSTAT        : 0x%08x\n",
+              (unsigned)VML_READ32(par, VML_RCOMPSTAT));
+       printk(KERN_DEBUG MODULE_NAME ": End of modesetting register dump.\n");
+}
+#endif
+
+static int vmlfb_set_par_locked(struct vml_info *vinfo)
+{
+       struct vml_par *par = vinfo->par;
+       struct fb_info *info = &vinfo->info;
+       struct fb_var_screeninfo *var = &info->var;
+       u32 htotal, hactive, hblank_start, hblank_end, hsync_start, hsync_end;
+       u32 vtotal, vactive, vblank_start, vblank_end, vsync_start, vsync_end;
+       u32 dspcntr;
+       int clock;
+
+       vinfo->bytes_per_pixel = var->bits_per_pixel >> 3;
+       vinfo->stride =
+           __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F);
+       info->fix.line_length = vinfo->stride;
+
+       if (!subsys)
+               return 0;
+
+       htotal =
+           var->xres + var->right_margin + var->hsync_len + var->left_margin;
+       hactive = var->xres;
+       hblank_start = var->xres;
+       hblank_end = htotal;
+       hsync_start = hactive + var->right_margin;
+       hsync_end = hsync_start + var->hsync_len;
+
+       vtotal =
+           var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
+       vactive = var->yres;
+       vblank_start = var->yres;
+       vblank_end = vtotal;
+       vsync_start = vactive + var->lower_margin;
+       vsync_end = vsync_start + var->vsync_len;
+
+       dspcntr = VML_GFX_ENABLE | VML_GFX_GAMMABYPASS;
+       clock = PICOS2KHZ(var->pixclock);
+
+       if (subsys->nearest_clock) {
+               clock = subsys->nearest_clock(subsys, clock);
+       } else {
+               clock = vml_nearest_clock(clock);
+       }
+       printk(KERN_DEBUG MODULE_NAME
+              ": Set mode Hfreq : %d kHz, Vfreq : %d Hz.\n", clock / htotal,
+              ((clock / htotal) * 1000) / vtotal);
+
+       switch (var->bits_per_pixel) {
+       case 16:
+               dspcntr |= VML_GFX_ARGB1555;
+               break;
+       case 32:
+               if (var->transp.length == 8)
+                       dspcntr |= VML_GFX_ARGB8888 | VML_GFX_ALPHAMULT;
+               else
+                       dspcntr |= VML_GFX_RGB0888;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       vmlfb_disable_pipe(vinfo);
+       mb();
+
+       if (subsys->set_clock)
+               subsys->set_clock(subsys, clock);
+       else
+               return -EINVAL;
+
+       VML_WRITE32(par, VML_HTOTAL_A, ((htotal - 1) << 16) | (hactive - 1));
+       VML_WRITE32(par, VML_HBLANK_A,
+                   ((hblank_end - 1) << 16) | (hblank_start - 1));
+       VML_WRITE32(par, VML_HSYNC_A,
+                   ((hsync_end - 1) << 16) | (hsync_start - 1));
+       VML_WRITE32(par, VML_VTOTAL_A, ((vtotal - 1) << 16) | (vactive - 1));
+       VML_WRITE32(par, VML_VBLANK_A,
+                   ((vblank_end - 1) << 16) | (vblank_start - 1));
+       VML_WRITE32(par, VML_VSYNC_A,
+                   ((vsync_end - 1) << 16) | (vsync_start - 1));
+       VML_WRITE32(par, VML_DSPCSTRIDE, vinfo->stride);
+       VML_WRITE32(par, VML_DSPCSIZE,
+                   ((var->yres - 1) << 16) | (var->xres - 1));
+       VML_WRITE32(par, VML_DSPCPOS, 0x00000000);
+       VML_WRITE32(par, VML_DSPARB, VML_FIFO_DEFAULT);
+       VML_WRITE32(par, VML_BCLRPAT_A, 0x00000000);
+       VML_WRITE32(par, VML_CANVSCLR_A, 0x00000000);
+       VML_WRITE32(par, VML_PIPEASRC,
+                   ((var->xres - 1) << 16) | (var->yres - 1));
+
+       wmb();
+       VML_WRITE32(par, VML_PIPEACONF, VML_PIPE_ENABLE);
+       wmb();
+       VML_WRITE32(par, VML_DSPCCNTR, dspcntr);
+       wmb();
+       VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
+                   var->yoffset * vinfo->stride +
+                   var->xoffset * vinfo->bytes_per_pixel);
+
+       VML_WRITE32(par, VML_RCOMPSTAT, VML_MDVO_PAD_ENABLE);
+
+       while (!(VML_READ32(par, VML_RCOMPSTAT) &
+                (VML_MDVO_VDC_I_RCOMP | VML_MDVO_PAD_ENABLE))) ;
+
+       vinfo->pipe_disabled = 0;
+#ifdef VERMILION_DEBUG
+       vml_dump_regs(vinfo);
+#endif
+
+       return 0;
+}
+
+static int vmlfb_set_par(struct fb_info *info)
+{
+       struct vml_info *vinfo = container_of(info, struct vml_info, info);
+       int ret;
+
+       mutex_lock(&vml_mutex);
+       list_del(&vinfo->head);
+       list_add(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode);
+       ret = vmlfb_set_par_locked(vinfo);
+
+       mutex_unlock(&vml_mutex);
+       return ret;
+}
+
+static int vmlfb_blank_locked(struct vml_info *vinfo)
+{
+       struct vml_par *par = vinfo->par;
+       u32 cur = VML_READ32(par, VML_PIPEACONF);
+
+       switch (vinfo->cur_blank_mode) {
+       case FB_BLANK_UNBLANK:
+               if (vinfo->pipe_disabled) {
+                       vmlfb_set_par_locked(vinfo);
+               }
+               VML_WRITE32(par, VML_PIPEACONF, cur & ~VML_PIPE_FORCE_BORDER);
+               (void)VML_READ32(par, VML_PIPEACONF);
+               break;
+       case FB_BLANK_NORMAL:
+               if (vinfo->pipe_disabled) {
+                       vmlfb_set_par_locked(vinfo);
+               }
+               VML_WRITE32(par, VML_PIPEACONF, cur | VML_PIPE_FORCE_BORDER);
+               (void)VML_READ32(par, VML_PIPEACONF);
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+               if (!vinfo->pipe_disabled) {
+                       vmlfb_disable_pipe(vinfo);
+               }
+               break;
+       case FB_BLANK_POWERDOWN:
+               if (!vinfo->pipe_disabled) {
+                       vmlfb_disable_pipe(vinfo);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vmlfb_blank(int blank_mode, struct fb_info *info)
+{
+       struct vml_info *vinfo = container_of(info, struct vml_info, info);
+       int ret;
+
+       mutex_lock(&vml_mutex);
+       vinfo->cur_blank_mode = blank_mode;
+       ret = vmlfb_blank_locked(vinfo);
+       mutex_unlock(&vml_mutex);
+       return ret;
+}
+
+static int vmlfb_pan_display(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+       struct vml_info *vinfo = container_of(info, struct vml_info, info);
+       struct vml_par *par = vinfo->par;
+
+       mutex_lock(&vml_mutex);
+       VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
+                   var->yoffset * vinfo->stride +
+                   var->xoffset * vinfo->bytes_per_pixel);
+       (void)VML_READ32(par, VML_DSPCADDR);
+       mutex_unlock(&vml_mutex);
+
+       return 0;
+}
+
+static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                          u_int transp, struct fb_info *info)
+{
+       u32 v;
+
+       if (regno >= 16)
+               return -EINVAL;
+
+       if (info->var.grayscale) {
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+       }
+
+       if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+               return -EINVAL;
+
+       red = VML_TOHW(red, info->var.red.length);
+       blue = VML_TOHW(blue, info->var.blue.length);
+       green = VML_TOHW(green, info->var.green.length);
+       transp = VML_TOHW(transp, info->var.transp.length);
+
+       v = (red << info->var.red.offset) |
+           (green << info->var.green.offset) |
+           (blue << info->var.blue.offset) |
+           (transp << info->var.transp.offset);
+
+       switch (info->var.bits_per_pixel) {
+       case 16:
+               ((u32 *) info->pseudo_palette)[regno] = v;
+               break;
+       case 24:
+       case 32:
+               ((u32 *) info->pseudo_palette)[regno] = v;
+               break;
+       }
+       return 0;
+}
+
+static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       struct vml_info *vinfo = container_of(info, struct vml_info, info);
+       unsigned long size = vma->vm_end - vma->vm_start;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret;
+
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+       if (offset + size > vinfo->vram_contig_size)
+               return -EINVAL;
+       ret = vmlfb_vram_offset(vinfo, offset);
+       if (ret)
+               return -EINVAL;
+       offset += vinfo->vram_start;
+       pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+       pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+       vma->vm_flags |= VM_RESERVED | VM_IO;
+       if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+                                               size, vma->vm_page_prot))
+               return -EAGAIN;
+       return 0;
+}
+
+static int vmlfb_sync(struct fb_info *info)
+{
+       return 0;
+}
+
+static int vmlfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       return -EINVAL; /* just to force soft_cursor() call */
+}
+
+static struct fb_ops vmlfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_open = vmlfb_open,
+       .fb_release = vmlfb_release,
+       .fb_check_var = vmlfb_check_var,
+       .fb_set_par = vmlfb_set_par,
+       .fb_blank = vmlfb_blank,
+       .fb_pan_display = vmlfb_pan_display,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+       .fb_cursor = vmlfb_cursor,
+       .fb_sync = vmlfb_sync,
+       .fb_mmap = vmlfb_mmap,
+       .fb_setcolreg = vmlfb_setcolreg
+};
+
+static struct pci_device_id vml_ids[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, VML_DEVICE_VDC)},
+       {0}
+};
+
+static struct pci_driver vmlfb_pci_driver = {
+       .name = "vmlfb",
+       .id_table = vml_ids,
+       .probe = vml_pci_probe,
+       .remove = __devexit_p(vml_pci_remove)
+};
+
+static void __exit vmlfb_cleanup(void)
+{
+       pci_unregister_driver(&vmlfb_pci_driver);
+}
+
+static int __init vmlfb_init(void)
+{
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options(MODULE_NAME, &option))
+               return -ENODEV;
+#endif
+
+       printk(KERN_DEBUG MODULE_NAME ": initializing\n");
+       mutex_init(&vml_mutex);
+       INIT_LIST_HEAD(&global_no_mode);
+       INIT_LIST_HEAD(&global_has_mode);
+
+       return pci_register_driver(&vmlfb_pci_driver);
+}
+
+int vmlfb_register_subsys(struct vml_sys *sys)
+{
+       struct vml_info *entry;
+       struct list_head *list;
+       u32 save_activate;
+
+       mutex_lock(&vml_mutex);
+       if (subsys != NULL) {
+               subsys->restore(subsys);
+       }
+       subsys = sys;
+       subsys->save(subsys);
+
+       /*
+        * We need to restart list traversal for each item, since we
+        * release the list mutex in the loop.
+        */
+
+       list = global_no_mode.next;
+       while (list != &global_no_mode) {
+               list_del_init(list);
+               entry = list_entry(list, struct vml_info, head);
+
+               /*
+                * First, try the current mode which might not be
+                * completely validated with respect to the pixel clock.
+                */
+
+               if (!vmlfb_check_var_locked(&entry->info.var, entry)) {
+                       vmlfb_set_par_locked(entry);
+                       list_add_tail(list, &global_has_mode);
+               } else {
+
+                       /*
+                        * Didn't work. Try to find another mode,
+                        * that matches this subsys.
+                        */
+
+                       mutex_unlock(&vml_mutex);
+                       save_activate = entry->info.var.activate;
+                       entry->info.var.bits_per_pixel = 16;
+                       vmlfb_set_pref_pixel_format(&entry->info.var);
+                       if (fb_find_mode(&entry->info.var,
+                                        &entry->info,
+                                        vml_default_mode, NULL, 0, NULL, 16)) {
+                               entry->info.var.activate |=
+                                   FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+                               fb_set_var(&entry->info, &entry->info.var);
+                       } else {
+                               printk(KERN_ERR MODULE_NAME
+                                      ": Sorry. no mode found for this subsys.\n");
+                       }
+                       entry->info.var.activate = save_activate;
+                       mutex_lock(&vml_mutex);
+               }
+               vmlfb_blank_locked(entry);
+               list = global_no_mode.next;
+       }
+       mutex_unlock(&vml_mutex);
+
+       printk(KERN_DEBUG MODULE_NAME ": Registered %s subsystem.\n",
+                               subsys->name ? subsys->name : "unknown");
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(vmlfb_register_subsys);
+
+void vmlfb_unregister_subsys(struct vml_sys *sys)
+{
+       struct vml_info *entry, *next;
+
+       mutex_lock(&vml_mutex);
+       if (subsys != sys) {
+               mutex_unlock(&vml_mutex);
+               return;
+       }
+       subsys->restore(subsys);
+       subsys = NULL;
+       list_for_each_entry_safe(entry, next, &global_has_mode, head) {
+               printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
+               vmlfb_disable_pipe(entry);
+               list_del(&entry->head);
+               list_add_tail(&entry->head, &global_no_mode);
+       }
+       mutex_unlock(&vml_mutex);
+}
+
+EXPORT_SYMBOL_GPL(vmlfb_unregister_subsys);
+
+module_init(vmlfb_init);
+module_exit(vmlfb_cleanup);
+
+MODULE_AUTHOR("Tungsten Graphics");
+MODULE_DESCRIPTION("Initialization of the Vermilion display devices");
+MODULE_VERSION("1.0.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
new file mode 100644 (file)
index 0000000..1fc6695
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Vermilion Range fb driver.
+ * The Vermilion Range fb driver 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.
+ *
+ * The Vermilion Range fb driver 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 driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _VERMILION_H_
+#define _VERMILION_H_
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <asm/atomic.h>
+#include <linux/mutex.h>
+
+#define VML_DEVICE_GPU 0x5002
+#define VML_DEVICE_VDC 0x5009
+
+#define VML_VRAM_AREAS 3
+#define VML_MAX_XRES 1024
+#define VML_MAX_YRES 768
+#define VML_MAX_XRES_VIRTUAL 1040
+
+/*
+ * Display controller registers:
+ */
+
+/* Display controller 10-bit color representation */
+
+#define VML_R_MASK                   0x3FF00000
+#define VML_R_SHIFT                  20
+#define VML_G_MASK                   0x000FFC00
+#define VML_G_SHIFT                  10
+#define VML_B_MASK                   0x000003FF
+#define VML_B_SHIFT                  0
+
+/* Graphics plane control */
+#define VML_DSPCCNTR                 0x00072180
+#define VML_GFX_ENABLE               0x80000000
+#define VML_GFX_GAMMABYPASS          0x40000000
+#define VML_GFX_ARGB1555             0x0C000000
+#define VML_GFX_RGB0888              0x18000000
+#define VML_GFX_ARGB8888             0x1C000000
+#define VML_GFX_ALPHACONST           0x02000000
+#define VML_GFX_ALPHAMULT            0x01000000
+#define VML_GFX_CONST_ALPHA          0x000000FF
+
+/* Graphics plane start address. Pixel aligned. */
+#define VML_DSPCADDR                 0x00072184
+
+/* Graphics plane stride register. */
+#define VML_DSPCSTRIDE               0x00072188
+
+/* Graphics plane position register. */
+#define VML_DSPCPOS                  0x0007218C
+#define VML_POS_YMASK                0x0FFF0000
+#define VML_POS_YSHIFT               16
+#define VML_POS_XMASK                0x00000FFF
+#define VML_POS_XSHIFT               0
+
+/* Graphics plane height and width */
+#define VML_DSPCSIZE                 0x00072190
+#define VML_SIZE_HMASK               0x0FFF0000
+#define VML_SIZE_HSHIFT              16
+#define VML_SISE_WMASK               0x00000FFF
+#define VML_SIZE_WSHIFT              0
+
+/* Graphics plane gamma correction lookup table registers (129 * 32 bits) */
+#define VML_DSPCGAMLUT               0x00072200
+
+/* Pixel video output configuration register */
+#define VML_PVOCONFIG                0x00061140
+#define VML_CONFIG_BASE              0x80000000
+#define VML_CONFIG_PIXEL_SWAP        0x04000000
+#define VML_CONFIG_DE_INV            0x01000000
+#define VML_CONFIG_HREF_INV          0x00400000
+#define VML_CONFIG_VREF_INV          0x00100000
+#define VML_CONFIG_CLK_INV           0x00040000
+#define VML_CONFIG_CLK_DIV2          0x00010000
+#define VML_CONFIG_ESTRB_INV         0x00008000
+
+/* Pipe A Horizontal total register */
+#define VML_HTOTAL_A                 0x00060000
+#define VML_HTOTAL_MASK              0x1FFF0000
+#define VML_HTOTAL_SHIFT             16
+#define VML_HTOTAL_VAL               8192
+#define VML_HACTIVE_MASK             0x000007FF
+#define VML_HACTIVE_SHIFT            0
+#define VML_HACTIVE_VAL              4096
+
+/* Pipe A Horizontal Blank register */
+#define VML_HBLANK_A                 0x00060004
+#define VML_HBLANK_END_MASK          0x1FFF0000
+#define VML_HBLANK_END_SHIFT         16
+#define VML_HBLANK_END_VAL           8192
+#define VML_HBLANK_START_MASK        0x00001FFF
+#define VML_HBLANK_START_SHIFT       0
+#define VML_HBLANK_START_VAL         8192
+
+/* Pipe A Horizontal Sync register */
+#define VML_HSYNC_A                  0x00060008
+#define VML_HSYNC_END_MASK           0x1FFF0000
+#define VML_HSYNC_END_SHIFT          16
+#define VML_HSYNC_END_VAL            8192
+#define VML_HSYNC_START_MASK         0x00001FFF
+#define VML_HSYNC_START_SHIFT        0
+#define VML_HSYNC_START_VAL          8192
+
+/* Pipe A Vertical total register */
+#define VML_VTOTAL_A                 0x0006000C
+#define VML_VTOTAL_MASK              0x1FFF0000
+#define VML_VTOTAL_SHIFT             16
+#define VML_VTOTAL_VAL               8192
+#define VML_VACTIVE_MASK             0x000007FF
+#define VML_VACTIVE_SHIFT            0
+#define VML_VACTIVE_VAL              4096
+
+/* Pipe A Vertical Blank register */
+#define VML_VBLANK_A                 0x00060010
+#define VML_VBLANK_END_MASK          0x1FFF0000
+#define VML_VBLANK_END_SHIFT         16
+#define VML_VBLANK_END_VAL           8192
+#define VML_VBLANK_START_MASK        0x00001FFF
+#define VML_VBLANK_START_SHIFT       0
+#define VML_VBLANK_START_VAL         8192
+
+/* Pipe A Vertical Sync register */
+#define VML_VSYNC_A                  0x00060014
+#define VML_VSYNC_END_MASK           0x1FFF0000
+#define VML_VSYNC_END_SHIFT          16
+#define VML_VSYNC_END_VAL            8192
+#define VML_VSYNC_START_MASK         0x00001FFF
+#define VML_VSYNC_START_SHIFT        0
+#define VML_VSYNC_START_VAL          8192
+
+/* Pipe A Source Image size (minus one - equal to active size)
+ * Programmable while pipe is enabled.
+ */
+#define VML_PIPEASRC                 0x0006001C
+#define VML_PIPEASRC_HMASK           0x0FFF0000
+#define VML_PIPEASRC_HSHIFT          16
+#define VML_PIPEASRC_VMASK           0x00000FFF
+#define VML_PIPEASRC_VSHIFT          0
+
+/* Pipe A Border Color Pattern register (10 bit color) */
+#define VML_BCLRPAT_A                0x00060020
+
+/* Pipe A Canvas Color register  (10 bit color) */
+#define VML_CANVSCLR_A               0x00060024
+
+/* Pipe A Configuration register */
+#define VML_PIPEACONF                0x00070008
+#define VML_PIPE_BASE                0x00000000
+#define VML_PIPE_ENABLE              0x80000000
+#define VML_PIPE_FORCE_BORDER        0x02000000
+#define VML_PIPE_PLANES_OFF          0x00080000
+#define VML_PIPE_ARGB_OUTPUT_MODE    0x00040000
+
+/* Pipe A FIFO setting */
+#define VML_DSPARB                   0x00070030
+#define VML_FIFO_DEFAULT             0x00001D9C
+
+/* MDVO rcomp status & pads control register */
+#define VML_RCOMPSTAT                0x00070048
+#define VML_MDVO_VDC_I_RCOMP         0x80000000
+#define VML_MDVO_POWERSAVE_OFF       0x00000008
+#define VML_MDVO_PAD_ENABLE          0x00000004
+#define VML_MDVO_PULLDOWN_ENABLE     0x00000001
+
+struct vml_par {
+       struct pci_dev *vdc;
+       u64 vdc_mem_base;
+       u64 vdc_mem_size;
+       char __iomem *vdc_mem;
+
+       struct pci_dev *gpu;
+       u64 gpu_mem_base;
+       u64 gpu_mem_size;
+       char __iomem *gpu_mem;
+
+       atomic_t refcount;
+};
+
+struct vram_area {
+       unsigned long logical;
+       unsigned long phys;
+       unsigned long size;
+       unsigned order;
+};
+
+struct vml_info {
+       struct fb_info info;
+       struct vml_par *par;
+       struct list_head head;
+       struct vram_area vram[VML_VRAM_AREAS];
+       u64 vram_start;
+       u64 vram_contig_size;
+       u32 num_areas;
+       void __iomem *vram_logical;
+       u32 pseudo_palette[16];
+       u32 stride;
+       u32 bytes_per_pixel;
+       atomic_t vmas;
+       int cur_blank_mode;
+       int pipe_disabled;
+};
+
+/*
+ * Subsystem
+ */
+
+struct vml_sys {
+       char *name;
+
+       /*
+        * Save / Restore;
+        */
+
+       int (*save) (struct vml_sys * sys);
+       int (*restore) (struct vml_sys * sys);
+
+       /*
+        * PLL programming;
+        */
+
+       int (*set_clock) (struct vml_sys * sys, int clock);
+       int (*nearest_clock) (const struct vml_sys * sys, int clock);
+};
+
+extern int vmlfb_register_subsys(struct vml_sys *sys);
+extern void vmlfb_unregister_subsys(struct vml_sys *sys);
+
+#define VML_READ32(_par, _offset) \
+       (ioread32((_par)->vdc_mem + (_offset)))
+#define VML_WRITE32(_par, _offset, _value)                             \
+       iowrite32(_value, (_par)->vdc_mem + (_offset))
+
+#endif
index a9b99b01bd8e377f2656058bd29b09accb7ef6ea..64ee78c3c12bba274d18db4f24f63f1016687b75 100644 (file)
@@ -84,13 +84,15 @@ static int vfb_mmap(struct fb_info *info,
                    struct vm_area_struct *vma);
 
 static struct fb_ops vfb_ops = {
+       .fb_read        = fb_sys_read,
+       .fb_write       = fb_sys_write,
        .fb_check_var   = vfb_check_var,
        .fb_set_par     = vfb_set_par,
        .fb_setcolreg   = vfb_setcolreg,
        .fb_pan_display = vfb_pan_display,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = sys_fillrect,
+       .fb_copyarea    = sys_copyarea,
+       .fb_imageblit   = sys_imageblit,
        .fb_mmap        = vfb_mmap,
 };
 
index ec4c7dc54a66972dbc662e0137b468d2bda088aa..2a14d28c41633ff92b28b9e253d1fb3530349fb0 100644 (file)
@@ -1378,6 +1378,8 @@ static int __init vga16fb_probe(struct platform_device *dev)
        info->fbops = &vga16fb_ops;
        info->var = vga16fb_defined;
        info->fix = vga16fb_fix;
+       /* supports rectangles with widths of multiples of 8 */
+       info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
        info->flags = FBINFO_FLAG_DEFAULT |
                FBINFO_HWACCEL_YPAN;
 
index d94efafc77b57362ee8e29e8fdf2e118b69756a4..b91c466225b957610b7a8ddc7207c7fb47a6f355 100644 (file)
@@ -50,23 +50,28 @@ static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
        struct regstate *saved = (struct regstate *) state->vidstate;
        int i;
        u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
+       unsigned short iobase;
 
        /* if in graphics mode, no need to save */
+       misc = vga_r(state->vgabase, VGA_MIS_R);
+       iobase = (misc & 1) ? 0x3d0 : 0x3b0;
+
+       vga_r(state->vgabase, iobase + 0xa);
+       vga_w(state->vgabase, VGA_ATT_W, 0x00);
        attr10 = vga_rattr(state->vgabase, 0x10);
+       vga_r(state->vgabase, iobase + 0xa);
+       vga_w(state->vgabase, VGA_ATT_W, 0x20);
+
        if (attr10 & 1)
                return;
-       
+
        /* save regs */
-       misc = vga_r(state->vgabase, VGA_MIS_R);
        gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
        gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
        gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
        seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
        seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
        
-       /* force graphics mode */
-       vga_w(state->vgabase, VGA_MIS_W, misc | 1);
-
        /* blank screen */
        seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
        vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@@ -115,15 +120,12 @@ static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
        }
 
        /* restore regs */
-       vga_wattr(state->vgabase, 0x10, attr10);
-
        vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
        vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
 
        vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
        vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
        vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
-       vga_w(state->vgabase, VGA_MIS_W, misc);
 
        /* unblank screen */
        vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@@ -137,11 +139,10 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
        struct regstate *saved = (struct regstate *) state->vidstate;
        int i;
-       u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; 
+       u8 gr1, gr3, gr4, gr5, gr6, gr8;
        u8 seq1, seq2, seq4;
 
        /* save regs */
-       misc = vga_r(state->vgabase, VGA_MIS_R);
        gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE);
        gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE);
        gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
@@ -151,9 +152,6 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
        seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
        seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
        
-       /* force graphics mode */
-       vga_w(state->vgabase, VGA_MIS_W, misc | 1);
-
        /* blank screen */
        seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
        vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@@ -213,8 +211,6 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
        vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
 
        /* restore regs */
-       vga_w(state->vgabase, VGA_MIS_W, misc);
-
        vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1);
        vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3);
        vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
new file mode 100644 (file)
index 0000000..5e9755e
--- /dev/null
@@ -0,0 +1,927 @@
+/*
+ * linux/drivers/video/vt8623fb.c - fbdev driver for
+ * integrated graphic core in VIA VT8623 [CLE266] chipset
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * 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.
+ *
+ * Code is based on s3fb, some parts are from David Boucher's viafb
+ * (http://davesdomain.org.uk/viafb/)
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct vt8623fb_info {
+       char __iomem *mmio_base;
+       int mtrr_reg;
+       struct vgastate state;
+       struct mutex open_lock;
+       unsigned int ref_count;
+       u32 pseudo_palette[16];
+};
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static const struct svga_fb_format vt8623fb_formats[] = {
+       { 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP8,   FB_VISUAL_PSEUDOCOLOR, 16, 16},
+       { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 16, 16},
+       { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+               FB_TYPE_INTERLEAVED_PLANES, 1,          FB_VISUAL_PSEUDOCOLOR, 16, 16},
+       { 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 8, 8},
+/*     {16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},     */
+       {16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},
+       {32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+               FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 2, 2},
+       SVGA_FORMAT_END
+};
+
+static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
+       60000, 300000, 14318};
+
+/* CRT timing register sets */
+
+struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
+struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
+struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
+struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
+struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
+struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
+
+struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
+struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
+struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
+struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
+struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
+struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
+
+struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
+struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
+struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
+struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
+
+struct svga_timing_regs vt8623_timing_regs     = {
+       vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
+       vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
+       vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
+       vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Module parameters */
+
+static char *mode = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
+
+module_param(mode, charp, 0644);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static struct fb_tile_ops vt8623fb_tile_ops = {
+       .fb_settile     = svga_settile,
+       .fb_tilecopy    = svga_tilecopy,
+       .fb_tilefill    = svga_tilefill,
+       .fb_tileblit    = svga_tileblit,
+       .fb_tilecursor  = svga_tilecursor,
+       .fb_get_tilemax = svga_get_tilemax,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+       return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* vt8623fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       u32 fg = expand_color(image->fg_color);
+       u32 bg = expand_color(image->bg_color);
+       const u8 *src1, *src;
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       u32 val;
+       int x, y;
+
+       src1 = image->data;
+       dst1 = info->screen_base + (image->dy * info->fix.line_length)
+                + ((image->dx / 8) * 4);
+
+       for (y = 0; y < image->height; y++) {
+               src = src1;
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < image->width; x += 8) {
+                       val = *(src++) * 0x01010101;
+                       val = (val & fg) | (~val & bg);
+                       fb_writel(val, dst++);
+               }
+               src1 += image->width / 8;
+               dst1 += info->fix.line_length;
+       }
+}
+
+/* vt8623fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       u32 fg = expand_color(rect->color);
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       int x, y;
+
+       dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+                + ((rect->dx / 8) * 4);
+
+       for (y = 0; y < rect->height; y++) {
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < rect->width; x += 8) {
+                       fb_writel(fg, dst++);
+               }
+               dst1 += info->fix.line_length;
+       }
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+       return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+               ((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* vt8623fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       u32 fg = image->fg_color * 0x11111111;
+       u32 bg = image->bg_color * 0x11111111;
+       const u8 *src1, *src;
+       u8 __iomem *dst1;
+       u32 __iomem *dst;
+       u32 val;
+       int x, y;
+
+       src1 = image->data;
+       dst1 = info->screen_base + (image->dy * info->fix.line_length)
+                + ((image->dx / 8) * 4);
+
+       for (y = 0; y < image->height; y++) {
+               src = src1;
+               dst = (u32 __iomem *) dst1;
+               for (x = 0; x < image->width; x += 8) {
+                       val = expand_pixel(*(src++));
+                       val = (val & fg) | (~val & bg);
+                       fb_writel(val, dst++);
+               }
+               src1 += image->width / 8;
+               dst1 += info->fix.line_length;
+       }
+}
+
+static void vt8623fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+           && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+               if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+                       vt8623fb_iplan_imageblit(info, image);
+               else
+                       vt8623fb_cfb4_imageblit(info, image);
+       } else
+               cfb_imageblit(info, image);
+}
+
+static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       if ((info->var.bits_per_pixel == 4)
+           && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+           && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+               vt8623fb_iplan_fillrect(info, rect);
+        else
+               cfb_fillrect(info, rect);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+       u16 m, n, r;
+       u8 regval;
+       int rv;
+
+       rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+       if (rv < 0) {
+               printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
+               return;
+       }
+
+       /* Set VGA misc register  */
+       regval = vga_r(NULL, VGA_MIS_R);
+       vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+
+       /* Set clock registers */
+       vga_wseq(NULL, 0x46, (n  | (r << 6)));
+       vga_wseq(NULL, 0x47, m);
+
+       udelay(1000);
+
+       /* PLL reset */
+       svga_wseq_mask(0x40, 0x02, 0x02);
+       svga_wseq_mask(0x40, 0x00, 0x02);
+}
+
+
+static int vt8623fb_open(struct fb_info *info, int user)
+{
+       struct vt8623fb_info *par = info->par;
+
+       mutex_lock(&(par->open_lock));
+       if (par->ref_count == 0) {
+               memset(&(par->state), 0, sizeof(struct vgastate));
+               par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+               par->state.num_crtc = 0xA2;
+               par->state.num_seq = 0x50;
+               save_vga(&(par->state));
+       }
+
+       par->ref_count++;
+       mutex_unlock(&(par->open_lock));
+
+       return 0;
+}
+
+static int vt8623fb_release(struct fb_info *info, int user)
+{
+       struct vt8623fb_info *par = info->par;
+
+       mutex_lock(&(par->open_lock));
+       if (par->ref_count == 0) {
+               mutex_unlock(&(par->open_lock));
+               return -EINVAL;
+       }
+
+       if (par->ref_count == 1)
+               restore_vga(&(par->state));
+
+       par->ref_count--;
+       mutex_unlock(&(par->open_lock));
+
+       return 0;
+}
+
+static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int rv, mem, step;
+
+       /* Find appropriate format */
+       rv = svga_match_format (vt8623fb_formats, var, NULL);
+       if (rv < 0)
+       {
+               printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
+               return rv;
+       }
+
+       /* Do not allow to have real resoulution larger than virtual */
+       if (var->xres > var->xres_virtual)
+               var->xres_virtual = var->xres;
+
+       if (var->yres > var->yres_virtual)
+               var->yres_virtual = var->yres;
+
+       /* Round up xres_virtual to have proper alignment of lines */
+       step = vt8623fb_formats[rv].xresstep - 1;
+       var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+       /* Check whether have enough memory */
+       mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+       if (mem > info->screen_size)
+       {
+               printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
+               return -EINVAL;
+       }
+
+       /* Text mode is limited to 256 kB of memory */
+       if ((var->bits_per_pixel == 0) && (mem > (256*1024)))
+       {
+               printk(KERN_ERR "fb%d: text framebuffer size too large (%d kB requested, 256 kB possible)\n", info->node, mem >> 10);
+               return -EINVAL;
+       }
+
+       rv = svga_check_timings (&vt8623_timing_regs, var, info->node);
+       if (rv < 0)
+       {
+               printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
+               return rv;
+       }
+
+       /* Interlaced mode not supported */
+       if (var->vmode & FB_VMODE_INTERLACED)
+               return -EINVAL;
+
+       return 0;
+}
+
+
+static int vt8623fb_set_par(struct fb_info *info)
+{
+       u32 mode, offset_value, fetch_value, screen_size;
+       u32 bpp = info->var.bits_per_pixel;
+
+       if (bpp != 0) {
+               info->fix.ypanstep = 1;
+               info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+               info->flags &= ~FBINFO_MISC_TILEBLITTING;
+               info->tileops = NULL;
+
+               /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+               info->pixmap.blit_y = ~(u32)0;
+
+               offset_value = (info->var.xres_virtual * bpp) / 64;
+               fetch_value  = ((info->var.xres * bpp) / 128) + 4;
+
+               if (bpp == 4)
+                       fetch_value  = (info->var.xres / 8) + 8; /* + 0 is OK */
+
+               screen_size  = info->var.yres_virtual * info->fix.line_length;
+       } else {
+               info->fix.ypanstep = 16;
+               info->fix.line_length = 0;
+
+               info->flags |= FBINFO_MISC_TILEBLITTING;
+               info->tileops = &vt8623fb_tile_ops;
+
+               /* supports 8x16 tiles only */
+               info->pixmap.blit_x = 1 << (8 - 1);
+               info->pixmap.blit_y = 1 << (16 - 1);
+
+               offset_value = info->var.xres_virtual / 16;
+               fetch_value  = (info->var.xres / 8) + 8;
+               screen_size  = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+       }
+
+       info->var.xoffset = 0;
+       info->var.yoffset = 0;
+       info->var.activate = FB_ACTIVATE_NOW;
+
+       /* Unlock registers */
+       svga_wseq_mask(0x10, 0x01, 0x01);
+       svga_wcrt_mask(0x11, 0x00, 0x80);
+       svga_wcrt_mask(0x47, 0x00, 0x01);
+
+       /* Device, screen and sync off */
+       svga_wseq_mask(0x01, 0x20, 0x20);
+       svga_wcrt_mask(0x36, 0x30, 0x30);
+       svga_wcrt_mask(0x17, 0x00, 0x80);
+
+       /* Set default values */
+       svga_set_default_gfx_regs();
+       svga_set_default_atc_regs();
+       svga_set_default_seq_regs();
+       svga_set_default_crt_regs();
+       svga_wcrt_multi(vt8623_line_compare_regs, 0xFFFFFFFF);
+       svga_wcrt_multi(vt8623_start_address_regs, 0);
+
+       svga_wcrt_multi(vt8623_offset_regs, offset_value);
+       svga_wseq_multi(vt8623_fetch_count_regs, fetch_value);
+
+       if (info->var.vmode & FB_VMODE_DOUBLE)
+               svga_wcrt_mask(0x09, 0x80, 0x80);
+       else
+               svga_wcrt_mask(0x09, 0x00, 0x80);
+
+       svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus
+       svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus
+       svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read treshold
+       vga_wseq(NULL, 0x17, 0x1F);       // FIFO depth
+       vga_wseq(NULL, 0x18, 0x4E);
+       svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ?
+
+       vga_wcrt(NULL, 0x32, 0x00);
+       vga_wcrt(NULL, 0x34, 0x00);
+       vga_wcrt(NULL, 0x6A, 0x80);
+       vga_wcrt(NULL, 0x6A, 0xC0);
+
+       vga_wgfx(NULL, 0x20, 0x00);
+       vga_wgfx(NULL, 0x21, 0x00);
+       vga_wgfx(NULL, 0x22, 0x00);
+
+       /* Set SR15 according to number of bits per pixel */
+       mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix));
+       switch (mode) {
+       case 0:
+               pr_debug("fb%d: text mode\n", info->node);
+               svga_set_textmode_vga_regs();
+               svga_wseq_mask(0x15, 0x00, 0xFE);
+               svga_wcrt_mask(0x11, 0x60, 0x70);
+               break;
+       case 1:
+               pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
+               vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
+               svga_wseq_mask(0x15, 0x20, 0xFE);
+               svga_wcrt_mask(0x11, 0x00, 0x70);
+               break;
+       case 2:
+               pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
+               svga_wseq_mask(0x15, 0x00, 0xFE);
+               svga_wcrt_mask(0x11, 0x00, 0x70);
+               break;
+       case 3:
+               pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
+               svga_wseq_mask(0x15, 0x22, 0xFE);
+               break;
+       case 4:
+               pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
+               svga_wseq_mask(0x15, 0xB6, 0xFE);
+               break;
+       case 5:
+               pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
+               svga_wseq_mask(0x15, 0xAE, 0xFE);
+               break;
+       default:
+               printk(KERN_ERR "vt8623fb: unsupported mode - bug\n");
+               return (-EINVAL);
+       }
+
+       vt8623_set_pixclock(info, info->var.pixclock);
+       svga_set_timings(&vt8623_timing_regs, &(info->var), 1, 1,
+                        (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1,
+                        1, info->node);
+
+       memset_io(info->screen_base, 0x00, screen_size);
+
+       /* Device and screen back on */
+       svga_wcrt_mask(0x17, 0x80, 0x80);
+       svga_wcrt_mask(0x36, 0x00, 0x30);
+       svga_wseq_mask(0x01, 0x00, 0x20);
+
+       return 0;
+}
+
+
+static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                               u_int transp, struct fb_info *fb)
+{
+       switch (fb->var.bits_per_pixel) {
+       case 0:
+       case 4:
+               if (regno >= 16)
+                       return -EINVAL;
+
+               outb(0x0F, VGA_PEL_MSK);
+               outb(regno, VGA_PEL_IW);
+               outb(red >> 10, VGA_PEL_D);
+               outb(green >> 10, VGA_PEL_D);
+               outb(blue >> 10, VGA_PEL_D);
+               break;
+       case 8:
+               if (regno >= 256)
+                       return -EINVAL;
+
+               outb(0xFF, VGA_PEL_MSK);
+               outb(regno, VGA_PEL_IW);
+               outb(red >> 10, VGA_PEL_D);
+               outb(green >> 10, VGA_PEL_D);
+               outb(blue >> 10, VGA_PEL_D);
+               break;
+       case 16:
+               if (regno >= 16)
+                       return 0;
+
+               if (fb->var.green.length == 5)
+                       ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+                               ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+               else if (fb->var.green.length == 6)
+                       ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+                               ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+               else
+                       return -EINVAL;
+               break;
+       case 24:
+       case 32:
+               if (regno >= 16)
+                       return 0;
+
+               /* ((transp & 0xFF00) << 16) */
+               ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
+                       (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+static int vt8623fb_blank(int blank_mode, struct fb_info *info)
+{
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               pr_debug("fb%d: unblank\n", info->node);
+               svga_wcrt_mask(0x36, 0x00, 0x30);
+               svga_wseq_mask(0x01, 0x00, 0x20);
+               break;
+       case FB_BLANK_NORMAL:
+               pr_debug("fb%d: blank\n", info->node);
+               svga_wcrt_mask(0x36, 0x00, 0x30);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               pr_debug("fb%d: DPMS standby (hsync off)\n", info->node);
+               svga_wcrt_mask(0x36, 0x10, 0x30);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node);
+               svga_wcrt_mask(0x36, 0x20, 0x30);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               break;
+       case FB_BLANK_POWERDOWN:
+               pr_debug("fb%d: DPMS off (no sync)\n", info->node);
+               svga_wcrt_mask(0x36, 0x30, 0x30);
+               svga_wseq_mask(0x01, 0x20, 0x20);
+               break;
+       }
+
+       return 0;
+}
+
+
+static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       unsigned int offset;
+
+       /* Calculate the offset */
+       if (var->bits_per_pixel == 0) {
+               offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset;
+               offset = offset >> 3;
+       } else {
+               offset = (var->yoffset * info->fix.line_length) +
+                        (var->xoffset * var->bits_per_pixel / 8);
+               offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1);
+       }
+
+       /* Set the offset */
+       svga_wcrt_multi(vt8623_start_address_regs, offset);
+
+       return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Frame buffer operations */
+
+static struct fb_ops vt8623fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open        = vt8623fb_open,
+       .fb_release     = vt8623fb_release,
+       .fb_check_var   = vt8623fb_check_var,
+       .fb_set_par     = vt8623fb_set_par,
+       .fb_setcolreg   = vt8623fb_setcolreg,
+       .fb_blank       = vt8623fb_blank,
+       .fb_pan_display = vt8623fb_pan_display,
+       .fb_fillrect    = vt8623fb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = vt8623fb_imageblit,
+       .fb_get_caps    = svga_get_caps,
+};
+
+
+/* PCI probe */
+
+static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct fb_info *info;
+       struct vt8623fb_info *par;
+       unsigned int memsize1, memsize2;
+       int rc;
+
+       /* Ignore secondary VGA device because there is no VGA arbitration */
+       if (! svga_primary_device(dev)) {
+               dev_info(&(dev->dev), "ignoring secondary device\n");
+               return -ENODEV;
+       }
+
+       /* Allocate and fill driver data structure */
+       info = framebuffer_alloc(sizeof(struct vt8623fb_info), NULL);
+       if (! info) {
+               dev_err(&(dev->dev), "cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       par = info->par;
+       mutex_init(&par->open_lock);
+
+       info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+       info->fbops = &vt8623fb_ops;
+
+       /* Prepare PCI device */
+
+       rc = pci_enable_device(dev);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot enable PCI device\n");
+               goto err_enable_device;
+       }
+
+       rc = pci_request_regions(dev, "vt8623fb");
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
+               goto err_request_regions;
+       }
+
+       info->fix.smem_start = pci_resource_start(dev, 0);
+       info->fix.smem_len = pci_resource_len(dev, 0);
+       info->fix.mmio_start = pci_resource_start(dev, 1);
+       info->fix.mmio_len = pci_resource_len(dev, 1);
+
+       /* Map physical IO memory address into kernel space */
+       info->screen_base = pci_iomap(dev, 0, 0);
+       if (! info->screen_base) {
+               rc = -ENOMEM;
+               dev_err(&(dev->dev), "iomap for framebuffer failed\n");
+               goto err_iomap_1;
+       }
+
+       par->mmio_base = pci_iomap(dev, 1, 0);
+       if (! par->mmio_base) {
+               rc = -ENOMEM;
+               dev_err(&(dev->dev), "iomap for MMIO failed\n");
+               goto err_iomap_2;
+       }
+
+       /* Find how many physical memory there is on card */
+       memsize1 = (vga_rseq(NULL, 0x34) + 1) >> 1;
+       memsize2 = vga_rseq(NULL, 0x39) << 2;
+
+       if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
+               info->screen_size = memsize1 << 20;
+       else {
+               dev_err(&(dev->dev), "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
+               info->screen_size = 16 << 20;
+       }
+
+       info->fix.smem_len = info->screen_size;
+       strcpy(info->fix.id, "VIA VT8623");
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+       info->fix.ypanstep = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+       info->pseudo_palette = (void*)par->pseudo_palette;
+
+       /* Prepare startup mode */
+
+       rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
+       if (! ((rc == 1) || (rc == 2))) {
+               rc = -EINVAL;
+               dev_err(&(dev->dev), "mode %s not found\n", mode);
+               goto err_find_mode;
+       }
+
+       rc = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot allocate colormap\n");
+               goto err_alloc_cmap;
+       }
+
+       rc = register_framebuffer(info);
+       if (rc < 0) {
+               dev_err(&(dev->dev), "cannot register framebugger\n");
+               goto err_reg_fb;
+       }
+
+       printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id,
+                pci_name(dev), info->fix.smem_len >> 20);
+
+       /* Record a reference to the driver data */
+       pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+       if (mtrr) {
+               par->mtrr_reg = -1;
+               par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+       }
+#endif
+
+       return 0;
+
+       /* Error handling */
+err_reg_fb:
+       fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+       pci_iounmap(dev, par->mmio_base);
+err_iomap_2:
+       pci_iounmap(dev, info->screen_base);
+err_iomap_1:
+       pci_release_regions(dev);
+err_request_regions:
+/*     pci_disable_device(dev); */
+err_enable_device:
+       framebuffer_release(info);
+       return rc;
+}
+
+/* PCI remove */
+
+static void __devexit vt8623_pci_remove(struct pci_dev *dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct vt8623fb_info *par = info->par;
+
+       if (info) {
+#ifdef CONFIG_MTRR
+               if (par->mtrr_reg >= 0) {
+                       mtrr_del(par->mtrr_reg, 0, 0);
+                       par->mtrr_reg = -1;
+               }
+#endif
+
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+
+               pci_iounmap(dev, info->screen_base);
+               pci_iounmap(dev, par->mmio_base);
+               pci_release_regions(dev);
+/*             pci_disable_device(dev); */
+
+               pci_set_drvdata(dev, NULL);
+               framebuffer_release(info);
+       }
+}
+
+
+#ifdef CONFIG_PM
+/* PCI suspend */
+
+static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct vt8623fb_info *par = info->par;
+
+       dev_info(&(dev->dev), "suspend\n");
+
+       acquire_console_sem();
+       mutex_lock(&(par->open_lock));
+
+       if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+               mutex_unlock(&(par->open_lock));
+               release_console_sem();
+               return 0;
+       }
+
+       fb_set_suspend(info, 1);
+
+       pci_save_state(dev);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+
+       mutex_unlock(&(par->open_lock));
+       release_console_sem();
+
+       return 0;
+}
+
+
+/* PCI resume */
+
+static int vt8623_pci_resume(struct pci_dev* dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct vt8623fb_info *par = info->par;
+
+       dev_info(&(dev->dev), "resume\n");
+
+       acquire_console_sem();
+       mutex_lock(&(par->open_lock));
+
+       if (par->ref_count == 0) {
+               mutex_unlock(&(par->open_lock));
+               release_console_sem();
+               return 0;
+       }
+
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       if (pci_enable_device(dev))
+               goto fail;
+
+       pci_set_master(dev);
+
+       vt8623fb_set_par(info);
+       fb_set_suspend(info, 0);
+
+       mutex_unlock(&(par->open_lock));
+fail:
+       release_console_sem();
+
+       return 0;
+}
+#else
+#define vt8623_pci_suspend NULL
+#define vt8623_pci_resume NULL
+#endif /* CONFIG_PM */
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id vt8623_devices[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},
+       {0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, vt8623_devices);
+
+static struct pci_driver vt8623fb_pci_driver = {
+       .name           = "vt8623fb",
+       .id_table       = vt8623_devices,
+       .probe          = vt8623_pci_probe,
+       .remove         = __devexit_p(vt8623_pci_remove),
+       .suspend        = vt8623_pci_suspend,
+       .resume         = vt8623_pci_resume,
+};
+
+/* Cleanup */
+
+static void __exit vt8623fb_cleanup(void)
+{
+       pr_debug("vt8623fb: cleaning up\n");
+       pci_unregister_driver(&vt8623fb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+int __init vt8623fb_init(void)
+{
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("vt8623fb", &option))
+               return -ENODEV;
+
+       if (option && *option)
+               mode = option;
+#endif
+
+       pr_debug("vt8623fb: initializing\n");
+       return pci_register_driver(&vt8623fb_pci_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Modularization */
+
+module_init(vt8623fb_init);
+module_exit(vt8623fb_cleanup);
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
new file mode 100644 (file)
index 0000000..1d29a89
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * xilinxfb.c
+ *
+ * Xilinx TFT LCD frame buffer driver
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2007 (c) MontaVista Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2.  This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+/*
+ * This driver was based on au1100fb.c by MontaVista rewritten for 2.6
+ * by Embedded Alley Solutions <source@embeddedalley.com>, which in turn
+ * was based on skeletonfb.c, Skeleton for a frame buffer device by
+ * Geert Uytterhoeven.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <syslib/virtex_devices.h>
+
+#define DRIVER_NAME            "xilinxfb"
+#define DRIVER_DESCRIPTION     "Xilinx TFT LCD frame buffer driver"
+
+/*
+ * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for
+ * the VGA port on the Xilinx ML40x board. This is a hardware display controller
+ * for a 640x480 resolution TFT or VGA screen.
+ *
+ * The interface to the framebuffer is nice and simple.  There are two
+ * control registers.  The first tells the LCD interface where in memory
+ * the frame buffer is (only the 11 most significant bits are used, so
+ * don't start thinking about scrolling).  The second allows the LCD to
+ * be turned on or off as well as rotated 180 degrees.
+ */
+#define NUM_REGS       2
+#define REG_FB_ADDR    0
+#define REG_CTRL       1
+#define REG_CTRL_ENABLE         0x0001
+#define REG_CTRL_ROTATE         0x0002
+
+/*
+ * The hardware only handles a single mode: 640x480 24 bit true
+ * color. Each pixel gets a word (32 bits) of memory.  Within each word,
+ * the 8 most significant bits are ignored, the next 8 bits are the red
+ * level, the next 8 bits are the green level and the 8 least
+ * significant bits are the blue level.  Each row of the LCD uses 1024
+ * words, but only the first 640 pixels are displayed with the other 384
+ * words being ignored.  There are 480 rows.
+ */
+#define BYTES_PER_PIXEL        4
+#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
+#define XRES           640
+#define YRES           480
+#define XRES_VIRTUAL   1024
+#define YRES_VIRTUAL   YRES
+#define LINE_LENGTH    (XRES_VIRTUAL * BYTES_PER_PIXEL)
+#define FB_SIZE                (YRES_VIRTUAL * LINE_LENGTH)
+
+#define RED_SHIFT      16
+#define GREEN_SHIFT    8
+#define BLUE_SHIFT     0
+
+#define PALETTE_ENTRIES_NO     16      /* passed to fb_alloc_cmap() */
+
+/*
+ * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures
+ */
+static struct fb_fix_screeninfo xilinx_fb_fix __initdata = {
+       .id =           "Xilinx",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+       .smem_len =     FB_SIZE,
+       .line_length =  LINE_LENGTH,
+       .accel =        FB_ACCEL_NONE
+};
+
+static struct fb_var_screeninfo xilinx_fb_var __initdata = {
+       .xres =                 XRES,
+       .yres =                 YRES,
+       .xres_virtual =         XRES_VIRTUAL,
+       .yres_virtual =         YRES_VIRTUAL,
+
+       .bits_per_pixel =       BITS_PER_PIXEL,
+
+       .red =          { RED_SHIFT, 8, 0 },
+       .green =        { GREEN_SHIFT, 8, 0 },
+       .blue =         { BLUE_SHIFT, 8, 0 },
+       .transp =       { 0, 0, 0 },
+
+       .activate =     FB_ACTIVATE_NOW
+};
+
+struct xilinxfb_drvdata {
+
+       struct fb_info  info;           /* FB driver info record */
+
+       u32             regs_phys;      /* phys. address of the control registers */
+       u32 __iomem     *regs;          /* virt. address of the control registers */
+
+       unsigned char __iomem   *fb_virt;       /* virt. address of the frame buffer */
+       dma_addr_t      fb_phys;        /* phys. address of the frame buffer */
+
+       u32             reg_ctrl_default;
+
+       u32             pseudo_palette[PALETTE_ENTRIES_NO];
+                                       /* Fake palette of 16 colors */
+};
+
+#define to_xilinxfb_drvdata(_info) \
+       container_of(_info, struct xilinxfb_drvdata, info)
+
+/*
+ * The LCD controller has DCR interface to its registers, but all
+ * the boards and configurations the driver has been tested with
+ * use opb2dcr bridge. So the registers are seen as memory mapped.
+ * This macro is to make it simple to add the direct DCR access
+ * when it's needed.
+ */
+#define xilinx_fb_out_be32(driverdata, offset, val) \
+       out_be32(driverdata->regs + offset, val)
+
+static int
+xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+       unsigned transp, struct fb_info *fbi)
+{
+       u32 *palette = fbi->pseudo_palette;
+
+       if (regno >= PALETTE_ENTRIES_NO)
+               return -EINVAL;
+
+       if (fbi->var.grayscale) {
+               /* Convert color to grayscale.
+                * grayscale = 0.30*R + 0.59*G + 0.11*B */
+               red = green = blue =
+                       (red * 77 + green * 151 + blue * 28 + 127) >> 8;
+       }
+
+       /* fbi->fix.visual is always FB_VISUAL_TRUECOLOR */
+
+       /* We only handle 8 bits of each color. */
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+       palette[regno] = (red << RED_SHIFT) | (green << GREEN_SHIFT) |
+                        (blue << BLUE_SHIFT);
+
+       return 0;
+}
+
+static int
+xilinx_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+       struct xilinxfb_drvdata *drvdata = to_xilinxfb_drvdata(fbi);
+
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               /* turn on panel */
+               xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
+               break;
+
+       case FB_BLANK_NORMAL:
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_POWERDOWN:
+               /* turn off panel */
+               xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
+       default:
+               break;
+
+       }
+       return 0; /* success */
+}
+
+static struct fb_ops xilinxfb_ops =
+{
+       .owner                  = THIS_MODULE,
+       .fb_setcolreg           = xilinx_fb_setcolreg,
+       .fb_blank               = xilinx_fb_blank,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+};
+
+/* === The device driver === */
+
+static int
+xilinxfb_drv_probe(struct device *dev)
+{
+       struct platform_device *pdev;
+       struct xilinxfb_platform_data *pdata;
+       struct xilinxfb_drvdata *drvdata;
+       struct resource *regs_res;
+       int retval;
+
+       if (!dev)
+               return -EINVAL;
+
+       pdev = to_platform_device(dev);
+       pdata = pdev->dev.platform_data;
+
+       if (pdata == NULL) {
+               printk(KERN_ERR "Couldn't find platform data.\n");
+               return -EFAULT;
+       }
+
+       drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata) {
+               printk(KERN_ERR "Couldn't allocate device private record\n");
+               return -ENOMEM;
+       }
+       dev_set_drvdata(dev, drvdata);
+
+       /* Map the control registers in */
+       regs_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
+               printk(KERN_ERR "Couldn't get registers resource\n");
+               retval = -EFAULT;
+               goto failed1;
+       }
+
+       if (!request_mem_region(regs_res->start, 8, DRIVER_NAME)) {
+               printk(KERN_ERR
+                      "Couldn't lock memory region at 0x%08X\n",
+                      regs_res->start);
+               retval = -EBUSY;
+               goto failed1;
+       }
+       drvdata->regs = (u32 __iomem*) ioremap(regs_res->start, 8);
+       drvdata->regs_phys = regs_res->start;
+
+       /* Allocate the framebuffer memory */
+       drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE),
+                               &drvdata->fb_phys, GFP_KERNEL);
+       if (!drvdata->fb_virt) {
+               printk(KERN_ERR "Could not allocate frame buffer memory\n");
+               retval = -ENOMEM;
+               goto failed2;
+       }
+
+       /* Clear (turn to black) the framebuffer */
+       memset_io((void *) drvdata->fb_virt, 0, FB_SIZE);
+
+       /* Tell the hardware where the frame buffer is */
+       xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
+
+       /* Turn on the display */
+       if (pdata->rotate_screen) {
+               drvdata->reg_ctrl_default = REG_CTRL_ENABLE | REG_CTRL_ROTATE;
+       } else {
+               drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
+       }
+       xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
+
+       /* Fill struct fb_info */
+       drvdata->info.device = dev;
+       drvdata->info.screen_base = drvdata->fb_virt;
+       drvdata->info.fbops = &xilinxfb_ops;
+       drvdata->info.fix = xilinx_fb_fix;
+       drvdata->info.fix.smem_start = drvdata->fb_phys;
+       drvdata->info.pseudo_palette = drvdata->pseudo_palette;
+
+       if (fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0) < 0) {
+               printk(KERN_ERR "Fail to allocate colormap (%d entries)\n",
+                       PALETTE_ENTRIES_NO);
+               retval = -EFAULT;
+               goto failed3;
+       }
+
+       drvdata->info.flags = FBINFO_DEFAULT;
+       xilinx_fb_var.height = pdata->screen_height_mm;
+       xilinx_fb_var.width = pdata->screen_width_mm;
+       drvdata->info.var = xilinx_fb_var;
+
+       /* Register new frame buffer */
+       if (register_framebuffer(&drvdata->info) < 0) {
+               printk(KERN_ERR "Could not register frame buffer\n");
+               retval = -EINVAL;
+               goto failed4;
+       }
+
+       return 0;       /* success */
+
+failed4:
+       fb_dealloc_cmap(&drvdata->info.cmap);
+
+failed3:
+       dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt,
+               drvdata->fb_phys);
+
+       /* Turn off the display */
+       xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
+       iounmap(drvdata->regs);
+
+failed2:
+       release_mem_region(regs_res->start, 8);
+
+failed1:
+       kfree(drvdata);
+       dev_set_drvdata(dev, NULL);
+
+       return retval;
+}
+
+static int
+xilinxfb_drv_remove(struct device *dev)
+{
+       struct xilinxfb_drvdata *drvdata;
+
+       if (!dev)
+               return -ENODEV;
+
+       drvdata = (struct xilinxfb_drvdata *) dev_get_drvdata(dev);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+       xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info);
+#endif
+
+       unregister_framebuffer(&drvdata->info);
+
+       fb_dealloc_cmap(&drvdata->info.cmap);
+
+       dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt,
+               drvdata->fb_phys);
+
+       /* Turn off the display */
+       xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
+       iounmap(drvdata->regs);
+
+       release_mem_region(drvdata->regs_phys, 8);
+
+       kfree(drvdata);
+       dev_set_drvdata(dev, NULL);
+
+       return 0;
+}
+
+
+static struct device_driver xilinxfb_driver = {
+       .name           = DRIVER_NAME,
+       .bus            = &platform_bus_type,
+
+       .probe          = xilinxfb_drv_probe,
+       .remove         = xilinxfb_drv_remove
+};
+
+static int __init
+xilinxfb_init(void)
+{
+       /*
+        * No kernel boot options used,
+        * so we just need to register the driver
+        */
+       return driver_register(&xilinxfb_driver);
+}
+
+static void __exit
+xilinxfb_cleanup(void)
+{
+       driver_unregister(&xilinxfb_driver);
+}
+
+module_init(xilinxfb_init);
+module_exit(xilinxfb_cleanup);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_LICENSE("GPL");
index 2fb425536eaea2228e17502b5c68054aa2bf0463..8f779338f744a55f91ac6ebb23f27b0b515f97f5 100644 (file)
@@ -35,5 +35,13 @@ config W1_MASTER_DS2482
          This driver can also be built as a module.  If so, the module
          will be called ds2482.
 
+config W1_MASTER_DS1WM
+       tristate "Maxim DS1WM 1-wire busmaster"
+       depends on W1 && ARM
+       help
+         Say Y here to enable the DS1WM 1-wire driver, such as that
+         in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
+         hx4700.
+
 endmenu
 
index 4cee256a8134dcdffd4aa71e345c4050abb06747..11551b328186fb23de8a9ddc71f1a13350d802dd 100644 (file)
@@ -5,4 +5,4 @@
 obj-$(CONFIG_W1_MASTER_MATROX)         += matrox_w1.o
 obj-$(CONFIG_W1_MASTER_DS2490)         += ds2490.o
 obj-$(CONFIG_W1_MASTER_DS2482)         += ds2482.o
-
+obj-$(CONFIG_W1_MASTER_DS1WM)          += ds1wm.o
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
new file mode 100644 (file)
index 0000000..763bc73
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * 1-wire busmaster driver for DS1WM and ASICs with embedded DS1WMs
+ * such as HP iPAQs (including h5xxx, h2200, and devices with ASIC3
+ * like hx4700).
+ *
+ * Copyright (c) 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ * Copyright (c) 2004-2007, Matt Reimer <mreimer@vpop.net>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/ds1wm.h>
+
+#include <asm/io.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+
+
+#define DS1WM_CMD      0x00    /* R/W 4 bits command */
+#define DS1WM_DATA     0x01    /* R/W 8 bits, transmit/receive buffer */
+#define DS1WM_INT      0x02    /* R/W interrupt status */
+#define DS1WM_INT_EN   0x03    /* R/W interrupt enable */
+#define DS1WM_CLKDIV   0x04    /* R/W 5 bits of divisor and pre-scale */
+
+#define DS1WM_CMD_1W_RESET  (1 << 0)   /* force reset on 1-wire bus */
+#define DS1WM_CMD_SRA      (1 << 1)    /* enable Search ROM accelerator mode */
+#define DS1WM_CMD_DQ_OUTPUT (1 << 2)   /* write only - forces bus low */
+#define DS1WM_CMD_DQ_INPUT  (1 << 3)   /* read only - reflects state of bus */
+#define DS1WM_CMD_RST      (1 << 5)    /* software reset */
+#define DS1WM_CMD_OD       (1 << 7)    /* overdrive */
+
+#define DS1WM_INT_PD       (1 << 0)    /* presence detect */
+#define DS1WM_INT_PDR      (1 << 1)    /* presence detect result */
+#define DS1WM_INT_TBE      (1 << 2)    /* tx buffer empty */
+#define DS1WM_INT_TSRE     (1 << 3)    /* tx shift register empty */
+#define DS1WM_INT_RBF      (1 << 4)    /* rx buffer full */
+#define DS1WM_INT_RSRF     (1 << 5)    /* rx shift register full */
+
+#define DS1WM_INTEN_EPD            (1 << 0)    /* enable presence detect int */
+#define DS1WM_INTEN_IAS            (1 << 1)    /* INTR active state */
+#define DS1WM_INTEN_ETBE    (1 << 2)   /* enable tx buffer empty int */
+#define DS1WM_INTEN_ETMT    (1 << 3)   /* enable tx shift register empty int */
+#define DS1WM_INTEN_ERBF    (1 << 4)   /* enable rx buffer full int */
+#define DS1WM_INTEN_ERSRF   (1 << 5)   /* enable rx shift register full int */
+#define DS1WM_INTEN_DQO            (1 << 6)    /* enable direct bus driving ops */
+
+
+#define DS1WM_TIMEOUT (HZ * 5)
+
+static struct {
+       unsigned long freq;
+       unsigned long divisor;
+} freq[] = {
+       { 4000000, 0x8 },
+       { 5000000, 0x2 },
+       { 6000000, 0x5 },
+       { 7000000, 0x3 },
+       { 8000000, 0xc },
+       { 10000000, 0x6 },
+       { 12000000, 0x9 },
+       { 14000000, 0x7 },
+       { 16000000, 0x10 },
+       { 20000000, 0xa },
+       { 24000000, 0xd },
+       { 28000000, 0xb },
+       { 32000000, 0x14 },
+       { 40000000, 0xe },
+       { 48000000, 0x11 },
+       { 56000000, 0xf },
+       { 64000000, 0x18 },
+       { 80000000, 0x12 },
+       { 96000000, 0x15 },
+       { 112000000, 0x13 },
+       { 128000000, 0x1c },
+};
+
+struct ds1wm_data {
+       void            *map;
+       int             bus_shift; /* # of shifts to calc register offsets */
+       struct platform_device *pdev;
+       struct ds1wm_platform_data *pdata;
+       int             irq;
+       int             active_high;
+       struct clk      *clk;
+       int             slave_present;
+       void            *reset_complete;
+       void            *read_complete;
+       void            *write_complete;
+       u8              read_byte; /* last byte received */
+};
+
+static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg,
+                                       u8 val)
+{
+        __raw_writeb(val, ds1wm_data->map + (reg << ds1wm_data->bus_shift));
+}
+
+static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg)
+{
+        return __raw_readb(ds1wm_data->map + (reg << ds1wm_data->bus_shift));
+}
+
+
+static irqreturn_t ds1wm_isr(int isr, void *data)
+{
+       struct ds1wm_data *ds1wm_data = data;
+       u8 intr = ds1wm_read_register(ds1wm_data, DS1WM_INT);
+
+       ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1;
+
+       if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete)
+               complete(ds1wm_data->reset_complete);
+
+       if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete)
+               complete(ds1wm_data->write_complete);
+
+       if (intr & DS1WM_INT_RBF) {
+               ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data,
+                                                           DS1WM_DATA);
+               if (ds1wm_data->read_complete)
+                       complete(ds1wm_data->read_complete);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int ds1wm_reset(struct ds1wm_data *ds1wm_data)
+{
+       unsigned long timeleft;
+       DECLARE_COMPLETION_ONSTACK(reset_done);
+
+       ds1wm_data->reset_complete = &reset_done;
+
+       ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD |
+               (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0));
+
+       ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET);
+
+       timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT);
+       ds1wm_data->reset_complete = NULL;
+       if (!timeleft) {
+                dev_dbg(&ds1wm_data->pdev->dev, "reset failed\n");
+                return 1;
+       }
+
+       /* Wait for the end of the reset. According to the specs, the time
+        * from when the interrupt is asserted to the end of the reset is:
+        *     tRSTH  - tPDH  - tPDL - tPDI
+        *     625 us - 60 us - 240 us - 100 ns = 324.9 us
+        *
+        * We'll wait a bit longer just to be sure.
+        */
+       udelay(500);
+
+       ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
+               DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD |
+               (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0));
+
+       if (!ds1wm_data->slave_present) {
+                dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n");
+                return 1;
+        }
+
+        return 0;
+}
+
+static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data)
+{
+       DECLARE_COMPLETION_ONSTACK(write_done);
+       ds1wm_data->write_complete = &write_done;
+
+       ds1wm_write_register(ds1wm_data, DS1WM_DATA, data);
+
+       wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT);
+       ds1wm_data->write_complete = NULL;
+
+       return 0;
+}
+
+static int ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data)
+{
+       DECLARE_COMPLETION_ONSTACK(read_done);
+       ds1wm_data->read_complete = &read_done;
+
+       ds1wm_write(ds1wm_data, write_data);
+       wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT);
+       ds1wm_data->read_complete = NULL;
+
+       return ds1wm_data->read_byte;
+}
+
+static int ds1wm_find_divisor(int gclk)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(freq); i++)
+               if (gclk <= freq[i].freq)
+                       return freq[i].divisor;
+
+       return 0;
+}
+
+static void ds1wm_up(struct ds1wm_data *ds1wm_data)
+{
+       int gclk, divisor;
+
+       if (ds1wm_data->pdata->enable)
+               ds1wm_data->pdata->enable(ds1wm_data->pdev);
+
+       gclk = clk_get_rate(ds1wm_data->clk);
+       clk_enable(ds1wm_data->clk);
+       divisor = ds1wm_find_divisor(gclk);
+       if (divisor == 0) {
+               dev_err(&ds1wm_data->pdev->dev,
+                       "no suitable divisor for %dHz clock\n", gclk);
+               return;
+       }
+       ds1wm_write_register(ds1wm_data, DS1WM_CLKDIV, divisor);
+
+       /* Let the w1 clock stabilize. */
+       msleep(1);
+
+       ds1wm_reset(ds1wm_data);
+}
+
+static void ds1wm_down(struct ds1wm_data *ds1wm_data)
+{
+       ds1wm_reset(ds1wm_data);
+
+       /* Disable interrupts. */
+       ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
+                            ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0);
+
+       if (ds1wm_data->pdata->disable)
+               ds1wm_data->pdata->disable(ds1wm_data->pdev);
+
+       clk_disable(ds1wm_data->clk);
+}
+
+/* --------------------------------------------------------------------- */
+/* w1 methods */
+
+static u8 ds1wm_read_byte(void *data)
+{
+       struct ds1wm_data *ds1wm_data = data;
+
+       return ds1wm_read(ds1wm_data, 0xff);
+}
+
+static void ds1wm_write_byte(void *data, u8 byte)
+{
+       struct ds1wm_data *ds1wm_data = data;
+
+       ds1wm_write(ds1wm_data, byte);
+}
+
+static u8 ds1wm_reset_bus(void *data)
+{
+       struct ds1wm_data *ds1wm_data = data;
+
+       ds1wm_reset(ds1wm_data);
+
+       return 0;
+}
+
+static void ds1wm_search(void *data, u8 search_type,
+                        w1_slave_found_callback slave_found)
+{
+       struct ds1wm_data *ds1wm_data = data;
+       int i;
+       unsigned long long rom_id;
+
+       /* XXX We need to iterate for multiple devices per the DS1WM docs.
+        * See http://www.maxim-ic.com/appnotes.cfm/appnote_number/120. */
+       if (ds1wm_reset(ds1wm_data))
+               return;
+
+       ds1wm_write(ds1wm_data, search_type);
+       ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA);
+
+       for (rom_id = 0, i = 0; i < 16; i++) {
+
+               unsigned char resp, r, d;
+
+               resp = ds1wm_read(ds1wm_data, 0x00);
+
+               r = ((resp & 0x02) >> 1) |
+                   ((resp & 0x08) >> 2) |
+                   ((resp & 0x20) >> 3) |
+                   ((resp & 0x80) >> 4);
+
+               d = ((resp & 0x01) >> 0) |
+                   ((resp & 0x04) >> 1) |
+                   ((resp & 0x10) >> 2) |
+                   ((resp & 0x40) >> 3);
+
+               rom_id |= (unsigned long long) r << (i * 4);
+
+       }
+       dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX", rom_id);
+
+       ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA);
+       ds1wm_reset(ds1wm_data);
+
+       slave_found(ds1wm_data, rom_id);
+}
+
+/* --------------------------------------------------------------------- */
+
+static struct w1_bus_master ds1wm_master = {
+       .read_byte  = ds1wm_read_byte,
+       .write_byte = ds1wm_write_byte,
+       .reset_bus  = ds1wm_reset_bus,
+       .search     = ds1wm_search,
+};
+
+static int ds1wm_probe(struct platform_device *pdev)
+{
+       struct ds1wm_data *ds1wm_data;
+       struct ds1wm_platform_data *plat;
+       struct resource *res;
+       int ret;
+
+       if (!pdev)
+               return -ENODEV;
+
+       ds1wm_data = kzalloc(sizeof (*ds1wm_data), GFP_KERNEL);
+       if (!ds1wm_data)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, ds1wm_data);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENXIO;
+               goto err0;
+       }
+       ds1wm_data->map = ioremap(res->start, res->end - res->start + 1);
+       if (!ds1wm_data->map) {
+               ret = -ENOMEM;
+               goto err0;
+       }
+       plat = pdev->dev.platform_data;
+       ds1wm_data->bus_shift = plat->bus_shift;
+       ds1wm_data->pdev = pdev;
+       ds1wm_data->pdata = plat;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               ret = -ENXIO;
+               goto err1;
+       }
+       ds1wm_data->irq = res->start;
+       ds1wm_data->active_high = (res->flags & IORESOURCE_IRQ_HIGHEDGE) ?
+               1 : 0;
+
+       set_irq_type(ds1wm_data->irq, ds1wm_data->active_high ?
+                       IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING);
+
+       ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED,
+                         "ds1wm", ds1wm_data);
+       if (ret)
+               goto err1;
+
+       ds1wm_data->clk = clk_get(&pdev->dev, "ds1wm");
+       if (!ds1wm_data->clk) {
+               ret = -ENOENT;
+               goto err2;
+       }
+
+       ds1wm_up(ds1wm_data);
+
+       ds1wm_master.data = (void *)ds1wm_data;
+
+       ret = w1_add_master_device(&ds1wm_master);
+       if (ret)
+               goto err3;
+
+       return 0;
+
+err3:
+       ds1wm_down(ds1wm_data);
+       clk_put(ds1wm_data->clk);
+err2:
+       free_irq(ds1wm_data->irq, ds1wm_data);
+err1:
+       iounmap(ds1wm_data->map);
+err0:
+       kfree(ds1wm_data);
+
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int ds1wm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
+
+       ds1wm_down(ds1wm_data);
+
+       return 0;
+}
+
+static int ds1wm_resume(struct platform_device *pdev)
+{
+       struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
+
+       ds1wm_up(ds1wm_data);
+
+       return 0;
+}
+#else
+#define ds1wm_suspend NULL
+#define ds1wm_resume NULL
+#endif
+
+static int ds1wm_remove(struct platform_device *pdev)
+{
+       struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
+
+       w1_remove_master_device(&ds1wm_master);
+       ds1wm_down(ds1wm_data);
+       clk_put(ds1wm_data->clk);
+       free_irq(ds1wm_data->irq, ds1wm_data);
+       iounmap(ds1wm_data->map);
+       kfree(ds1wm_data);
+
+       return 0;
+}
+
+static struct platform_driver ds1wm_driver = {
+       .driver   = {
+               .name = "ds1wm",
+       },
+       .probe    = ds1wm_probe,
+       .remove   = ds1wm_remove,
+       .suspend  = ds1wm_suspend,
+       .resume   = ds1wm_resume
+};
+
+static int __init ds1wm_init(void)
+{
+       printk("DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko\n");
+       return platform_driver_register(&ds1wm_driver);
+}
+
+static void __exit ds1wm_exit(void)
+{
+       platform_driver_unregister(&ds1wm_driver);
+}
+
+module_init(ds1wm_init);
+module_exit(ds1wm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+             "Matt Reimer <mreimer@vpop.net>");
+MODULE_DESCRIPTION("DS1WM w1 busmaster driver");
index 63c07243993c1b1b50c007ffc6773eccf2e98441..7d6876dbcc96a6dcf5cb85f12eb3a10045e52123 100644 (file)
@@ -459,7 +459,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                 (unsigned long long) sl->reg_num.id);
 
        dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
-               &sl->dev.bus_id[0]);
+               &sl->dev.bus_id[0], sl);
 
        err = device_register(&sl->dev);
        if (err < 0) {
index 357a2e0f637a1d7270e247d146c00131d4374f62..258defdb2efd1cb82d242be2024ab49029a70e58 100644 (file)
@@ -100,7 +100,8 @@ int w1_add_master_device(struct w1_bus_master *master)
 
         /* validate minimum functionality */
         if (!(master->touch_bit && master->reset_bus) &&
-            !(master->write_bit && master->read_bit)) {
+            !(master->write_bit && master->read_bit) &&
+           !(master->write_byte && master->read_byte && master->reset_bus)) {
                printk(KERN_ERR "w1_add_master_device: invalid function set\n");
                return(-EINVAL);
         }
index bed48fa96521862d6aa26d503df589bbc4993bdd..3128aa948a4ea5bc6acdfaf6f71739a21e86743c 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/pagemap.h>
 #include <linux/idr.h>
index ddffd8aa902d65d1c389fc3a86d845ca62238210..775e26e82cbcb5ba2f53fb583d822cf362d6672c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/pagemap.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
index 3129688143ea96e4eaa9c6738a4cf19533993a66..1dd86ee90bc53eb0cf5d4d11ae40c812123f8d34 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/inet.h>
 #include <linux/idr.h>
index c7b6772538432150b0ab9e717175b108087d9de9..6e7678e4852ffa53b2e84fdd06dbf4ae8ce66b5a 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/list.h>
 #include <asm/uaccess.h>
index b01b0a457932bb19b125bf62039beddda0bf871d..7624821729a0b17131a84b4e459a8fbebb747c47 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/pagemap.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
index 0ec42f6654571b5c8aab77bd4d36d43abd058547..8eb9263a67b9c57fa408120fdd15f39a28081d1f 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
index 8ea7b04c661ff5360af30e399ea5a993889298d4..0fa0c1193e81335869c6e93e3a3df070105101b5 100644 (file)
@@ -314,7 +314,7 @@ config REISERFS_CHECK
 
 config REISERFS_PROC_INFO
        bool "Stats in /proc/fs/reiserfs"
-       depends on REISERFS_FS
+       depends on REISERFS_FS && PROC_FS
        help
          Create under /proc/fs/reiserfs a hierarchy of files, displaying
          various ReiserFS statistics and internal data at the expense of
@@ -724,10 +724,6 @@ config FAT_FS
          file system and use GNU tar's M option. GNU tar is a program
          available for Unix and DOS ("man tar" or "info tar").
 
-         It is now also becoming possible to read and write compressed FAT
-         file systems; read <file:Documentation/filesystems/fat_cvf.txt> for
-         details.
-
          The FAT support will enlarge your kernel by about 37 KB. If unsure,
          say Y.
 
index 4aa8079e71be8c7c9ffb7f92d88cd1ce852a38af..c8796906f584bdb2bffe406e186b4f17e6aa5c75 100644 (file)
@@ -628,11 +628,7 @@ static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned
                        return err;
        }
        if (to < PAGE_CACHE_SIZE) {
-               char *kaddr = kmap_atomic(page, KM_USER0);
-
-               memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, to, PAGE_CACHE_SIZE - to, KM_USER0);
                if (size > offset + to) {
                        if (size < offset + PAGE_CACHE_SIZE)
                                tmp = size & ~PAGE_CACHE_MASK;
index cf83e5d63512021e9d69c6b18ce067b9f296eea0..73ce561f3ea0c2ea5cd901156a0c3cbf730ed200 100644 (file)
@@ -22,6 +22,7 @@ kafs-objs := \
        vlclient.o \
        vlocation.o \
        vnode.o \
-       volume.o
+       volume.o \
+       write.o
 
 obj-$(CONFIG_AFS_FS)  := kafs.o
index 89e0d1650a72503d8b78ac0279378962876f4e94..2198006d2d0399d87ff019053dea6a5eb11415d5 100644 (file)
@@ -18,6 +18,8 @@
 enum AFS_FS_Operations {
        FSFETCHDATA             = 130,  /* AFS Fetch file data */
        FSFETCHSTATUS           = 132,  /* AFS Fetch file status */
+       FSSTOREDATA             = 133,  /* AFS Store file data */
+       FSSTORESTATUS           = 135,  /* AFS Store file status */
        FSREMOVEFILE            = 136,  /* AFS Remove a file */
        FSCREATEFILE            = 137,  /* AFS Create a file */
        FSRENAME                = 138,  /* AFS Rename or move a file or directory */
index 9bdbf36a9aa9ac20fe3ecb94f4403483af74ad0e..f64e40fefc02841d8c9625e556780e963c0f2090 100644 (file)
@@ -44,7 +44,7 @@ void afs_init_callback_state(struct afs_server *server)
        while (!RB_EMPTY_ROOT(&server->cb_promises)) {
                vnode = rb_entry(server->cb_promises.rb_node,
                                 struct afs_vnode, cb_promise);
-               _debug("UNPROMISE { vid=%x vn=%u uq=%u}",
+               _debug("UNPROMISE { vid=%x:%u uq=%u}",
                       vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
                rb_erase(&vnode->cb_promise, &server->cb_promises);
                vnode->cb_promised = false;
@@ -84,11 +84,8 @@ void afs_broken_callback_work(struct work_struct *work)
 
                /* if the vnode's data version number changed then its contents
                 * are different */
-               if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
-                       _debug("zap data {%x:%u}",
-                              vnode->fid.vid, vnode->fid.vnode);
-                       invalidate_remote_inode(&vnode->vfs_inode);
-               }
+               if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
+                       afs_zap_data(vnode);
        }
 
 out:
index 0c1e902f17a3d80db2e32135c0278a3130495e92..2fb31276196bbc32d5c6fab51c12b8e7132c37e2 100644 (file)
@@ -55,7 +55,8 @@ const struct inode_operations afs_dir_inode_operations = {
        .rmdir          = afs_rmdir,
        .rename         = afs_rename,
        .permission     = afs_permission,
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
+       .setattr        = afs_setattr,
 };
 
 static struct dentry_operations afs_fs_dentry_operations = {
@@ -491,7 +492,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 
        vnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},%p{%s},",
+       _enter("{%x:%u},%p{%s},",
               vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);
 
        ASSERTCMP(dentry->d_inode, ==, NULL);
@@ -731,7 +732,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%o",
+       _enter("{%x:%u},{%s},%o",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
        ret = -ENAMETOOLONG;
@@ -796,7 +797,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s}",
+       _enter("{%x:%u},{%s}",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
        ret = -ENAMETOOLONG;
@@ -842,7 +843,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s}",
+       _enter("{%x:%u},{%s}",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
        ret = -ENAMETOOLONG;
@@ -916,7 +917,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%o,",
+       _enter("{%x:%u},{%s},%o,",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
        ret = -ENAMETOOLONG;
@@ -983,7 +984,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
        vnode = AFS_FS_I(from->d_inode);
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%x:%d},{%s}",
+       _enter("{%x:%u},{%x:%u},{%s}",
               vnode->fid.vid, vnode->fid.vnode,
               dvnode->fid.vid, dvnode->fid.vnode,
               dentry->d_name.name);
@@ -1032,7 +1033,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%s",
+       _enter("{%x:%u},{%s},%s",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
               content);
 
@@ -1104,7 +1105,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        orig_dvnode = AFS_FS_I(old_dir);
        new_dvnode = AFS_FS_I(new_dir);
 
-       _enter("{%x:%d},{%x:%d},{%x:%d},{%s}",
+       _enter("{%x:%u},{%x:%u},{%x:%u},{%s}",
               orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
               vnode->fid.vid, vnode->fid.vnode,
               new_dvnode->fid.vid, new_dvnode->fid.vnode,
index ae256498f4f70684e007bae54e40ff7dd2e0b027..3e25795e5a4243ca26315d847c0e6a42fa93e087 100644 (file)
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/writeback.h>
 #include "internal.h"
 
-static int afs_file_readpage(struct file *file, struct page *page);
-static void afs_file_invalidatepage(struct page *page, unsigned long offset);
-static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
+static int afs_readpage(struct file *file, struct page *page);
+static void afs_invalidatepage(struct page *page, unsigned long offset);
+static int afs_releasepage(struct page *page, gfp_t gfp_flags);
+static int afs_launder_page(struct page *page);
 
 const struct file_operations afs_file_operations = {
        .open           = afs_open,
        .release        = afs_release,
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
+       .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
+       .aio_write      = afs_file_write,
        .mmap           = generic_file_readonly_mmap,
        .sendfile       = generic_file_sendfile,
+       .fsync          = afs_fsync,
 };
 
 const struct inode_operations afs_file_inode_operations = {
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
+       .setattr        = afs_setattr,
        .permission     = afs_permission,
 };
 
 const struct address_space_operations afs_fs_aops = {
-       .readpage       = afs_file_readpage,
-       .set_page_dirty = __set_page_dirty_nobuffers,
-       .releasepage    = afs_file_releasepage,
-       .invalidatepage = afs_file_invalidatepage,
+       .readpage       = afs_readpage,
+       .set_page_dirty = afs_set_page_dirty,
+       .launder_page   = afs_launder_page,
+       .releasepage    = afs_releasepage,
+       .invalidatepage = afs_invalidatepage,
+       .prepare_write  = afs_prepare_write,
+       .commit_write   = afs_commit_write,
+       .writepage      = afs_writepage,
+       .writepages     = afs_writepages,
 };
 
 /*
@@ -52,7 +63,7 @@ int afs_open(struct inode *inode, struct file *file)
        struct key *key;
        int ret;
 
-       _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
+       _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
 
        key = afs_request_key(vnode->volume->cell);
        if (IS_ERR(key)) {
@@ -78,7 +89,7 @@ int afs_release(struct inode *inode, struct file *file)
 {
        struct afs_vnode *vnode = AFS_FS_I(inode);
 
-       _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
+       _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
 
        key_put(file->private_data);
        _leave(" = 0");
@@ -89,10 +100,10 @@ int afs_release(struct inode *inode, struct file *file)
  * deal with notification that a page was read from the cache
  */
 #ifdef AFS_CACHING_SUPPORT
-static void afs_file_readpage_read_complete(void *cookie_data,
-                                           struct page *page,
-                                           void *data,
-                                           int error)
+static void afs_readpage_read_complete(void *cookie_data,
+                                      struct page *page,
+                                      void *data,
+                                      int error)
 {
        _enter("%p,%p,%p,%d", cookie_data, page, data, error);
 
@@ -109,10 +120,10 @@ static void afs_file_readpage_read_complete(void *cookie_data,
  * deal with notification that a page was written to the cache
  */
 #ifdef AFS_CACHING_SUPPORT
-static void afs_file_readpage_write_complete(void *cookie_data,
-                                            struct page *page,
-                                            void *data,
-                                            int error)
+static void afs_readpage_write_complete(void *cookie_data,
+                                       struct page *page,
+                                       void *data,
+                                       int error)
 {
        _enter("%p,%p,%p,%d", cookie_data, page, data, error);
 
@@ -121,9 +132,9 @@ static void afs_file_readpage_write_complete(void *cookie_data,
 #endif
 
 /*
- * AFS read page from file (or symlink)
+ * AFS read page from file, directory or symlink
  */
-static int afs_file_readpage(struct file *file, struct page *page)
+static int afs_readpage(struct file *file, struct page *page)
 {
        struct afs_vnode *vnode;
        struct inode *inode;
@@ -218,40 +229,18 @@ error:
        return ret;
 }
 
-/*
- * get a page cookie for the specified page
- */
-#ifdef AFS_CACHING_SUPPORT
-int afs_cache_get_page_cookie(struct page *page,
-                             struct cachefs_page **_page_cookie)
-{
-       int ret;
-
-       _enter("");
-       ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);
-
-       _leave(" = %d", ret);
-       return ret;
-}
-#endif
-
 /*
  * invalidate part or all of a page
  */
-static void afs_file_invalidatepage(struct page *page, unsigned long offset)
+static void afs_invalidatepage(struct page *page, unsigned long offset)
 {
        int ret = 1;
 
-       _enter("{%lu},%lu", page->index, offset);
+       kenter("{%lu},%lu", page->index, offset);
 
        BUG_ON(!PageLocked(page));
 
        if (PagePrivate(page)) {
-#ifdef AFS_CACHING_SUPPORT
-               struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-               cachefs_uncache_page(vnode->cache,page);
-#endif
-
                /* We release buffers only if the entire page is being
                 * invalidated.
                 * The get_block cached value has been unconditionally
@@ -271,26 +260,34 @@ static void afs_file_invalidatepage(struct page *page, unsigned long offset)
        _leave(" = %d", ret);
 }
 
+/*
+ * write back a dirty page
+ */
+static int afs_launder_page(struct page *page)
+{
+       _enter("{%lu}", page->index);
+
+       return 0;
+}
+
 /*
  * release a page and cleanup its private data
  */
-static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
+static int afs_releasepage(struct page *page, gfp_t gfp_flags)
 {
-       struct cachefs_page *pageio;
+       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
+       struct afs_writeback *wb;
 
-       _enter("{%lu},%x", page->index, gfp_flags);
+       _enter("{{%x:%u}[%lu],%lx},%x",
+              vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
+              gfp_flags);
 
        if (PagePrivate(page)) {
-#ifdef AFS_CACHING_SUPPORT
-               struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-               cachefs_uncache_page(vnode->cache, page);
-#endif
-
-               pageio = (struct cachefs_page *) page_private(page);
+               wb = (struct afs_writeback *) page_private(page);
+               ASSERT(wb != NULL);
                set_page_private(page, 0);
                ClearPagePrivate(page);
-
-               kfree(pageio);
+               afs_put_writeback(wb);
        }
 
        _leave(" = 0");
index e54e6c2ad343a25aba23997806a21b06dbca369a..025b1903d9e1fee96c9e9a0b65c7729235cc527c 100644 (file)
@@ -33,8 +33,10 @@ static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
  */
 static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                                      struct afs_file_status *status,
-                                     struct afs_vnode *vnode)
+                                     struct afs_vnode *vnode,
+                                     afs_dataversion_t *store_version)
 {
+       afs_dataversion_t expected_version;
        const __be32 *bp = *_bp;
        umode_t mode;
        u64 data_version, size;
@@ -101,7 +103,11 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                vnode->vfs_inode.i_atime        = vnode->vfs_inode.i_ctime;
        }
 
-       if (status->data_version != data_version) {
+       expected_version = status->data_version;
+       if (store_version)
+               expected_version = *store_version;
+
+       if (expected_version != data_version) {
                status->data_version = data_version;
                if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
                        _debug("vnode modified %llx on {%x:%u}",
@@ -110,6 +116,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                        set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
                        set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
                }
+       } else if (store_version) {
+               status->data_version = data_version;
        }
 }
 
@@ -155,6 +163,44 @@ static void xdr_decode_AFSVolSync(const __be32 **_bp,
        *_bp = bp;
 }
 
+/*
+ * encode the requested attributes into an AFSStoreStatus block
+ */
+static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
+{
+       __be32 *bp = *_bp;
+       u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
+
+       mask = 0;
+       if (attr->ia_valid & ATTR_MTIME) {
+               mask |= AFS_SET_MTIME;
+               mtime = attr->ia_mtime.tv_sec;
+       }
+
+       if (attr->ia_valid & ATTR_UID) {
+               mask |= AFS_SET_OWNER;
+               owner = attr->ia_uid;
+       }
+
+       if (attr->ia_valid & ATTR_GID) {
+               mask |= AFS_SET_GROUP;
+               group = attr->ia_gid;
+       }
+
+       if (attr->ia_valid & ATTR_MODE) {
+               mask |= AFS_SET_MODE;
+               mode = attr->ia_mode & S_IALLUGO;
+       }
+
+       *bp++ = htonl(mask);
+       *bp++ = htonl(mtime);
+       *bp++ = htonl(owner);
+       *bp++ = htonl(group);
+       *bp++ = htonl(mode);
+       *bp++ = 0;              /* segment size */
+       *_bp = bp;
+}
+
 /*
  * deliver reply data to an FS.FetchStatus
  */
@@ -175,7 +221,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call,
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
        xdr_decode_AFSCallBack(&bp, vnode);
        if (call->reply2)
                xdr_decode_AFSVolSync(&bp, call->reply2);
@@ -206,7 +252,7 @@ int afs_fs_fetch_file_status(struct afs_server *server,
        struct afs_call *call;
        __be32 *bp;
 
-       _enter(",%x,{%x:%d},,",
+       _enter(",%x,{%x:%u},,",
               key_serial(key), vnode->fid.vid, vnode->fid.vnode);
 
        call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
@@ -265,25 +311,20 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
                call->offset = 0;
                call->unmarshall++;
 
-               if (call->count < PAGE_SIZE) {
-                       page = call->reply3;
-                       buffer = kmap_atomic(page, KM_USER0);
-                       memset(buffer + PAGE_SIZE - call->count, 0,
-                              call->count);
-                       kunmap_atomic(buffer, KM_USER0);
-               }
-
                /* extract the returned data */
        case 2:
                _debug("extract data");
-               page = call->reply3;
-               buffer = kmap_atomic(page, KM_USER0);
-               ret = afs_extract_data(call, skb, last, buffer, call->count);
-               kunmap_atomic(buffer, KM_USER0);
-               switch (ret) {
-               case 0:         break;
-               case -EAGAIN:   return 0;
-               default:        return ret;
+               if (call->count > 0) {
+                       page = call->reply3;
+                       buffer = kmap_atomic(page, KM_USER0);
+                       ret = afs_extract_data(call, skb, last, buffer,
+                                              call->count);
+                       kunmap_atomic(buffer, KM_USER0);
+                       switch (ret) {
+                       case 0:         break;
+                       case -EAGAIN:   return 0;
+                       default:        return ret;
+                       }
                }
 
                call->offset = 0;
@@ -300,7 +341,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
                }
 
                bp = call->buffer;
-               xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
+               xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
                xdr_decode_AFSCallBack(&bp, vnode);
                if (call->reply2)
                        xdr_decode_AFSVolSync(&bp, call->reply2);
@@ -318,6 +359,14 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
        if (!last)
                return 0;
 
+       if (call->count < PAGE_SIZE) {
+               _debug("clear");
+               page = call->reply3;
+               buffer = kmap_atomic(page, KM_USER0);
+               memset(buffer + call->count, 0, PAGE_SIZE - call->count);
+               kunmap_atomic(buffer, KM_USER0);
+       }
+
        _leave(" = 0 [done]");
        return 0;
 }
@@ -476,8 +525,8 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call,
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
        xdr_decode_AFSFid(&bp, call->reply2);
-       xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL);
-       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
+       xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
        xdr_decode_AFSCallBack_raw(&bp, call->reply4);
        /* xdr_decode_AFSVolSync(&bp, call->replyX); */
 
@@ -574,7 +623,7 @@ static int afs_deliver_fs_remove(struct afs_call *call,
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
        /* xdr_decode_AFSVolSync(&bp, call->replyX); */
 
        _leave(" = 0 [done]");
@@ -657,8 +706,8 @@ static int afs_deliver_fs_link(struct afs_call *call,
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
-       xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode);
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
+       xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
        /* xdr_decode_AFSVolSync(&bp, call->replyX); */
 
        _leave(" = 0 [done]");
@@ -746,8 +795,8 @@ static int afs_deliver_fs_symlink(struct afs_call *call,
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
        xdr_decode_AFSFid(&bp, call->reply2);
-       xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL);
-       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
+       xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
        /* xdr_decode_AFSVolSync(&bp, call->replyX); */
 
        _leave(" = 0 [done]");
@@ -852,9 +901,10 @@ static int afs_deliver_fs_rename(struct afs_call *call,
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode);
+       xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
        if (new_dvnode != orig_dvnode)
-               xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode);
+               xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
+                                         NULL);
        /* xdr_decode_AFSVolSync(&bp, call->replyX); */
 
        _leave(" = 0 [done]");
@@ -936,3 +986,262 @@ int afs_fs_rename(struct afs_server *server,
 
        return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
 }
+
+/*
+ * deliver reply data to an FS.StoreData
+ */
+static int afs_deliver_fs_store_data(struct afs_call *call,
+                                    struct sk_buff *skb, bool last)
+{
+       struct afs_vnode *vnode = call->reply;
+       const __be32 *bp;
+
+       _enter(",,%u", last);
+
+       afs_transfer_reply(call, skb);
+       if (!last) {
+               _leave(" = 0 [more]");
+               return 0;
+       }
+
+       if (call->reply_size != call->reply_max) {
+               _leave(" = -EBADMSG [%u != %u]",
+                      call->reply_size, call->reply_max);
+               return -EBADMSG;
+       }
+
+       /* unmarshall the reply once we've received all of it */
+       bp = call->buffer;
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
+                                 &call->store_version);
+       /* xdr_decode_AFSVolSync(&bp, call->replyX); */
+
+       afs_pages_written_back(vnode, call);
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
+/*
+ * FS.StoreData operation type
+ */
+static const struct afs_call_type afs_RXFSStoreData = {
+       .name           = "FS.StoreData",
+       .deliver        = afs_deliver_fs_store_data,
+       .abort_to_error = afs_abort_to_error,
+       .destructor     = afs_flat_call_destructor,
+};
+
+/*
+ * store a set of pages
+ */
+int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
+                     pgoff_t first, pgoff_t last,
+                     unsigned offset, unsigned to,
+                     const struct afs_wait_mode *wait_mode)
+{
+       struct afs_vnode *vnode = wb->vnode;
+       struct afs_call *call;
+       loff_t size, pos, i_size;
+       __be32 *bp;
+
+       _enter(",%x,{%x:%u},,",
+              key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
+
+       size = to - offset;
+       if (first != last)
+               size += (loff_t)(last - first) << PAGE_SHIFT;
+       pos = (loff_t)first << PAGE_SHIFT;
+       pos += offset;
+
+       i_size = i_size_read(&vnode->vfs_inode);
+       if (pos + size > i_size)
+               i_size = size + pos;
+
+       _debug("size %llx, at %llx, i_size %llx",
+              (unsigned long long) size, (unsigned long long) pos,
+              (unsigned long long) i_size);
+
+       BUG_ON(i_size > 0xffffffff); // TODO: use 64-bit store
+
+       call = afs_alloc_flat_call(&afs_RXFSStoreData,
+                                  (4 + 6 + 3) * 4,
+                                  (21 + 6) * 4);
+       if (!call)
+               return -ENOMEM;
+
+       call->wb = wb;
+       call->key = wb->key;
+       call->reply = vnode;
+       call->service_id = FS_SERVICE;
+       call->port = htons(AFS_FS_PORT);
+       call->mapping = vnode->vfs_inode.i_mapping;
+       call->first = first;
+       call->last = last;
+       call->first_offset = offset;
+       call->last_to = to;
+       call->send_pages = true;
+       call->store_version = vnode->status.data_version + 1;
+
+       /* marshall the parameters */
+       bp = call->request;
+       *bp++ = htonl(FSSTOREDATA);
+       *bp++ = htonl(vnode->fid.vid);
+       *bp++ = htonl(vnode->fid.vnode);
+       *bp++ = htonl(vnode->fid.unique);
+
+       *bp++ = 0; /* mask */
+       *bp++ = 0; /* mtime */
+       *bp++ = 0; /* owner */
+       *bp++ = 0; /* group */
+       *bp++ = 0; /* unix mode */
+       *bp++ = 0; /* segment size */
+
+       *bp++ = htonl(pos);
+       *bp++ = htonl(size);
+       *bp++ = htonl(i_size);
+
+       return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * deliver reply data to an FS.StoreStatus
+ */
+static int afs_deliver_fs_store_status(struct afs_call *call,
+                                      struct sk_buff *skb, bool last)
+{
+       afs_dataversion_t *store_version;
+       struct afs_vnode *vnode = call->reply;
+       const __be32 *bp;
+
+       _enter(",,%u", last);
+
+       afs_transfer_reply(call, skb);
+       if (!last) {
+               _leave(" = 0 [more]");
+               return 0;
+       }
+
+       if (call->reply_size != call->reply_max) {
+               _leave(" = -EBADMSG [%u != %u]",
+                      call->reply_size, call->reply_max);
+               return -EBADMSG;
+       }
+
+       /* unmarshall the reply once we've received all of it */
+       store_version = NULL;
+       if (call->operation_ID == FSSTOREDATA)
+               store_version = &call->store_version;
+
+       bp = call->buffer;
+       xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
+       /* xdr_decode_AFSVolSync(&bp, call->replyX); */
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
+/*
+ * FS.StoreStatus operation type
+ */
+static const struct afs_call_type afs_RXFSStoreStatus = {
+       .name           = "FS.StoreStatus",
+       .deliver        = afs_deliver_fs_store_status,
+       .abort_to_error = afs_abort_to_error,
+       .destructor     = afs_flat_call_destructor,
+};
+
+static const struct afs_call_type afs_RXFSStoreData_as_Status = {
+       .name           = "FS.StoreData",
+       .deliver        = afs_deliver_fs_store_status,
+       .abort_to_error = afs_abort_to_error,
+       .destructor     = afs_flat_call_destructor,
+};
+
+/*
+ * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
+ * so as to alter the file size also
+ */
+static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
+                              struct afs_vnode *vnode, struct iattr *attr,
+                              const struct afs_wait_mode *wait_mode)
+{
+       struct afs_call *call;
+       __be32 *bp;
+
+       _enter(",%x,{%x:%u},,",
+              key_serial(key), vnode->fid.vid, vnode->fid.vnode);
+
+       ASSERT(attr->ia_valid & ATTR_SIZE);
+       ASSERTCMP(attr->ia_size, <=, 0xffffffff); // TODO: use 64-bit store
+
+       call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
+                                  (4 + 6 + 3) * 4,
+                                  (21 + 6) * 4);
+       if (!call)
+               return -ENOMEM;
+
+       call->key = key;
+       call->reply = vnode;
+       call->service_id = FS_SERVICE;
+       call->port = htons(AFS_FS_PORT);
+       call->store_version = vnode->status.data_version + 1;
+       call->operation_ID = FSSTOREDATA;
+
+       /* marshall the parameters */
+       bp = call->request;
+       *bp++ = htonl(FSSTOREDATA);
+       *bp++ = htonl(vnode->fid.vid);
+       *bp++ = htonl(vnode->fid.vnode);
+       *bp++ = htonl(vnode->fid.unique);
+
+       xdr_encode_AFS_StoreStatus(&bp, attr);
+
+       *bp++ = 0;                              /* position of start of write */
+       *bp++ = 0;                              /* size of write */
+       *bp++ = htonl(attr->ia_size);           /* new file length */
+
+       return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * set the attributes on a file, using FS.StoreData if there's a change in file
+ * size, and FS.StoreStatus otherwise
+ */
+int afs_fs_setattr(struct afs_server *server, struct key *key,
+                  struct afs_vnode *vnode, struct iattr *attr,
+                  const struct afs_wait_mode *wait_mode)
+{
+       struct afs_call *call;
+       __be32 *bp;
+
+       if (attr->ia_valid & ATTR_SIZE)
+               return afs_fs_setattr_size(server, key, vnode, attr,
+                                          wait_mode);
+
+       _enter(",%x,{%x:%u},,",
+              key_serial(key), vnode->fid.vid, vnode->fid.vnode);
+
+       call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
+                                  (4 + 6) * 4,
+                                  (21 + 6) * 4);
+       if (!call)
+               return -ENOMEM;
+
+       call->key = key;
+       call->reply = vnode;
+       call->service_id = FS_SERVICE;
+       call->port = htons(AFS_FS_PORT);
+       call->operation_ID = FSSTORESTATUS;
+
+       /* marshall the parameters */
+       bp = call->request;
+       *bp++ = htonl(FSSTORESTATUS);
+       *bp++ = htonl(vnode->fid.vid);
+       *bp++ = htonl(vnode->fid.vnode);
+       *bp++ = htonl(vnode->fid.unique);
+
+       xdr_encode_AFS_StoreStatus(&bp, attr);
+
+       return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
index c184a4ee59950ddf48a69a1cd3f555134a465029..515a5d12d8fb5d49d69a6f896ac33c2dfdbdf859 100644 (file)
@@ -125,7 +125,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
        struct inode *inode;
        int ret;
 
-       _enter(",{%u,%u,%u},,", fid->vid, fid->vnode, fid->unique);
+       _enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);
 
        as = sb->s_fs_info;
        data.volume = as->volume;
@@ -203,6 +203,19 @@ bad_inode:
        return ERR_PTR(ret);
 }
 
+/*
+ * mark the data attached to an inode as obsolete due to a write on the server
+ * - might also want to ditch all the outstanding writes and dirty pages
+ */
+void afs_zap_data(struct afs_vnode *vnode)
+{
+       _enter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+       /* nuke all the non-dirty pages that aren't locked, mapped or being
+        * written back */
+       invalidate_remote_inode(&vnode->vfs_inode);
+}
+
 /*
  * validate a vnode/inode
  * - there are several things we need to check
@@ -258,10 +271,8 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
 
        /* if the vnode's data version number changed then its contents are
         * different */
-       if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
-               _debug("zap data {%x:%d}", vnode->fid.vid, vnode->fid.vnode);
-               invalidate_remote_inode(&vnode->vfs_inode);
-       }
+       if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
+               afs_zap_data(vnode);
 
        clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
        mutex_unlock(&vnode->validate_lock);
@@ -278,7 +289,7 @@ error_unlock:
 /*
  * read the attributes of an inode
  */
-int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
+int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
                      struct kstat *stat)
 {
        struct inode *inode;
@@ -301,7 +312,7 @@ void afs_clear_inode(struct inode *inode)
 
        vnode = AFS_FS_I(inode);
 
-       _enter("{%x:%d.%d} v=%u x=%u t=%u }",
+       _enter("{%x:%u.%d} v=%u x=%u t=%u }",
               vnode->fid.vid,
               vnode->fid.vnode,
               vnode->fid.unique,
@@ -323,6 +334,7 @@ void afs_clear_inode(struct inode *inode)
                vnode->server = NULL;
        }
 
+       ASSERT(list_empty(&vnode->writebacks));
        ASSERT(!vnode->cb_promised);
 
 #ifdef AFS_CACHING_SUPPORT
@@ -339,3 +351,47 @@ void afs_clear_inode(struct inode *inode)
 
        _leave("");
 }
+
+/*
+ * set the attributes of an inode
+ */
+int afs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+       struct key *key;
+       int ret;
+
+       _enter("{%x:%u},{n=%s},%x",
+              vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
+              attr->ia_valid);
+
+       if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
+                               ATTR_MTIME))) {
+               _leave(" = 0 [unsupported]");
+               return 0;
+       }
+
+       /* flush any dirty data outstanding on a regular file */
+       if (S_ISREG(vnode->vfs_inode.i_mode)) {
+               filemap_write_and_wait(vnode->vfs_inode.i_mapping);
+               afs_writeback_all(vnode);
+       }
+
+       if (attr->ia_valid & ATTR_FILE) {
+               key = attr->ia_file->private_data;
+       } else {
+               key = afs_request_key(vnode->volume->cell);
+               if (IS_ERR(key)) {
+                       ret = PTR_ERR(key);
+                       goto error;
+               }
+       }
+
+       ret = afs_vnode_setattr(vnode, key, attr);
+       if (!(attr->ia_valid & ATTR_FILE))
+               key_put(key);
+
+error:
+       _leave(" = %d", ret);
+       return ret;
+}
index d90c158cd9346d46c0abbb9dd01dcacf6b1c30f2..a30d4fa768e34d3f6016762190d0d89ba8f915c7 100644 (file)
@@ -21,6 +21,7 @@
 
 #define AFS_CELL_MAX_ADDRS 15
 
+struct pagevec;
 struct afs_call;
 
 typedef enum {
@@ -75,12 +76,15 @@ struct afs_call {
        struct key              *key;           /* security for this call */
        struct afs_server       *server;        /* server affected by incoming CM call */
        void                    *request;       /* request data (first part) */
-       void                    *request2;      /* request data (second part) */
+       struct address_space    *mapping;       /* page set */
+       struct afs_writeback    *wb;            /* writeback being performed */
        void                    *buffer;        /* reply receive buffer */
        void                    *reply;         /* reply buffer (first part) */
        void                    *reply2;        /* reply buffer (second part) */
        void                    *reply3;        /* reply buffer (third part) */
        void                    *reply4;        /* reply buffer (fourth part) */
+       pgoff_t                 first;          /* first page in mapping to deal with */
+       pgoff_t                 last;           /* last page in mapping to deal with */
        enum {                                  /* call state */
                AFS_CALL_REQUESTING,    /* request is being sent for outgoing call */
                AFS_CALL_AWAIT_REPLY,   /* awaiting reply to outgoing call */
@@ -97,14 +101,18 @@ struct afs_call {
        unsigned                request_size;   /* size of request data */
        unsigned                reply_max;      /* maximum size of reply */
        unsigned                reply_size;     /* current size of reply */
+       unsigned                first_offset;   /* offset into mapping[first] */
+       unsigned                last_to;        /* amount of mapping[last] */
        unsigned short          offset;         /* offset into received data store */
        unsigned char           unmarshall;     /* unmarshalling phase */
        bool                    incoming;       /* T if incoming call */
+       bool                    send_pages;     /* T if data from mapping should be sent */
        u16                     service_id;     /* RxRPC service ID to call */
        __be16                  port;           /* target UDP port */
        __be32                  operation_ID;   /* operation ID for an incoming call */
        u32                     count;          /* count for use in unmarshalling */
        __be32                  tmp;            /* place to extract temporary data */
+       afs_dataversion_t       store_version;  /* updated version expected from store */
 };
 
 struct afs_call_type {
@@ -123,6 +131,32 @@ struct afs_call_type {
        void (*destructor)(struct afs_call *call);
 };
 
+/*
+ * record of an outstanding writeback on a vnode
+ */
+struct afs_writeback {
+       struct list_head        link;           /* link in vnode->writebacks */
+       struct work_struct      writer;         /* work item to perform the writeback */
+       struct afs_vnode        *vnode;         /* vnode to which this write applies */
+       struct key              *key;           /* owner of this write */
+       wait_queue_head_t       waitq;          /* completion and ready wait queue */
+       pgoff_t                 first;          /* first page in batch */
+       pgoff_t                 point;          /* last page in current store op */
+       pgoff_t                 last;           /* last page in batch (inclusive) */
+       unsigned                offset_first;   /* offset into first page of start of write */
+       unsigned                to_last;        /* offset into last page of end of write */
+       int                     num_conflicts;  /* count of conflicting writes in list */
+       int                     usage;
+       bool                    conflicts;      /* T if has dependent conflicts */
+       enum {
+               AFS_WBACK_SYNCING,              /* synchronisation being performed */
+               AFS_WBACK_PENDING,              /* write pending */
+               AFS_WBACK_CONFLICTING,          /* conflicting writes posted */
+               AFS_WBACK_WRITING,              /* writing back */
+               AFS_WBACK_COMPLETE              /* the writeback record has been unlinked */
+       } state __attribute__((packed));
+};
+
 /*
  * AFS superblock private data
  * - there's one superblock per volume
@@ -305,6 +339,7 @@ struct afs_vnode {
        wait_queue_head_t       update_waitq;   /* status fetch waitqueue */
        int                     update_cnt;     /* number of outstanding ops that will update the
                                                 * status */
+       spinlock_t              writeback_lock; /* lock for writebacks */
        spinlock_t              lock;           /* waitqueue/flags lock */
        unsigned long           flags;
 #define AFS_VNODE_CB_BROKEN    0               /* set if vnode's callback was broken */
@@ -316,6 +351,8 @@ struct afs_vnode {
 
        long                    acl_order;      /* ACL check count (callback break count) */
 
+       struct list_head        writebacks;     /* alterations in pagecache that need writing */
+
        /* outstanding callback notification on this file */
        struct rb_node          server_rb;      /* link in server->fs_vnodes */
        struct rb_node          cb_promise;     /* link in server->cb_promises */
@@ -433,10 +470,6 @@ extern const struct file_operations afs_file_operations;
 extern int afs_open(struct inode *, struct file *);
 extern int afs_release(struct inode *, struct file *);
 
-#ifdef AFS_CACHING_SUPPORT
-extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
-#endif
-
 /*
  * fsclient.c
  */
@@ -467,6 +500,12 @@ extern int afs_fs_rename(struct afs_server *, struct key *,
                         struct afs_vnode *, const char *,
                         struct afs_vnode *, const char *,
                         const struct afs_wait_mode *);
+extern int afs_fs_store_data(struct afs_server *, struct afs_writeback *,
+                            pgoff_t, pgoff_t, unsigned, unsigned,
+                            const struct afs_wait_mode *);
+extern int afs_fs_setattr(struct afs_server *, struct key *,
+                         struct afs_vnode *, struct iattr *,
+                         const struct afs_wait_mode *);
 
 /*
  * inode.c
@@ -474,10 +513,10 @@ extern int afs_fs_rename(struct afs_server *, struct key *,
 extern struct inode *afs_iget(struct super_block *, struct key *,
                              struct afs_fid *, struct afs_file_status *,
                              struct afs_callback *);
+extern void afs_zap_data(struct afs_vnode *);
 extern int afs_validate(struct afs_vnode *, struct key *);
-extern int afs_inode_getattr(struct vfsmount *, struct dentry *,
-                            struct kstat *);
-extern void afs_zap_permits(struct rcu_head *);
+extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int afs_setattr(struct dentry *, struct iattr *);
 extern void afs_clear_inode(struct inode *);
 
 /*
@@ -533,6 +572,7 @@ extern int afs_extract_data(struct afs_call *, struct sk_buff *, bool, void *,
  */
 extern void afs_clear_permits(struct afs_vnode *);
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
+extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
 extern int afs_permission(struct inode *, int, struct nameidata *);
 
@@ -629,6 +669,9 @@ extern int afs_vnode_symlink(struct afs_vnode *, struct key *, const char *,
                             struct afs_file_status *, struct afs_server **);
 extern int afs_vnode_rename(struct afs_vnode *, struct afs_vnode *,
                            struct key *, const char *, const char *);
+extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t,
+                               unsigned, unsigned);
+extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
 
 /*
  * volume.c
@@ -645,6 +688,23 @@ extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *);
 extern int afs_volume_release_fileserver(struct afs_vnode *,
                                         struct afs_server *, int);
 
+/*
+ * write.c
+ */
+extern int afs_set_page_dirty(struct page *);
+extern void afs_put_writeback(struct afs_writeback *);
+extern int afs_prepare_write(struct file *, struct page *, unsigned, unsigned);
+extern int afs_commit_write(struct file *, struct page *, unsigned, unsigned);
+extern int afs_writepage(struct page *, struct writeback_control *);
+extern int afs_writepages(struct address_space *, struct writeback_control *);
+extern int afs_write_inode(struct inode *, int);
+extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
+extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
+                             unsigned long, loff_t);
+extern int afs_writeback_all(struct afs_vnode *);
+extern int afs_fsync(struct file *, struct dentry *, int);
+
+
 /*****************************************************************************/
 /*
  * debug tracing
@@ -726,6 +786,21 @@ do {                                                                       \
        }                                                               \
 } while(0)
 
+#define ASSERTRANGE(L, OP1, N, OP2, H)                                 \
+do {                                                                   \
+       if (unlikely(!((L) OP1 (N)) || !((N) OP2 (H)))) {               \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "AFS: Assertion failed\n");             \
+               printk(KERN_ERR "%lu "#OP1" %lu "#OP2" %lu is false\n", \
+                      (unsigned long)(L), (unsigned long)(N),          \
+                      (unsigned long)(H));                             \
+               printk(KERN_ERR "0x%lx "#OP1" 0x%lx "#OP2" 0x%lx is false\n", \
+                      (unsigned long)(L), (unsigned long)(N),          \
+                      (unsigned long)(H));                             \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
 #define ASSERTIF(C, X)                                         \
 do {                                                           \
        if (unlikely((C) && !(X))) {                            \
@@ -758,6 +833,10 @@ do {                                               \
 do {                                           \
 } while(0)
 
+#define ASSERTRANGE(L, OP1, N, OP2, H)         \
+do {                                           \
+} while(0)
+
 #define ASSERTIF(C, X)                         \
 do {                                           \
 } while(0)
index 80ec6fd19a733fb50efb3fb896061fea76a08298..f1f71ff7d5c673ccccffd02f965224ea51456934 100644 (file)
@@ -149,6 +149,7 @@ error_cache:
        afs_vlocation_purge();
        afs_cell_purge();
        afs_proc_cleanup();
+       rcu_barrier();
        printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
        return ret;
 }
@@ -176,6 +177,7 @@ static void __exit afs_exit(void)
        cachefs_unregister_netfs(&afs_cache_netfs);
 #endif
        afs_proc_cleanup();
+       rcu_barrier();
 }
 
 module_exit(afs_exit);
index cdb9792d8161eb0324fdf3c6315cfae435d0b86a..d1a889c4074292b8dbf6d4f251497e681067cd1a 100644 (file)
@@ -22,6 +22,7 @@ int afs_abort_to_error(u32 abort_code)
 {
        switch (abort_code) {
        case 13:                return -EACCES;
+       case 27:                return -EFBIG;
        case 30:                return -EROFS;
        case VSALVAGE:          return -EIO;
        case VNOVNODE:          return -ENOENT;
index 034fcfd4e3304d2ff6942c2a91c5ab6237460558..a3684dcc76e7985a4a2b53ea32c81cd12f61cd86 100644 (file)
@@ -36,7 +36,7 @@ const struct inode_operations afs_mntpt_inode_operations = {
        .lookup         = afs_mntpt_lookup,
        .follow_link    = afs_mntpt_follow_link,
        .readlink       = page_readlink,
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
 };
 
 static LIST_HEAD(afs_vfsmounts);
@@ -58,7 +58,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
        char *buf;
        int ret;
 
-       _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
+       _enter("{%x:%u,%u}",
+              vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
 
        /* read the contents of the symlink into the pagecache */
        page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file);
index 222c1a3abbb8fdbcf30a6c9fd48c25b0d34f1b25..04189c47d6a08eedf89184a1cd5739e24275ec15 100644 (file)
@@ -236,6 +236,70 @@ void afs_flat_call_destructor(struct afs_call *call)
        call->buffer = NULL;
 }
 
+/*
+ * attach the data from a bunch of pages on an inode to a call
+ */
+int afs_send_pages(struct afs_call *call, struct msghdr *msg, struct kvec *iov)
+{
+       struct page *pages[8];
+       unsigned count, n, loop, offset, to;
+       pgoff_t first = call->first, last = call->last;
+       int ret;
+
+       _enter("");
+
+       offset = call->first_offset;
+       call->first_offset = 0;
+
+       do {
+               _debug("attach %lx-%lx", first, last);
+
+               count = last - first + 1;
+               if (count > ARRAY_SIZE(pages))
+                       count = ARRAY_SIZE(pages);
+               n = find_get_pages_contig(call->mapping, first, count, pages);
+               ASSERTCMP(n, ==, count);
+
+               loop = 0;
+               do {
+                       msg->msg_flags = 0;
+                       to = PAGE_SIZE;
+                       if (first + loop >= last)
+                               to = call->last_to;
+                       else
+                               msg->msg_flags = MSG_MORE;
+                       iov->iov_base = kmap(pages[loop]) + offset;
+                       iov->iov_len = to - offset;
+                       offset = 0;
+
+                       _debug("- range %u-%u%s",
+                              offset, to, msg->msg_flags ? " [more]" : "");
+                       msg->msg_iov = (struct iovec *) iov;
+                       msg->msg_iovlen = 1;
+
+                       /* have to change the state *before* sending the last
+                        * packet as RxRPC might give us the reply before it
+                        * returns from sending the request */
+                       if (first + loop >= last)
+                               call->state = AFS_CALL_AWAIT_REPLY;
+                       ret = rxrpc_kernel_send_data(call->rxcall, msg,
+                                                    to - offset);
+                       kunmap(pages[loop]);
+                       if (ret < 0)
+                               break;
+               } while (++loop < count);
+               first += count;
+
+               for (loop = 0; loop < count; loop++)
+                       put_page(pages[loop]);
+               if (ret < 0)
+                       break;
+       } while (first < last);
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
 /*
  * initiate a call
  */
@@ -253,8 +317,9 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        ASSERT(call->type != NULL);
        ASSERT(call->type->name != NULL);
 
-       _debug("MAKE %p{%s} [%d]",
-              call, call->type->name, atomic_read(&afs_outstanding_calls));
+       _debug("____MAKE %p{%s,%x} [%d]____",
+              call, call->type->name, key_serial(call->key),
+              atomic_read(&afs_outstanding_calls));
 
        call->wait_mode = wait_mode;
        INIT_WORK(&call->async_work, afs_process_async_call);
@@ -289,16 +354,23 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        msg.msg_iovlen          = 1;
        msg.msg_control         = NULL;
        msg.msg_controllen      = 0;
-       msg.msg_flags           = 0;
+       msg.msg_flags           = (call->send_pages ? MSG_MORE : 0);
 
        /* have to change the state *before* sending the last packet as RxRPC
         * might give us the reply before it returns from sending the
         * request */
-       call->state = AFS_CALL_AWAIT_REPLY;
+       if (!call->send_pages)
+               call->state = AFS_CALL_AWAIT_REPLY;
        ret = rxrpc_kernel_send_data(rxcall, &msg, call->request_size);
        if (ret < 0)
                goto error_do_abort;
 
+       if (call->send_pages) {
+               ret = afs_send_pages(call, &msg, iov);
+               if (ret < 0)
+                       goto error_do_abort;
+       }
+
        /* at this point, an async call may no longer exist as it may have
         * already completed */
        return wait_mode->wait(call);
index f9f424d804589aa108d0d19821521bb6386e9bbc..e0ea88b63ebf429e7d2ec45c7f6377b24ab27364 100644 (file)
@@ -109,7 +109,7 @@ void afs_clear_permits(struct afs_vnode *vnode)
 {
        struct afs_permits *permits;
 
-       _enter("{%x}", vnode->fid.vnode);
+       _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
 
        mutex_lock(&vnode->permits_lock);
        permits = vnode->permits;
@@ -132,7 +132,8 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, long acl_order)
        struct afs_vnode *auth_vnode;
        int count, loop;
 
-       _enter("{%x},%x,%lx", vnode->fid.vnode, key_serial(key), acl_order);
+       _enter("{%x:%u},%x,%lx",
+              vnode->fid.vid, vnode->fid.vnode, key_serial(key), acl_order);
 
        auth_vnode = afs_get_auth_inode(vnode, key);
        if (IS_ERR(auth_vnode)) {
@@ -220,7 +221,8 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
        bool valid;
        int loop, ret;
 
-       _enter("");
+       _enter("{%x:%u},%x",
+              vnode->fid.vid, vnode->fid.vnode, key_serial(key));
 
        auth_vnode = afs_get_auth_inode(vnode, key);
        if (IS_ERR(auth_vnode)) {
@@ -268,9 +270,9 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
                        _leave(" = %d", ret);
                        return ret;
                }
+               *_access = vnode->status.caller_access;
        }
 
-       *_access = vnode->status.caller_access;
        iput(&auth_vnode->vfs_inode);
        _leave(" = 0 [access %x]", *_access);
        return 0;
@@ -288,7 +290,7 @@ int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
        struct key *key;
        int ret;
 
-       _enter("{{%x:%x},%lx},%x,",
+       _enter("{{%x:%u},%lx},%x,",
               vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);
 
        key = afs_request_key(vnode->volume->cell);
index 96bb23b476a2f4282a03a07a9a146d2e4d1b2e24..231ae4150279e2b98f78dac4b9a45ec5bde26633 100644 (file)
@@ -252,6 +252,9 @@ static void afs_destroy_server(struct afs_server *server)
 {
        _enter("%p", server);
 
+       ASSERTIF(server->cb_break_head != server->cb_break_tail,
+                delayed_work_pending(&server->cb_break_work));
+
        ASSERTCMP(server->fs_vnodes.rb_node, ==, NULL);
        ASSERTCMP(server->cb_promises.rb_node, ==, NULL);
        ASSERTCMP(server->cb_break_head, ==, server->cb_break_tail);
index 7030d76155fcdf42398ccc71e8a6c8af17237d9a..d24be334b6089c592068634de7f613d8f2114f27 100644 (file)
@@ -50,6 +50,7 @@ static const struct super_operations afs_super_ops = {
        .statfs         = simple_statfs,
        .alloc_inode    = afs_alloc_inode,
        .drop_inode     = generic_delete_inode,
+       .write_inode    = afs_write_inode,
        .destroy_inode  = afs_destroy_inode,
        .clear_inode    = afs_clear_inode,
        .umount_begin   = afs_umount_begin,
@@ -66,7 +67,7 @@ enum {
        afs_opt_vol,
 };
 
-static const match_table_t afs_options_list = {
+static match_table_t afs_options_list = {
        { afs_opt_cell,         "cell=%s"       },
        { afs_opt_rwpath,       "rwpath"        },
        { afs_opt_vol,          "vol=%s"        },
@@ -459,7 +460,9 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
                init_waitqueue_head(&vnode->update_waitq);
                mutex_init(&vnode->permits_lock);
                mutex_init(&vnode->validate_lock);
+               spin_lock_init(&vnode->writeback_lock);
                spin_lock_init(&vnode->lock);
+               INIT_LIST_HEAD(&vnode->writebacks);
                INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
        }
 }
index a1904ab8426adb12fdecfcc3a353da6b909bdee1..ec814660209faf83abe40e3a9a831d445243dba3 100644 (file)
@@ -261,7 +261,7 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode,
 
        DECLARE_WAITQUEUE(myself, current);
 
-       _enter("%s,{%u,%u,%u}",
+       _enter("%s,{%x:%u.%u}",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
 
@@ -389,7 +389,7 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,,,",
+       _enter("%s{%x:%u.%u},%x,,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
@@ -446,7 +446,7 @@ int afs_vnode_create(struct afs_vnode *vnode, struct key *key,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s,,",
+       _enter("%s{%x:%u.%u},%x,%s,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
@@ -502,7 +502,7 @@ int afs_vnode_remove(struct afs_vnode *vnode, struct key *key, const char *name,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s",
+       _enter("%s{%x:%u.%u},%x,%s",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
@@ -557,7 +557,7 @@ extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%s{%u,%u,%u},%x,%s",
+       _enter("%s{%x:%u.%u},%s{%x:%u.%u},%x,%s",
               dvnode->volume->vlocation->vldb.name,
               dvnode->fid.vid,
               dvnode->fid.vnode,
@@ -628,7 +628,7 @@ int afs_vnode_symlink(struct afs_vnode *vnode, struct key *key,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s,%s,,,",
+       _enter("%s{%x:%u.%u},%x,%s,%s,,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
@@ -687,7 +687,7 @@ int afs_vnode_rename(struct afs_vnode *orig_dvnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%s{%u,%u,%u},%x,%s,%s",
+       _enter("%s{%x:%u.%u},%s{%u,%u,%u},%x,%s,%s",
               orig_dvnode->volume->vlocation->vldb.name,
               orig_dvnode->fid.vid,
               orig_dvnode->fid.vnode,
@@ -753,3 +753,110 @@ no_server:
        _leave(" = %ld [cnt %d]", PTR_ERR(server), orig_dvnode->update_cnt);
        return PTR_ERR(server);
 }
+
+/*
+ * write to a file
+ */
+int afs_vnode_store_data(struct afs_writeback *wb, pgoff_t first, pgoff_t last,
+                        unsigned offset, unsigned to)
+{
+       struct afs_server *server;
+       struct afs_vnode *vnode = wb->vnode;
+       int ret;
+
+       _enter("%s{%x:%u.%u},%x,%lx,%lx,%x,%x",
+              vnode->volume->vlocation->vldb.name,
+              vnode->fid.vid,
+              vnode->fid.vnode,
+              vnode->fid.unique,
+              key_serial(wb->key),
+              first, last, offset, to);
+
+       /* this op will fetch the status */
+       spin_lock(&vnode->lock);
+       vnode->update_cnt++;
+       spin_unlock(&vnode->lock);
+
+       do {
+               /* pick a server to query */
+               server = afs_volume_pick_fileserver(vnode);
+               if (IS_ERR(server))
+                       goto no_server;
+
+               _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+               ret = afs_fs_store_data(server, wb, first, last, offset, to,
+                                       &afs_sync_call);
+
+       } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+       /* adjust the flags */
+       if (ret == 0) {
+               afs_vnode_finalise_status_update(vnode, server);
+               afs_put_server(server);
+       } else {
+               afs_vnode_status_update_failed(vnode, ret);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+no_server:
+       spin_lock(&vnode->lock);
+       vnode->update_cnt--;
+       ASSERTCMP(vnode->update_cnt, >=, 0);
+       spin_unlock(&vnode->lock);
+       return PTR_ERR(server);
+}
+
+/*
+ * set the attributes on a file
+ */
+int afs_vnode_setattr(struct afs_vnode *vnode, struct key *key,
+                     struct iattr *attr)
+{
+       struct afs_server *server;
+       int ret;
+
+       _enter("%s{%x:%u.%u},%x",
+              vnode->volume->vlocation->vldb.name,
+              vnode->fid.vid,
+              vnode->fid.vnode,
+              vnode->fid.unique,
+              key_serial(key));
+
+       /* this op will fetch the status */
+       spin_lock(&vnode->lock);
+       vnode->update_cnt++;
+       spin_unlock(&vnode->lock);
+
+       do {
+               /* pick a server to query */
+               server = afs_volume_pick_fileserver(vnode);
+               if (IS_ERR(server))
+                       goto no_server;
+
+               _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+               ret = afs_fs_setattr(server, key, vnode, attr, &afs_sync_call);
+
+       } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+       /* adjust the flags */
+       if (ret == 0) {
+               afs_vnode_finalise_status_update(vnode, server);
+               afs_put_server(server);
+       } else {
+               afs_vnode_status_update_failed(vnode, ret);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+no_server:
+       spin_lock(&vnode->lock);
+       vnode->update_cnt--;
+       ASSERTCMP(vnode->update_cnt, >=, 0);
+       spin_unlock(&vnode->lock);
+       return PTR_ERR(server);
+}
diff --git a/fs/afs/write.c b/fs/afs/write.c
new file mode 100644 (file)
index 0000000..83ff292
--- /dev/null
@@ -0,0 +1,835 @@
+/* handling of writes to regular files and writing back to the server
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/writeback.h>
+#include <linux/pagevec.h>
+#include "internal.h"
+
+static int afs_write_back_from_locked_page(struct afs_writeback *wb,
+                                          struct page *page);
+
+/*
+ * mark a page as having been made dirty and thus needing writeback
+ */
+int afs_set_page_dirty(struct page *page)
+{
+       _enter("");
+       return __set_page_dirty_nobuffers(page);
+}
+
+/*
+ * unlink a writeback record because its usage has reached zero
+ * - must be called with the wb->vnode->writeback_lock held
+ */
+static void afs_unlink_writeback(struct afs_writeback *wb)
+{
+       struct afs_writeback *front;
+       struct afs_vnode *vnode = wb->vnode;
+
+       list_del_init(&wb->link);
+       if (!list_empty(&vnode->writebacks)) {
+               /* if an fsync rises to the front of the queue then wake it
+                * up */
+               front = list_entry(vnode->writebacks.next,
+                                  struct afs_writeback, link);
+               if (front->state == AFS_WBACK_SYNCING) {
+                       _debug("wake up sync");
+                       front->state = AFS_WBACK_COMPLETE;
+                       wake_up(&front->waitq);
+               }
+       }
+}
+
+/*
+ * free a writeback record
+ */
+static void afs_free_writeback(struct afs_writeback *wb)
+{
+       _enter("");
+       key_put(wb->key);
+       kfree(wb);
+}
+
+/*
+ * dispose of a reference to a writeback record
+ */
+void afs_put_writeback(struct afs_writeback *wb)
+{
+       struct afs_vnode *vnode = wb->vnode;
+
+       _enter("{%d}", wb->usage);
+
+       spin_lock(&vnode->writeback_lock);
+       if (--wb->usage == 0)
+               afs_unlink_writeback(wb);
+       else
+               wb = NULL;
+       spin_unlock(&vnode->writeback_lock);
+       if (wb)
+               afs_free_writeback(wb);
+}
+
+/*
+ * partly or wholly fill a page that's under preparation for writing
+ */
+static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
+                        unsigned start, unsigned len, struct page *page)
+{
+       int ret;
+
+       _enter(",,%u,%u", start, len);
+
+       ASSERTCMP(start + len, <=, PAGE_SIZE);
+
+       ret = afs_vnode_fetch_data(vnode, key, start, len, page);
+       if (ret < 0) {
+               if (ret == -ENOENT) {
+                       _debug("got NOENT from server"
+                              " - marking file deleted and stale");
+                       set_bit(AFS_VNODE_DELETED, &vnode->flags);
+                       ret = -ESTALE;
+               }
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * prepare a page for being written to
+ */
+static int afs_prepare_page(struct afs_vnode *vnode, struct page *page,
+                           struct key *key, unsigned offset, unsigned to)
+{
+       unsigned eof, tail, start, stop, len;
+       loff_t i_size, pos;
+       void *p;
+       int ret;
+
+       _enter("");
+
+       if (offset == 0 && to == PAGE_SIZE)
+               return 0;
+
+       p = kmap(page);
+
+       i_size = i_size_read(&vnode->vfs_inode);
+       pos = (loff_t) page->index << PAGE_SHIFT;
+       if (pos >= i_size) {
+               /* partial write, page beyond EOF */
+               _debug("beyond");
+               if (offset > 0)
+                       memset(p, 0, offset);
+               if (to < PAGE_SIZE)
+                       memset(p + to, 0, PAGE_SIZE - to);
+               kunmap(page);
+               return 0;
+       }
+
+       if (i_size - pos >= PAGE_SIZE) {
+               /* partial write, page entirely before EOF */
+               _debug("before");
+               tail = eof = PAGE_SIZE;
+       } else {
+               /* partial write, page overlaps EOF */
+               eof = i_size - pos;
+               _debug("overlap %u", eof);
+               tail = max(eof, to);
+               if (tail < PAGE_SIZE)
+                       memset(p + tail, 0, PAGE_SIZE - tail);
+               if (offset > eof)
+                       memset(p + eof, 0, PAGE_SIZE - eof);
+       }
+
+       kunmap(p);
+
+       ret = 0;
+       if (offset > 0 || eof > to) {
+               /* need to fill one or two bits that aren't going to be written
+                * (cover both fillers in one read if there are two) */
+               start = (offset > 0) ? 0 : to;
+               stop = (eof > to) ? eof : offset;
+               len = stop - start;
+               _debug("wr=%u-%u av=0-%u rd=%u@%u",
+                      offset, to, eof, start, len);
+               ret = afs_fill_page(vnode, key, start, len, page);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * prepare to perform part of a write to a page
+ * - the caller holds the page locked, preventing it from being written out or
+ *   modified by anyone else
+ */
+int afs_prepare_write(struct file *file, struct page *page,
+                     unsigned offset, unsigned to)
+{
+       struct afs_writeback *candidate, *wb;
+       struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+       struct key *key = file->private_data;
+       pgoff_t index;
+       int ret;
+
+       _enter("{%x:%u},{%lx},%u,%u",
+              vnode->fid.vid, vnode->fid.vnode, page->index, offset, to);
+
+       candidate = kzalloc(sizeof(*candidate), GFP_KERNEL);
+       if (!candidate)
+               return -ENOMEM;
+       candidate->vnode = vnode;
+       candidate->first = candidate->last = page->index;
+       candidate->offset_first = offset;
+       candidate->to_last = to;
+       candidate->usage = 1;
+       candidate->state = AFS_WBACK_PENDING;
+       init_waitqueue_head(&candidate->waitq);
+
+       if (!PageUptodate(page)) {
+               _debug("not up to date");
+               ret = afs_prepare_page(vnode, page, key, offset, to);
+               if (ret < 0) {
+                       kfree(candidate);
+                       _leave(" = %d [prep]", ret);
+                       return ret;
+               }
+               SetPageUptodate(page);
+       }
+
+try_again:
+       index = page->index;
+       spin_lock(&vnode->writeback_lock);
+
+       /* see if this page is already pending a writeback under a suitable key
+        * - if so we can just join onto that one */
+       wb = (struct afs_writeback *) page_private(page);
+       if (wb) {
+               if (wb->key == key && wb->state == AFS_WBACK_PENDING)
+                       goto subsume_in_current_wb;
+               goto flush_conflicting_wb;
+       }
+
+       if (index > 0) {
+               /* see if we can find an already pending writeback that we can
+                * append this page to */
+               list_for_each_entry(wb, &vnode->writebacks, link) {
+                       if (wb->last == index - 1 && wb->key == key &&
+                           wb->state == AFS_WBACK_PENDING)
+                               goto append_to_previous_wb;
+               }
+       }
+
+       list_add_tail(&candidate->link, &vnode->writebacks);
+       candidate->key = key_get(key);
+       spin_unlock(&vnode->writeback_lock);
+       SetPagePrivate(page);
+       set_page_private(page, (unsigned long) candidate);
+       _leave(" = 0 [new]");
+       return 0;
+
+subsume_in_current_wb:
+       _debug("subsume");
+       ASSERTRANGE(wb->first, <=, index, <=, wb->last);
+       if (index == wb->first && offset < wb->offset_first)
+               wb->offset_first = offset;
+       if (index == wb->last && to > wb->to_last)
+               wb->to_last = to;
+       spin_unlock(&vnode->writeback_lock);
+       kfree(candidate);
+       _leave(" = 0 [sub]");
+       return 0;
+
+append_to_previous_wb:
+       _debug("append into %lx-%lx", wb->first, wb->last);
+       wb->usage++;
+       wb->last++;
+       wb->to_last = to;
+       spin_unlock(&vnode->writeback_lock);
+       SetPagePrivate(page);
+       set_page_private(page, (unsigned long) wb);
+       kfree(candidate);
+       _leave(" = 0 [app]");
+       return 0;
+
+       /* the page is currently bound to another context, so if it's dirty we
+        * need to flush it before we can use the new context */
+flush_conflicting_wb:
+       _debug("flush conflict");
+       if (wb->state == AFS_WBACK_PENDING)
+               wb->state = AFS_WBACK_CONFLICTING;
+       spin_unlock(&vnode->writeback_lock);
+       if (PageDirty(page)) {
+               ret = afs_write_back_from_locked_page(wb, page);
+               if (ret < 0) {
+                       afs_put_writeback(candidate);
+                       _leave(" = %d", ret);
+                       return ret;
+               }
+       }
+
+       /* the page holds a ref on the writeback record */
+       afs_put_writeback(wb);
+       set_page_private(page, 0);
+       ClearPagePrivate(page);
+       goto try_again;
+}
+
+/*
+ * finalise part of a write to a page
+ */
+int afs_commit_write(struct file *file, struct page *page,
+                    unsigned offset, unsigned to)
+{
+       struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+       loff_t i_size, maybe_i_size;
+
+       _enter("{%x:%u},{%lx},%u,%u",
+              vnode->fid.vid, vnode->fid.vnode, page->index, offset, to);
+
+       maybe_i_size = (loff_t) page->index << PAGE_SHIFT;
+       maybe_i_size += to;
+
+       i_size = i_size_read(&vnode->vfs_inode);
+       if (maybe_i_size > i_size) {
+               spin_lock(&vnode->writeback_lock);
+               i_size = i_size_read(&vnode->vfs_inode);
+               if (maybe_i_size > i_size)
+                       i_size_write(&vnode->vfs_inode, maybe_i_size);
+               spin_unlock(&vnode->writeback_lock);
+       }
+
+       set_page_dirty(page);
+
+       if (PageDirty(page))
+               _debug("dirtied");
+
+       return 0;
+}
+
+/*
+ * kill all the pages in the given range
+ */
+static void afs_kill_pages(struct afs_vnode *vnode, bool error,
+                          pgoff_t first, pgoff_t last)
+{
+       struct pagevec pv;
+       unsigned count, loop;
+
+       _enter("{%x:%u},%lx-%lx",
+              vnode->fid.vid, vnode->fid.vnode, first, last);
+
+       pagevec_init(&pv, 0);
+
+       do {
+               _debug("kill %lx-%lx", first, last);
+
+               count = last - first + 1;
+               if (count > PAGEVEC_SIZE)
+                       count = PAGEVEC_SIZE;
+               pv.nr = find_get_pages_contig(vnode->vfs_inode.i_mapping,
+                                             first, count, pv.pages);
+               ASSERTCMP(pv.nr, ==, count);
+
+               for (loop = 0; loop < count; loop++) {
+                       ClearPageUptodate(pv.pages[loop]);
+                       if (error)
+                               SetPageError(pv.pages[loop]);
+                       end_page_writeback(pv.pages[loop]);
+               }
+
+               __pagevec_release(&pv);
+       } while (first < last);
+
+       _leave("");
+}
+
+/*
+ * synchronously write back the locked page and any subsequent non-locked dirty
+ * pages also covered by the same writeback record
+ */
+static int afs_write_back_from_locked_page(struct afs_writeback *wb,
+                                          struct page *primary_page)
+{
+       struct page *pages[8], *page;
+       unsigned long count;
+       unsigned n, offset, to;
+       pgoff_t start, first, last;
+       int loop, ret;
+
+       _enter(",%lx", primary_page->index);
+
+       count = 1;
+       if (!clear_page_dirty_for_io(primary_page))
+               BUG();
+       if (test_set_page_writeback(primary_page))
+               BUG();
+
+       /* find all consecutive lockable dirty pages, stopping when we find a
+        * page that is not immediately lockable, is not dirty or is missing,
+        * or we reach the end of the range */
+       start = primary_page->index;
+       if (start >= wb->last)
+               goto no_more;
+       start++;
+       do {
+               _debug("more %lx [%lx]", start, count);
+               n = wb->last - start + 1;
+               if (n > ARRAY_SIZE(pages))
+                       n = ARRAY_SIZE(pages);
+               n = find_get_pages_contig(wb->vnode->vfs_inode.i_mapping,
+                                         start, n, pages);
+               _debug("fgpc %u", n);
+               if (n == 0)
+                       goto no_more;
+               if (pages[0]->index != start) {
+                       for (n--; n >= 0; n--)
+                               put_page(pages[n]);
+                       goto no_more;
+               }
+
+               for (loop = 0; loop < n; loop++) {
+                       page = pages[loop];
+                       if (page->index > wb->last)
+                               break;
+                       if (TestSetPageLocked(page))
+                               break;
+                       if (!PageDirty(page) ||
+                           page_private(page) != (unsigned long) wb) {
+                               unlock_page(page);
+                               break;
+                       }
+                       if (!clear_page_dirty_for_io(page))
+                               BUG();
+                       if (test_set_page_writeback(page))
+                               BUG();
+                       unlock_page(page);
+                       put_page(page);
+               }
+               count += loop;
+               if (loop < n) {
+                       for (; loop < n; loop++)
+                               put_page(pages[loop]);
+                       goto no_more;
+               }
+
+               start += loop;
+       } while (start <= wb->last && count < 65536);
+
+no_more:
+       /* we now have a contiguous set of dirty pages, each with writeback set
+        * and the dirty mark cleared; the first page is locked and must remain
+        * so, all the rest are unlocked */
+       first = primary_page->index;
+       last = first + count - 1;
+
+       offset = (first == wb->first) ? wb->offset_first : 0;
+       to = (last == wb->last) ? wb->to_last : PAGE_SIZE;
+
+       _debug("write back %lx[%u..] to %lx[..%u]", first, offset, last, to);
+
+       ret = afs_vnode_store_data(wb, first, last, offset, to);
+       if (ret < 0) {
+               switch (ret) {
+               case -EDQUOT:
+               case -ENOSPC:
+                       set_bit(AS_ENOSPC,
+                               &wb->vnode->vfs_inode.i_mapping->flags);
+                       break;
+               case -EROFS:
+               case -EIO:
+               case -EREMOTEIO:
+               case -EFBIG:
+               case -ENOENT:
+               case -ENOMEDIUM:
+               case -ENXIO:
+                       afs_kill_pages(wb->vnode, true, first, last);
+                       set_bit(AS_EIO, &wb->vnode->vfs_inode.i_mapping->flags);
+                       break;
+               case -EACCES:
+               case -EPERM:
+               case -ENOKEY:
+               case -EKEYEXPIRED:
+               case -EKEYREJECTED:
+               case -EKEYREVOKED:
+                       afs_kill_pages(wb->vnode, false, first, last);
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               ret = count;
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * write a page back to the server
+ * - the caller locked the page for us
+ */
+int afs_writepage(struct page *page, struct writeback_control *wbc)
+{
+       struct backing_dev_info *bdi = page->mapping->backing_dev_info;
+       struct afs_writeback *wb;
+       int ret;
+
+       _enter("{%lx},", page->index);
+
+       if (wbc->sync_mode != WB_SYNC_NONE)
+               wait_on_page_writeback(page);
+
+       if (PageWriteback(page) || !PageDirty(page)) {
+               unlock_page(page);
+               return 0;
+       }
+
+       wb = (struct afs_writeback *) page_private(page);
+       ASSERT(wb != NULL);
+
+       ret = afs_write_back_from_locked_page(wb, page);
+       unlock_page(page);
+       if (ret < 0) {
+               _leave(" = %d", ret);
+               return 0;
+       }
+
+       wbc->nr_to_write -= ret;
+       if (wbc->nonblocking && bdi_write_congested(bdi))
+               wbc->encountered_congestion = 1;
+
+       _leave(" = 0");
+       return 0;
+}
+
+/*
+ * write a region of pages back to the server
+ */
+int afs_writepages_region(struct address_space *mapping,
+                         struct writeback_control *wbc,
+                         pgoff_t index, pgoff_t end, pgoff_t *_next)
+{
+       struct backing_dev_info *bdi = mapping->backing_dev_info;
+       struct afs_writeback *wb;
+       struct page *page;
+       int ret, n;
+
+       _enter(",,%lx,%lx,", index, end);
+
+       do {
+               n = find_get_pages_tag(mapping, &index, PAGECACHE_TAG_DIRTY,
+                                      1, &page);
+               if (!n)
+                       break;
+
+               _debug("wback %lx", page->index);
+
+               if (page->index > end) {
+                       *_next = index;
+                       page_cache_release(page);
+                       _leave(" = 0 [%lx]", *_next);
+                       return 0;
+               }
+
+               /* at this point we hold neither mapping->tree_lock nor lock on
+                * the page itself: the page may be truncated or invalidated
+                * (changing page->mapping to NULL), or even swizzled back from
+                * swapper_space to tmpfs file mapping
+                */
+               lock_page(page);
+
+               if (page->mapping != mapping) {
+                       unlock_page(page);
+                       page_cache_release(page);
+                       continue;
+               }
+
+               if (wbc->sync_mode != WB_SYNC_NONE)
+                       wait_on_page_writeback(page);
+
+               if (PageWriteback(page) || !PageDirty(page)) {
+                       unlock_page(page);
+                       continue;
+               }
+
+               wb = (struct afs_writeback *) page_private(page);
+               ASSERT(wb != NULL);
+
+               spin_lock(&wb->vnode->writeback_lock);
+               wb->state = AFS_WBACK_WRITING;
+               spin_unlock(&wb->vnode->writeback_lock);
+
+               ret = afs_write_back_from_locked_page(wb, page);
+               unlock_page(page);
+               page_cache_release(page);
+               if (ret < 0) {
+                       _leave(" = %d", ret);
+                       return ret;
+               }
+
+               wbc->nr_to_write -= ret;
+
+               if (wbc->nonblocking && bdi_write_congested(bdi)) {
+                       wbc->encountered_congestion = 1;
+                       break;
+               }
+
+               cond_resched();
+       } while (index < end && wbc->nr_to_write > 0);
+
+       *_next = index;
+       _leave(" = 0 [%lx]", *_next);
+       return 0;
+}
+
+/*
+ * write some of the pending data back to the server
+ */
+int afs_writepages(struct address_space *mapping,
+                  struct writeback_control *wbc)
+{
+       struct backing_dev_info *bdi = mapping->backing_dev_info;
+       pgoff_t start, end, next;
+       int ret;
+
+       _enter("");
+
+       if (wbc->nonblocking && bdi_write_congested(bdi)) {
+               wbc->encountered_congestion = 1;
+               _leave(" = 0 [congest]");
+               return 0;
+       }
+
+       if (wbc->range_cyclic) {
+               start = mapping->writeback_index;
+               end = -1;
+               ret = afs_writepages_region(mapping, wbc, start, end, &next);
+               if (start > 0 && wbc->nr_to_write > 0 && ret == 0 &&
+                   !(wbc->nonblocking && wbc->encountered_congestion))
+                       ret = afs_writepages_region(mapping, wbc, 0, start,
+                                                   &next);
+               mapping->writeback_index = next;
+       } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) {
+               end = (pgoff_t)(LLONG_MAX >> PAGE_CACHE_SHIFT);
+               ret = afs_writepages_region(mapping, wbc, 0, end, &next);
+               if (wbc->nr_to_write > 0)
+                       mapping->writeback_index = next;
+       } else {
+               start = wbc->range_start >> PAGE_CACHE_SHIFT;
+               end = wbc->range_end >> PAGE_CACHE_SHIFT;
+               ret = afs_writepages_region(mapping, wbc, start, end, &next);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * write an inode back
+ */
+int afs_write_inode(struct inode *inode, int sync)
+{
+       struct afs_vnode *vnode = AFS_FS_I(inode);
+       int ret;
+
+       _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
+
+       ret = 0;
+       if (sync) {
+               ret = filemap_fdatawait(inode->i_mapping);
+               if (ret < 0)
+                       __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * completion of write to server
+ */
+void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
+{
+       struct afs_writeback *wb = call->wb;
+       struct pagevec pv;
+       unsigned count, loop;
+       pgoff_t first = call->first, last = call->last;
+       bool free_wb;
+
+       _enter("{%x:%u},{%lx-%lx}",
+              vnode->fid.vid, vnode->fid.vnode, first, last);
+
+       ASSERT(wb != NULL);
+
+       pagevec_init(&pv, 0);
+
+       do {
+               _debug("attach %lx-%lx", first, last);
+
+               count = last - first + 1;
+               if (count > PAGEVEC_SIZE)
+                       count = PAGEVEC_SIZE;
+               pv.nr = find_get_pages_contig(call->mapping, first, count,
+                                             pv.pages);
+               ASSERTCMP(pv.nr, ==, count);
+
+               spin_lock(&vnode->writeback_lock);
+               for (loop = 0; loop < count; loop++) {
+                       struct page *page = pv.pages[loop];
+                       end_page_writeback(page);
+                       if (page_private(page) == (unsigned long) wb) {
+                               set_page_private(page, 0);
+                               ClearPagePrivate(page);
+                               wb->usage--;
+                       }
+               }
+               free_wb = false;
+               if (wb->usage == 0) {
+                       afs_unlink_writeback(wb);
+                       free_wb = true;
+               }
+               spin_unlock(&vnode->writeback_lock);
+               first += count;
+               if (free_wb) {
+                       afs_free_writeback(wb);
+                       wb = NULL;
+               }
+
+               __pagevec_release(&pv);
+       } while (first < last);
+
+       _leave("");
+}
+
+/*
+ * write to an AFS file
+ */
+ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
+                      unsigned long nr_segs, loff_t pos)
+{
+       struct dentry *dentry = iocb->ki_filp->f_path.dentry;
+       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+       ssize_t result;
+       size_t count = iov_length(iov, nr_segs);
+       int ret;
+
+       _enter("{%x.%u},{%zu},%lu,",
+              vnode->fid.vid, vnode->fid.vnode, count, nr_segs);
+
+       if (IS_SWAPFILE(&vnode->vfs_inode)) {
+               printk(KERN_INFO
+                      "AFS: Attempt to write to active swap file!\n");
+               return -EBUSY;
+       }
+
+       if (!count)
+               return 0;
+
+       result = generic_file_aio_write(iocb, iov, nr_segs, pos);
+       if (IS_ERR_VALUE(result)) {
+               _leave(" = %zd", result);
+               return result;
+       }
+
+       /* return error values for O_SYNC and IS_SYNC() */
+       if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_SYNC) {
+               ret = afs_fsync(iocb->ki_filp, dentry, 1);
+               if (ret < 0)
+                       result = ret;
+       }
+
+       _leave(" = %zd", result);
+       return result;
+}
+
+/*
+ * flush the vnode to the fileserver
+ */
+int afs_writeback_all(struct afs_vnode *vnode)
+{
+       struct address_space *mapping = vnode->vfs_inode.i_mapping;
+       struct writeback_control wbc = {
+               .bdi            = mapping->backing_dev_info,
+               .sync_mode      = WB_SYNC_ALL,
+               .nr_to_write    = LONG_MAX,
+               .for_writepages = 1,
+               .range_cyclic   = 1,
+       };
+       int ret;
+
+       _enter("");
+
+       ret = mapping->a_ops->writepages(mapping, &wbc);
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*
+ * flush any dirty pages for this process, and check for write errors.
+ * - the return status from this call provides a reliable indication of
+ *   whether any write errors occurred for this process.
+ */
+int afs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+       struct afs_writeback *wb, *xwb;
+       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+       int ret;
+
+       _enter("{%x:%u},{n=%s},%d",
+              vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
+              datasync);
+
+       /* use a writeback record as a marker in the queue - when this reaches
+        * the front of the queue, all the outstanding writes are either
+        * completed or rejected */
+       wb = kzalloc(sizeof(*wb), GFP_KERNEL);
+       if (!wb)
+               return -ENOMEM;
+       wb->vnode = vnode;
+       wb->first = 0;
+       wb->last = -1;
+       wb->offset_first = 0;
+       wb->to_last = PAGE_SIZE;
+       wb->usage = 1;
+       wb->state = AFS_WBACK_SYNCING;
+       init_waitqueue_head(&wb->waitq);
+
+       spin_lock(&vnode->writeback_lock);
+       list_for_each_entry(xwb, &vnode->writebacks, link) {
+               if (xwb->state == AFS_WBACK_PENDING)
+                       xwb->state = AFS_WBACK_CONFLICTING;
+       }
+       list_add_tail(&wb->link, &vnode->writebacks);
+       spin_unlock(&vnode->writeback_lock);
+
+       /* push all the outstanding writebacks to the server */
+       ret = afs_writeback_all(vnode);
+       if (ret < 0) {
+               afs_put_writeback(wb);
+               _leave(" = %d [wb]", ret);
+               return ret;
+       }
+
+       /* wait for the preceding writes to actually complete */
+       ret = wait_event_interruptible(wb->waitq,
+                                      wb->state == AFS_WBACK_COMPLETE ||
+                                      vnode->writebacks.next == &wb->link);
+       afs_put_writeback(wb);
+       _leave(" = %d", ret);
+       return ret;
+}
index b97ab8028b6d2e9dde3ce85e5a2a91ad3140a7b0..ac1c1587aa02dad4583b7a394cf1261e79a0c680 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -346,10 +346,9 @@ void fastcall exit_aio(struct mm_struct *mm)
 
                wait_for_all_aios(ctx);
                /*
-                * this is an overkill, but ensures we don't leave
-                * the ctx on the aio_wq
+                * Ensure we don't leave the ctx on the aio_wq
                 */
-               flush_workqueue(aio_wq);
+               cancel_work_sync(&ctx->wq.work);
 
                if (1 != atomic_read(&ctx->users))
                        printk(KERN_DEBUG
@@ -372,7 +371,7 @@ void fastcall __put_ioctx(struct kioctx *ctx)
        BUG_ON(ctx->reqs_active);
 
        cancel_delayed_work(&ctx->wq);
-       flush_workqueue(aio_wq);
+       cancel_work_sync(&ctx->wq.work);
        aio_free_ring(ctx);
        mmdrop(ctx->mm);
        ctx->mm = NULL;
index 97de946708781df074388be1da5e4f811872766a..a0a0c7b07ba3908379d311931254cc5ba9b2d014 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -9,7 +9,6 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/capability.h>
 #include <linux/fsnotify.h>
 #include <linux/fcntl.h>
index 26063dc84a2a623da272a92a5c323058eb63ebb2..5769a2f9ad60a0f0222eb693ebb576a665cce624 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pagemap.h>
 #include <linux/parser.h>
 #include <linux/bitops.h>
-#include <linux/smp_lock.h>
 #include <linux/magic.h>
 #include "autofs_i.h"
 #include <linux/module.h>
index d0e9b3a3905d6e125a8d2fa2025251fbeab496ee..15170f4e13a763e704af9a6b9871f843a1d65a8a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/stat.h>
 #include <linux/param.h>
 #include <linux/time.h>
-#include <linux/smp_lock.h>
 #include "autofs_i.h"
 
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
index efeab2fab40b743e55718de1c365ec278804664c..329ee473eede9514d2b6511aa9d41fc3e3884beb 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/stat.h>
 #include <linux/time.h>
-#include <linux/smp_lock.h>
 #include <linux/namei.h>
 #include <linux/poll.h>
 
index 9cc4f0a8aaaec1ffba2b8a5f66389f2503fab2f3..fa8ea33ab0be1ef56ff78b5908a691676d815e27 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/compiler.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
@@ -39,6 +38,7 @@
 #include <linux/syscalls.h>
 #include <linux/random.h>
 #include <linux/elf.h>
+#include <linux/utsname.h>
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
@@ -871,6 +871,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                                elf_prot, elf_flags);
                if (BAD_ADDR(error)) {
                        send_sig(SIGKILL, current, 0);
+                       retval = IS_ERR((void *)error) ?
+                               PTR_ERR((void*)error) : -EINVAL;
                        goto out_free_dentry;
                }
 
@@ -900,6 +902,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                    TASK_SIZE - elf_ppnt->p_memsz < k) {
                        /* set_brk can never work. Avoid overflows. */
                        send_sig(SIGKILL, current, 0);
+                       retval = -EINVAL;
                        goto out_free_dentry;
                }
 
index f3ddca4a387b43f817b83ae85cd7aaf44b1c7398..9d62fbad3d4b4fc121a91323d05ab4809aa78c28 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/personality.h>
 #include <linux/ptrace.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/elf.h>
 #include <linux/elf-fdpic.h>
 #include <linux/elfcore.h>
index 1f2d1ad63319430ad4ea6ac4c2684df93829fc41..576dd7de22784e3007c5854d39ad867dc02d0bca 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
 #include <linux/init.h>
index e6f57990b121650647663f95f33727280cf22c4d..72d0b412c376641428244fac1acab7684b7cc748 100644 (file)
@@ -675,19 +675,8 @@ static ssize_t
 bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
        char *s = enabled ? "enabled" : "disabled";
-       int len = strlen(s);
-       loff_t pos = *ppos;
 
-       if (pos < 0)
-               return -EINVAL;
-       if (pos >= len)
-               return 0;
-       if (len < pos + nbytes)
-               nbytes = len - pos;
-       if (copy_to_user(buf, s + pos, nbytes))
-               return -EFAULT;
-       *ppos = pos + nbytes;
-       return nbytes;
+       return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
 }
 
 static ssize_t bm_status_write(struct file * file, const char __user * buffer,
@@ -727,8 +716,8 @@ static const struct super_operations s_ops = {
 static int bm_fill_super(struct super_block * sb, void * data, int silent)
 {
        static struct tree_descr bm_files[] = {
-               [1] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
-               [2] = {"register", &bm_register_operations, S_IWUSR},
+               [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
+               [3] = {"register", &bm_register_operations, S_IWUSR},
                /* last one */ {""}
        };
        int err = simple_fill_super(sb, 0x42494e4d, bm_files);
index 1edbcca25a7366198667d5c8fdfe92d4005a65bc..304c88544d890f161b06a182c55e3da7c678409d 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/binfmts.h>
 #include <linux/init.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <linux/err.h>
 #include <linux/fs.h>
 
index f02b7bdd9864874c5f038c792c20763a1bfa7437..742899240872ffb59e7329f6dabef624798c2fbb 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mount.h>
 #include <linux/uio.h>
 #include <linux/namei.h>
+#include <linux/log2.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -67,7 +68,7 @@ static void kill_bdev(struct block_device *bdev)
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
-       if (size > PAGE_SIZE || size < 512 || (size & (size-1)))
+       if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
                return -EINVAL;
 
        /* Size cannot be smaller than the size supported by the device */
index 7db24b9e54490b82f8201cda70d25afb6424d38a..aecd057cd0e0607631201d93be38bda0b9e44001 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/mm.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/capability.h>
 #include <linux/blkdev.h>
 #include <linux/file.h>
@@ -1727,6 +1726,7 @@ recover:
        } while ((bh = bh->b_this_page) != head);
        SetPageError(page);
        BUG_ON(PageWriteback(page));
+       mapping_set_error(page->mapping, err);
        set_page_writeback(page);
        do {
                struct buffer_head *next = bh->b_this_page;
@@ -1846,13 +1846,8 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
                if (block_start >= to)
                        break;
                if (buffer_new(bh)) {
-                       void *kaddr;
-
                        clear_buffer_new(bh);
-                       kaddr = kmap_atomic(page, KM_USER0);
-                       memset(kaddr+block_start, 0, bh->b_size);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
+                       zero_user_page(page, block_start, bh->b_size, KM_USER0);
                        set_buffer_uptodate(bh);
                        mark_buffer_dirty(bh);
                }
@@ -1940,10 +1935,8 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
                                        SetPageError(page);
                        }
                        if (!buffer_mapped(bh)) {
-                               void *kaddr = kmap_atomic(page, KM_USER0);
-                               memset(kaddr + i * blocksize, 0, blocksize);
-                               flush_dcache_page(page);
-                               kunmap_atomic(kaddr, KM_USER0);
+                               zero_user_page(page, i * blocksize, blocksize,
+                                               KM_USER0);
                                if (!err)
                                        set_buffer_uptodate(bh);
                                continue;
@@ -2086,7 +2079,6 @@ int cont_prepare_write(struct page *page, unsigned offset,
        long status;
        unsigned zerofrom;
        unsigned blocksize = 1 << inode->i_blkbits;
-       void *kaddr;
 
        while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) {
                status = -ENOMEM;
@@ -2108,10 +2100,8 @@ int cont_prepare_write(struct page *page, unsigned offset,
                                                PAGE_CACHE_SIZE, get_block);
                if (status)
                        goto out_unmap;
-               kaddr = kmap_atomic(new_page, KM_USER0);
-               memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom);
-               flush_dcache_page(new_page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, zerofrom, PAGE_CACHE_SIZE - zerofrom,
+                               KM_USER0);
                generic_commit_write(NULL, new_page, zerofrom, PAGE_CACHE_SIZE);
                unlock_page(new_page);
                page_cache_release(new_page);
@@ -2138,10 +2128,7 @@ int cont_prepare_write(struct page *page, unsigned offset,
        if (status)
                goto out1;
        if (zerofrom < offset) {
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr+zerofrom, 0, offset-zerofrom);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, zerofrom, offset - zerofrom, KM_USER0);
                __block_commit_write(inode, page, zerofrom, offset);
        }
        return 0;
@@ -2340,10 +2327,7 @@ failed:
         * Error recovery is pretty slack.  Clear the page and mark it dirty
         * so we'll later zero out any blocks which _were_ allocated.
         */
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr, 0, PAGE_CACHE_SIZE);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
+       zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
        SetPageUptodate(page);
        set_page_dirty(page);
        return ret;
@@ -2382,7 +2366,6 @@ int nobh_writepage(struct page *page, get_block_t *get_block,
        loff_t i_size = i_size_read(inode);
        const pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
        unsigned offset;
-       void *kaddr;
        int ret;
 
        /* Is the page fully inside i_size? */
@@ -2413,10 +2396,7 @@ int nobh_writepage(struct page *page, get_block_t *get_block,
         * the  page size, the remaining memory is zeroed when mapped, and
         * writes to that region are not written out to the file."
         */
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
+       zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
 out:
        ret = mpage_writepage(page, get_block, wbc);
        if (ret == -EAGAIN)
@@ -2437,7 +2417,6 @@ int nobh_truncate_page(struct address_space *mapping, loff_t from)
        unsigned to;
        struct page *page;
        const struct address_space_operations *a_ops = mapping->a_ops;
-       char *kaddr;
        int ret = 0;
 
        if ((offset & (blocksize - 1)) == 0)
@@ -2451,10 +2430,8 @@ int nobh_truncate_page(struct address_space *mapping, loff_t from)
        to = (offset + blocksize) & ~(blocksize - 1);
        ret = a_ops->prepare_write(NULL, page, offset, to);
        if (ret == 0) {
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, offset, PAGE_CACHE_SIZE - offset,
+                               KM_USER0);
                /*
                 * It would be more correct to call aops->commit_write()
                 * here, but this is more efficient.
@@ -2480,7 +2457,6 @@ int block_truncate_page(struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct page *page;
        struct buffer_head *bh;
-       void *kaddr;
        int err;
 
        blocksize = 1 << inode->i_blkbits;
@@ -2534,11 +2510,7 @@ int block_truncate_page(struct address_space *mapping,
                        goto unlock;
        }
 
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr + offset, 0, length);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
-
+       zero_user_page(page, offset, length, KM_USER0);
        mark_buffer_dirty(bh);
        err = 0;
 
@@ -2559,7 +2531,6 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
        loff_t i_size = i_size_read(inode);
        const pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
        unsigned offset;
-       void *kaddr;
 
        /* Is the page fully inside i_size? */
        if (page->index < end_index)
@@ -2585,10 +2556,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
         * the  page size, the remaining memory is zeroed when mapped, and
         * writes to that region are not written out to the file."
         */
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
+       zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
        return __block_write_full_page(inode, page, get_block, wbc);
 }
 
@@ -2978,7 +2946,7 @@ static void buffer_exit_cpu(int cpu)
 static int buffer_cpu_notify(struct notifier_block *self,
                              unsigned long action, void *hcpu)
 {
-       if (action == CPU_DEAD)
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
                buffer_exit_cpu((unsigned long)hcpu);
        return NOTIFY_OK;
 }
index b570530f97bf4c4952c26c8ed2c58c928827faef..94d5b49049df09082f44c221e37d87101d0d6c00 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/fcntl.h>
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
-#include <linux/smp_lock.h>
 #include <linux/writeback.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/delay.h>
index b5364f90d55194f556682b550f9858f9f062f6de..c08bda9fcac68bdd29879c18208b1ddb2b7de4f9 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/stat.h>
-#include <linux/smp_lock.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
index 72e5e69238288f976eefb6748624aac17ef85449..9cf75df9b2bb4753356ca9e3e5ae527b49329268 100644 (file)
@@ -15,6 +15,7 @@
  *  published by the Free Software Foundation.
  */
 
+#include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/namei.h>
 #include <linux/file.h>
 #include <linux/vfs.h>
-#include <linux/ioctl32.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
-#include <linux/sockios.h>     /* for SIOCDEVPRIVATE */
 #include <linux/smb.h>
 #include <linux/smb_mount.h>
 #include <linux/ncp_mount.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
 #include <linux/tsacct_kern.h>
+#include <linux/security.h>
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/eventpoll.h>
 
-#include <net/sock.h>          /* siocdevprivate_ioctl */
-
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
@@ -79,30 +77,57 @@ int compat_printk(const char *fmt, ...)
  */
 asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t)
 {
-       struct timeval tv[2];
+       struct timespec tv[2];
 
        if (t) {
                if (get_user(tv[0].tv_sec, &t->actime) ||
                    get_user(tv[1].tv_sec, &t->modtime))
                        return -EFAULT;
-               tv[0].tv_usec = 0;
-               tv[1].tv_usec = 0;
+               tv[0].tv_nsec = 0;
+               tv[1].tv_nsec = 0;
+       }
+       return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
+}
+
+asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags)
+{
+       struct timespec tv[2];
+
+       if  (t) {
+               if (get_compat_timespec(&tv[0], &t[0]) ||
+                   get_compat_timespec(&tv[1], &t[1]))
+                       return -EFAULT;
+
+               if ((tv[0].tv_nsec == UTIME_OMIT || tv[0].tv_nsec == UTIME_NOW)
+                   && tv[0].tv_sec != 0)
+                       return -EINVAL;
+               if ((tv[1].tv_nsec == UTIME_OMIT || tv[1].tv_nsec == UTIME_NOW)
+                   && tv[1].tv_sec != 0)
+                       return -EINVAL;
+
+               if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
+                       return 0;
        }
-       return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
+       return do_utimes(dfd, filename, t ? tv : NULL, flags);
 }
 
 asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t)
 {
-       struct timeval tv[2];
+       struct timespec tv[2];
 
        if (t) {
                if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
-                   get_user(tv[0].tv_usec, &t[0].tv_usec) ||
+                   get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
                    get_user(tv[1].tv_sec, &t[1].tv_sec) ||
-                   get_user(tv[1].tv_usec, &t[1].tv_usec))
+                   get_user(tv[1].tv_nsec, &t[1].tv_usec))
                        return -EFAULT;
+               if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
+                   tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
+                       return -EINVAL;
+               tv[0].tv_nsec *= 1000;
+               tv[1].tv_nsec *= 1000;
        }
-       return do_utimes(dfd, filename, t ? tv : NULL);
+       return do_utimes(dfd, filename, t ? tv : NULL, 0);
 }
 
 asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
@@ -312,163 +337,6 @@ out:
        return error;
 }
 
-/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
-
-#define IOCTL_HASHSIZE 256
-static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
-
-static inline unsigned long ioctl32_hash(unsigned long cmd)
-{
-       return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
-}
-
-static void ioctl32_insert_translation(struct ioctl_trans *trans)
-{
-       unsigned long hash;
-       struct ioctl_trans *t;
-
-       hash = ioctl32_hash (trans->cmd);
-       if (!ioctl32_hash_table[hash])
-               ioctl32_hash_table[hash] = trans;
-       else {
-               t = ioctl32_hash_table[hash];
-               while (t->next)
-                       t = t->next;
-               trans->next = NULL;
-               t->next = trans;
-       }
-}
-
-static int __init init_sys32_ioctl(void)
-{
-       int i;
-
-       for (i = 0; i < ioctl_table_size; i++) {
-               if (ioctl_start[i].next != 0) { 
-                       printk("ioctl translation %d bad\n",i); 
-                       return -1;
-               }
-
-               ioctl32_insert_translation(&ioctl_start[i]);
-       }
-       return 0;
-}
-
-__initcall(init_sys32_ioctl);
-
-static void compat_ioctl_error(struct file *filp, unsigned int fd,
-               unsigned int cmd, unsigned long arg)
-{
-       char buf[10];
-       char *fn = "?";
-       char *path;
-
-       /* find the name of the device. */
-       path = (char *)__get_free_page(GFP_KERNEL);
-       if (path) {
-               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
-               if (IS_ERR(fn))
-                       fn = "?";
-       }
-
-       sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
-       if (!isprint(buf[1]))
-               sprintf(buf, "%02x", buf[1]);
-       compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
-                       "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
-                       current->comm, current->pid,
-                       (int)fd, (unsigned int)cmd, buf,
-                       (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
-                       (unsigned int)arg, fn);
-
-       if (path)
-               free_page((unsigned long)path);
-}
-
-asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
-                               unsigned long arg)
-{
-       struct file *filp;
-       int error = -EBADF;
-       struct ioctl_trans *t;
-       int fput_needed;
-
-       filp = fget_light(fd, &fput_needed);
-       if (!filp)
-               goto out;
-
-       /* RED-PEN how should LSM module know it's handling 32bit? */
-       error = security_file_ioctl(filp, cmd, arg);
-       if (error)
-               goto out_fput;
-
-       /*
-        * To allow the compat_ioctl handlers to be self contained
-        * we need to check the common ioctls here first.
-        * Just handle them with the standard handlers below.
-        */
-       switch (cmd) {
-       case FIOCLEX:
-       case FIONCLEX:
-       case FIONBIO:
-       case FIOASYNC:
-       case FIOQSIZE:
-               break;
-
-       case FIBMAP:
-       case FIGETBSZ:
-       case FIONREAD:
-               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
-                       break;
-               /*FALL THROUGH*/
-
-       default:
-               if (filp->f_op && filp->f_op->compat_ioctl) {
-                       error = filp->f_op->compat_ioctl(filp, cmd, arg);
-                       if (error != -ENOIOCTLCMD)
-                               goto out_fput;
-               }
-
-               if (!filp->f_op ||
-                   (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
-                       goto do_ioctl;
-               break;
-       }
-
-       for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
-               if (t->cmd == cmd)
-                       goto found_handler;
-       }
-
-       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
-           cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
-               error = siocdevprivate_ioctl(fd, cmd, arg);
-       } else {
-               static int count;
-
-               if (++count <= 50)
-                       compat_ioctl_error(filp, fd, cmd, arg);
-               error = -EINVAL;
-       }
-
-       goto out_fput;
-
- found_handler:
-       if (t->handler) {
-               lock_kernel();
-               error = t->handler(fd, cmd, arg, filp);
-               unlock_kernel();
-               goto out_fput;
-       }
-
- do_ioctl:
-       error = vfs_ioctl(filp, fd, cmd, arg);
- out_fput:
-       fput_light(filp, fput_needed);
- out:
-       return error;
-}
-
 static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 {
        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
@@ -902,8 +770,6 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
 }
 
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define COMPAT_ROUND_UP(x) (((x)+sizeof(compat_long_t)-1) & \
-                               ~(sizeof(compat_long_t)-1))
 
 struct compat_old_linux_dirent {
        compat_ulong_t  d_ino;
@@ -991,7 +857,7 @@ static int compat_filldir(void *__buf, const char *name, int namlen,
        struct compat_linux_dirent __user * dirent;
        struct compat_getdents_callback *buf = __buf;
        compat_ulong_t d_ino;
-       int reclen = COMPAT_ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
+       int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t));
 
        buf->error = -EINVAL;   /* only used if we fail.. */
        if (reclen > buf->count)
@@ -1066,7 +932,6 @@ out:
 }
 
 #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
-#define COMPAT_ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
 
 struct compat_getdents_callback64 {
        struct linux_dirent64 __user *current_dir;
@@ -1081,7 +946,7 @@ static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t
        struct linux_dirent64 __user *dirent;
        struct compat_getdents_callback64 *buf = __buf;
        int jj = NAME_OFFSET(dirent);
-       int reclen = COMPAT_ROUND_UP64(jj + namlen + 1);
+       int reclen = ALIGN(jj + namlen + 1, sizeof(u64));
        u64 off;
 
        buf->error = -EINVAL;   /* only used if we fail.. */
@@ -1594,8 +1459,6 @@ out_ret:
 
 #define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
 
-#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-
 /*
  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
  * 64-bit unsigned longs.
@@ -1604,7 +1467,7 @@ static
 int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                        unsigned long *fdset)
 {
-       nr = ROUND_UP(nr, __COMPAT_NFDBITS);
+       nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
        if (ufdset) {
                unsigned long odd;
 
@@ -1638,7 +1501,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                      unsigned long *fdset)
 {
        unsigned long odd;
-       nr = ROUND_UP(nr, __COMPAT_NFDBITS);
+       nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
 
        if (!ufdset)
                return 0;
@@ -1760,7 +1623,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
                if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
                        timeout = -1;   /* infinite */
                else {
-                       timeout = ROUND_UP(tv.tv_usec, 1000000/HZ);
+                       timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ);
                        timeout += tv.tv_sec * HZ;
                }
        }
@@ -1828,7 +1691,7 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
        do {
                if (tsp) {
                        if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
-                               timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+                               timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
                                timeout += ts.tv_sec * (unsigned long)HZ;
                                ts.tv_sec = 0;
                                ts.tv_nsec = 0;
@@ -1924,7 +1787,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
                /* We assume that ts.tv_sec is always lower than
                   the number of seconds that can be expressed in
                   an s64. Otherwise the compiler bitches at us */
-               timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+               timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
                timeout += ts.tv_sec * HZ;
        }
 
index 464c04a9541d6dd02327daad96c59af7cfe0f6ec..d92bc3eb7afcb33f398dbf35a3e4bc8f2c0c5393 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/ioctl.h>
 #include <linux/if.h>
 #include <linux/if_bridge.h>
@@ -58,7 +57,6 @@
 #include <linux/serial.h>
 #include <linux/if_tun.h>
 #include <linux/ctype.h>
-#include <linux/ioctl32.h>
 #include <linux/syscalls.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
@@ -66,7 +64,6 @@
 #include <linux/atalk.h>
 #include <linux/blktrace_api.h>
 
-#include <net/sock.h>          /* siocdevprivate_ioctl */
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci.h>
 #include <net/bluetooth/rfcomm.h>
@@ -475,7 +472,7 @@ static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        };
 }
 
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
        struct ifreq __user *u_ifreq64;
        struct ifreq32 __user *u_ifreq32 = compat_ptr(arg);
@@ -687,8 +684,10 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
        if (!err) {
                err = copy_to_user (ugeo, &geo, 4);
                err |= __put_user (geo.start, &ugeo->start);
+               if (err)
+                       err = -EFAULT;
        }
-       return err ? -EFAULT : 0;
+       return err;
 }
 
 static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -2385,6 +2384,16 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
        return sys_ioctl(fd, cmd, (unsigned long)tn);
 }
 
+
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+                                       unsigned long, struct file *);
+
+struct ioctl_trans {
+       unsigned long cmd;
+       ioctl_trans_handler_t handler;
+       struct ioctl_trans *next;
+};
+
 #define HANDLE_IOCTL(cmd,handler) \
        { (cmd), (ioctl_trans_handler_t)(handler) },
 
@@ -2405,8 +2414,835 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
    Most other reasons are not valid. */
 #define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd)
 
-struct ioctl_trans ioctl_start[] = {
-#include <linux/compat_ioctl.h>
+static struct ioctl_trans ioctl_start[] = {
+/* compatible ioctls first */
+COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
+COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
+
+/* Big T */
+COMPATIBLE_IOCTL(TCGETA)
+COMPATIBLE_IOCTL(TCSETA)
+COMPATIBLE_IOCTL(TCSETAW)
+COMPATIBLE_IOCTL(TCSETAF)
+COMPATIBLE_IOCTL(TCSBRK)
+ULONG_IOCTL(TCSBRKP)
+COMPATIBLE_IOCTL(TCXONC)
+COMPATIBLE_IOCTL(TCFLSH)
+COMPATIBLE_IOCTL(TCGETS)
+COMPATIBLE_IOCTL(TCSETS)
+COMPATIBLE_IOCTL(TCSETSW)
+COMPATIBLE_IOCTL(TCSETSF)
+COMPATIBLE_IOCTL(TIOCLINUX)
+COMPATIBLE_IOCTL(TIOCSBRK)
+COMPATIBLE_IOCTL(TIOCCBRK)
+ULONG_IOCTL(TIOCMIWAIT)
+COMPATIBLE_IOCTL(TIOCGICOUNT)
+/* Little t */
+COMPATIBLE_IOCTL(TIOCGETD)
+COMPATIBLE_IOCTL(TIOCSETD)
+COMPATIBLE_IOCTL(TIOCEXCL)
+COMPATIBLE_IOCTL(TIOCNXCL)
+COMPATIBLE_IOCTL(TIOCCONS)
+COMPATIBLE_IOCTL(TIOCGSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSWINSZ)
+COMPATIBLE_IOCTL(TIOCGWINSZ)
+COMPATIBLE_IOCTL(TIOCMGET)
+COMPATIBLE_IOCTL(TIOCMBIC)
+COMPATIBLE_IOCTL(TIOCMBIS)
+COMPATIBLE_IOCTL(TIOCMSET)
+COMPATIBLE_IOCTL(TIOCPKT)
+COMPATIBLE_IOCTL(TIOCNOTTY)
+COMPATIBLE_IOCTL(TIOCSTI)
+COMPATIBLE_IOCTL(TIOCOUTQ)
+COMPATIBLE_IOCTL(TIOCSPGRP)
+COMPATIBLE_IOCTL(TIOCGPGRP)
+ULONG_IOCTL(TIOCSCTTY)
+COMPATIBLE_IOCTL(TIOCGPTN)
+COMPATIBLE_IOCTL(TIOCSPTLCK)
+COMPATIBLE_IOCTL(TIOCSERGETLSR)
+/* Little f */
+COMPATIBLE_IOCTL(FIOCLEX)
+COMPATIBLE_IOCTL(FIONCLEX)
+COMPATIBLE_IOCTL(FIOASYNC)
+COMPATIBLE_IOCTL(FIONBIO)
+COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
+/* 0x00 */
+COMPATIBLE_IOCTL(FIBMAP)
+COMPATIBLE_IOCTL(FIGETBSZ)
+/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
+ *         Some need translations, these do not.
+ */
+COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
+COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
+COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+ULONG_IOCTL(HDIO_SET_MULTCOUNT)
+ULONG_IOCTL(HDIO_SET_UNMASKINTR)
+ULONG_IOCTL(HDIO_SET_KEEPSETTINGS)
+ULONG_IOCTL(HDIO_SET_32BIT)
+ULONG_IOCTL(HDIO_SET_NOWERR)
+ULONG_IOCTL(HDIO_SET_DMA)
+ULONG_IOCTL(HDIO_SET_PIO_MODE)
+ULONG_IOCTL(HDIO_SET_NICE)
+ULONG_IOCTL(HDIO_SET_WCACHE)
+ULONG_IOCTL(HDIO_SET_ACOUSTIC)
+ULONG_IOCTL(HDIO_SET_BUSSTATE)
+ULONG_IOCTL(HDIO_SET_ADDRESS)
+COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
+/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+COMPATIBLE_IOCTL(0x330)
+/* 0x02 -- Floppy ioctls */
+COMPATIBLE_IOCTL(FDMSGON)
+COMPATIBLE_IOCTL(FDMSGOFF)
+COMPATIBLE_IOCTL(FDSETEMSGTRESH)
+COMPATIBLE_IOCTL(FDFLUSH)
+COMPATIBLE_IOCTL(FDWERRORCLR)
+COMPATIBLE_IOCTL(FDSETMAXERRS)
+COMPATIBLE_IOCTL(FDGETMAXERRS)
+COMPATIBLE_IOCTL(FDGETDRVTYP)
+COMPATIBLE_IOCTL(FDEJECT)
+COMPATIBLE_IOCTL(FDCLRPRM)
+COMPATIBLE_IOCTL(FDFMTBEG)
+COMPATIBLE_IOCTL(FDFMTEND)
+COMPATIBLE_IOCTL(FDRESET)
+COMPATIBLE_IOCTL(FDTWADDLE)
+COMPATIBLE_IOCTL(FDFMTTRK)
+COMPATIBLE_IOCTL(FDRAWCMD)
+/* 0x12 */
+#ifdef CONFIG_BLOCK
+COMPATIBLE_IOCTL(BLKRASET)
+COMPATIBLE_IOCTL(BLKROSET)
+COMPATIBLE_IOCTL(BLKROGET)
+COMPATIBLE_IOCTL(BLKRRPART)
+COMPATIBLE_IOCTL(BLKFLSBUF)
+COMPATIBLE_IOCTL(BLKSECTSET)
+COMPATIBLE_IOCTL(BLKSSZGET)
+COMPATIBLE_IOCTL(BLKTRACESTART)
+COMPATIBLE_IOCTL(BLKTRACESTOP)
+COMPATIBLE_IOCTL(BLKTRACESETUP)
+COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
+ULONG_IOCTL(BLKRASET)
+ULONG_IOCTL(BLKFRASET)
+#endif
+/* RAID */
+COMPATIBLE_IOCTL(RAID_VERSION)
+COMPATIBLE_IOCTL(GET_ARRAY_INFO)
+COMPATIBLE_IOCTL(GET_DISK_INFO)
+COMPATIBLE_IOCTL(PRINT_RAID_DEBUG)
+COMPATIBLE_IOCTL(RAID_AUTORUN)
+COMPATIBLE_IOCTL(CLEAR_ARRAY)
+COMPATIBLE_IOCTL(ADD_NEW_DISK)
+ULONG_IOCTL(HOT_REMOVE_DISK)
+COMPATIBLE_IOCTL(SET_ARRAY_INFO)
+COMPATIBLE_IOCTL(SET_DISK_INFO)
+COMPATIBLE_IOCTL(WRITE_RAID_INFO)
+COMPATIBLE_IOCTL(UNPROTECT_ARRAY)
+COMPATIBLE_IOCTL(PROTECT_ARRAY)
+ULONG_IOCTL(HOT_ADD_DISK)
+ULONG_IOCTL(SET_DISK_FAULTY)
+COMPATIBLE_IOCTL(RUN_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY_RO)
+COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
+COMPATIBLE_IOCTL(GET_BITMAP_FILE)
+ULONG_IOCTL(SET_BITMAP_FILE)
+/* DM */
+COMPATIBLE_IOCTL(DM_VERSION_32)
+COMPATIBLE_IOCTL(DM_REMOVE_ALL_32)
+COMPATIBLE_IOCTL(DM_LIST_DEVICES_32)
+COMPATIBLE_IOCTL(DM_DEV_CREATE_32)
+COMPATIBLE_IOCTL(DM_DEV_REMOVE_32)
+COMPATIBLE_IOCTL(DM_DEV_RENAME_32)
+COMPATIBLE_IOCTL(DM_DEV_SUSPEND_32)
+COMPATIBLE_IOCTL(DM_DEV_STATUS_32)
+COMPATIBLE_IOCTL(DM_DEV_WAIT_32)
+COMPATIBLE_IOCTL(DM_TABLE_LOAD_32)
+COMPATIBLE_IOCTL(DM_TABLE_CLEAR_32)
+COMPATIBLE_IOCTL(DM_TABLE_DEPS_32)
+COMPATIBLE_IOCTL(DM_TABLE_STATUS_32)
+COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32)
+COMPATIBLE_IOCTL(DM_TARGET_MSG_32)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32)
+COMPATIBLE_IOCTL(DM_VERSION)
+COMPATIBLE_IOCTL(DM_REMOVE_ALL)
+COMPATIBLE_IOCTL(DM_LIST_DEVICES)
+COMPATIBLE_IOCTL(DM_DEV_CREATE)
+COMPATIBLE_IOCTL(DM_DEV_REMOVE)
+COMPATIBLE_IOCTL(DM_DEV_RENAME)
+COMPATIBLE_IOCTL(DM_DEV_SUSPEND)
+COMPATIBLE_IOCTL(DM_DEV_STATUS)
+COMPATIBLE_IOCTL(DM_DEV_WAIT)
+COMPATIBLE_IOCTL(DM_TABLE_LOAD)
+COMPATIBLE_IOCTL(DM_TABLE_CLEAR)
+COMPATIBLE_IOCTL(DM_TABLE_DEPS)
+COMPATIBLE_IOCTL(DM_TABLE_STATUS)
+COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
+COMPATIBLE_IOCTL(DM_TARGET_MSG)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY)
+/* Big K */
+COMPATIBLE_IOCTL(PIO_FONT)
+COMPATIBLE_IOCTL(GIO_FONT)
+ULONG_IOCTL(KDSIGACCEPT)
+COMPATIBLE_IOCTL(KDGETKEYCODE)
+COMPATIBLE_IOCTL(KDSETKEYCODE)
+ULONG_IOCTL(KIOCSOUND)
+ULONG_IOCTL(KDMKTONE)
+COMPATIBLE_IOCTL(KDGKBTYPE)
+ULONG_IOCTL(KDSETMODE)
+COMPATIBLE_IOCTL(KDGETMODE)
+ULONG_IOCTL(KDSKBMODE)
+COMPATIBLE_IOCTL(KDGKBMODE)
+ULONG_IOCTL(KDSKBMETA)
+COMPATIBLE_IOCTL(KDGKBMETA)
+COMPATIBLE_IOCTL(KDGKBENT)
+COMPATIBLE_IOCTL(KDSKBENT)
+COMPATIBLE_IOCTL(KDGKBSENT)
+COMPATIBLE_IOCTL(KDSKBSENT)
+COMPATIBLE_IOCTL(KDGKBDIACR)
+COMPATIBLE_IOCTL(KDSKBDIACR)
+COMPATIBLE_IOCTL(KDKBDREP)
+COMPATIBLE_IOCTL(KDGKBLED)
+ULONG_IOCTL(KDSKBLED)
+COMPATIBLE_IOCTL(KDGETLED)
+ULONG_IOCTL(KDSETLED)
+COMPATIBLE_IOCTL(GIO_SCRNMAP)
+COMPATIBLE_IOCTL(PIO_SCRNMAP)
+COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_FONTRESET)
+COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
+/* Big S */
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
+COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
+/* Big T */
+COMPATIBLE_IOCTL(TUNSETNOCSUM)
+COMPATIBLE_IOCTL(TUNSETDEBUG)
+COMPATIBLE_IOCTL(TUNSETPERSIST)
+COMPATIBLE_IOCTL(TUNSETOWNER)
+/* Big V */
+COMPATIBLE_IOCTL(VT_SETMODE)
+COMPATIBLE_IOCTL(VT_GETMODE)
+COMPATIBLE_IOCTL(VT_GETSTATE)
+COMPATIBLE_IOCTL(VT_OPENQRY)
+ULONG_IOCTL(VT_ACTIVATE)
+ULONG_IOCTL(VT_WAITACTIVE)
+ULONG_IOCTL(VT_RELDISP)
+ULONG_IOCTL(VT_DISALLOCATE)
+COMPATIBLE_IOCTL(VT_RESIZE)
+COMPATIBLE_IOCTL(VT_RESIZEX)
+COMPATIBLE_IOCTL(VT_LOCKSWITCH)
+COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+COMPATIBLE_IOCTL(VT_GETHIFONTMASK)
+/* Little p (/dev/rtc, /dev/envctrl, etc.) */
+COMPATIBLE_IOCTL(RTC_AIE_ON)
+COMPATIBLE_IOCTL(RTC_AIE_OFF)
+COMPATIBLE_IOCTL(RTC_UIE_ON)
+COMPATIBLE_IOCTL(RTC_UIE_OFF)
+COMPATIBLE_IOCTL(RTC_PIE_ON)
+COMPATIBLE_IOCTL(RTC_PIE_OFF)
+COMPATIBLE_IOCTL(RTC_WIE_ON)
+COMPATIBLE_IOCTL(RTC_WIE_OFF)
+COMPATIBLE_IOCTL(RTC_ALM_SET)
+COMPATIBLE_IOCTL(RTC_ALM_READ)
+COMPATIBLE_IOCTL(RTC_RD_TIME)
+COMPATIBLE_IOCTL(RTC_SET_TIME)
+COMPATIBLE_IOCTL(RTC_WKALM_SET)
+COMPATIBLE_IOCTL(RTC_WKALM_RD)
+/*
+ * These two are only for the sbus rtc driver, but
+ * hwclock tries them on every rtc device first when
+ * running on sparc.  On other architectures the entries
+ * are useless but harmless.
+ */
+COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
+COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
+/* Little m */
+COMPATIBLE_IOCTL(MTIOCTOP)
+/* Socket level stuff */
+COMPATIBLE_IOCTL(FIOQSIZE)
+COMPATIBLE_IOCTL(FIOSETOWN)
+COMPATIBLE_IOCTL(SIOCSPGRP)
+COMPATIBLE_IOCTL(FIOGETOWN)
+COMPATIBLE_IOCTL(SIOCGPGRP)
+COMPATIBLE_IOCTL(SIOCATMARK)
+COMPATIBLE_IOCTL(SIOCSIFLINK)
+COMPATIBLE_IOCTL(SIOCSIFENCAP)
+COMPATIBLE_IOCTL(SIOCGIFENCAP)
+COMPATIBLE_IOCTL(SIOCSIFNAME)
+COMPATIBLE_IOCTL(SIOCSARP)
+COMPATIBLE_IOCTL(SIOCGARP)
+COMPATIBLE_IOCTL(SIOCDARP)
+COMPATIBLE_IOCTL(SIOCSRARP)
+COMPATIBLE_IOCTL(SIOCGRARP)
+COMPATIBLE_IOCTL(SIOCDRARP)
+COMPATIBLE_IOCTL(SIOCADDDLCI)
+COMPATIBLE_IOCTL(SIOCDELDLCI)
+COMPATIBLE_IOCTL(SIOCGMIIPHY)
+COMPATIBLE_IOCTL(SIOCGMIIREG)
+COMPATIBLE_IOCTL(SIOCSMIIREG)
+COMPATIBLE_IOCTL(SIOCGIFVLAN)
+COMPATIBLE_IOCTL(SIOCSIFVLAN)
+COMPATIBLE_IOCTL(SIOCBRADDBR)
+COMPATIBLE_IOCTL(SIOCBRDELBR)
+/* SG stuff */
+COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_EMULATED_HOST)
+ULONG_IOCTL(SG_SET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
+COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
+COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
+COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
+COMPATIBLE_IOCTL(SG_SET_DEBUG)
+COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
+COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
+COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
+COMPATIBLE_IOCTL(SG_SCSI_RESET)
+COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
+COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
+COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
+/* PPP stuff */
+COMPATIBLE_IOCTL(PPPIOCGFLAGS)
+COMPATIBLE_IOCTL(PPPIOCSFLAGS)
+COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGUNIT)
+COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGMRU)
+COMPATIBLE_IOCTL(PPPIOCSMRU)
+COMPATIBLE_IOCTL(PPPIOCSMAXCID)
+COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+/* PPPIOCSCOMPRESS is translated */
+COMPATIBLE_IOCTL(PPPIOCGNPMODE)
+COMPATIBLE_IOCTL(PPPIOCSNPMODE)
+COMPATIBLE_IOCTL(PPPIOCGDEBUG)
+COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+/* PPPIOCSPASS is translated */
+/* PPPIOCSACTIVE is translated */
+/* PPPIOCGIDLE is translated */
+COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
+COMPATIBLE_IOCTL(PPPIOCATTACH)
+COMPATIBLE_IOCTL(PPPIOCDETACH)
+COMPATIBLE_IOCTL(PPPIOCSMRRU)
+COMPATIBLE_IOCTL(PPPIOCCONNECT)
+COMPATIBLE_IOCTL(PPPIOCDISCONN)
+COMPATIBLE_IOCTL(PPPIOCATTCHAN)
+COMPATIBLE_IOCTL(PPPIOCGCHAN)
+/* PPPOX */
+COMPATIBLE_IOCTL(PPPOEIOCSFWD)
+COMPATIBLE_IOCTL(PPPOEIOCDFWD)
+/* LP */
+COMPATIBLE_IOCTL(LPGETSTATUS)
+/* ppdev */
+COMPATIBLE_IOCTL(PPSETMODE)
+COMPATIBLE_IOCTL(PPRSTATUS)
+COMPATIBLE_IOCTL(PPRCONTROL)
+COMPATIBLE_IOCTL(PPWCONTROL)
+COMPATIBLE_IOCTL(PPFCONTROL)
+COMPATIBLE_IOCTL(PPRDATA)
+COMPATIBLE_IOCTL(PPWDATA)
+COMPATIBLE_IOCTL(PPCLAIM)
+COMPATIBLE_IOCTL(PPRELEASE)
+COMPATIBLE_IOCTL(PPYIELD)
+COMPATIBLE_IOCTL(PPEXCL)
+COMPATIBLE_IOCTL(PPDATADIR)
+COMPATIBLE_IOCTL(PPNEGOT)
+COMPATIBLE_IOCTL(PPWCTLONIRQ)
+COMPATIBLE_IOCTL(PPCLRIRQ)
+COMPATIBLE_IOCTL(PPSETPHASE)
+COMPATIBLE_IOCTL(PPGETMODES)
+COMPATIBLE_IOCTL(PPGETMODE)
+COMPATIBLE_IOCTL(PPGETPHASE)
+COMPATIBLE_IOCTL(PPGETFLAGS)
+COMPATIBLE_IOCTL(PPSETFLAGS)
+/* CDROM stuff */
+COMPATIBLE_IOCTL(CDROMPAUSE)
+COMPATIBLE_IOCTL(CDROMRESUME)
+COMPATIBLE_IOCTL(CDROMPLAYMSF)
+COMPATIBLE_IOCTL(CDROMPLAYTRKIND)
+COMPATIBLE_IOCTL(CDROMREADTOCHDR)
+COMPATIBLE_IOCTL(CDROMREADTOCENTRY)
+COMPATIBLE_IOCTL(CDROMSTOP)
+COMPATIBLE_IOCTL(CDROMSTART)
+COMPATIBLE_IOCTL(CDROMEJECT)
+COMPATIBLE_IOCTL(CDROMVOLCTRL)
+COMPATIBLE_IOCTL(CDROMSUBCHNL)
+ULONG_IOCTL(CDROMEJECT_SW)
+COMPATIBLE_IOCTL(CDROMMULTISESSION)
+COMPATIBLE_IOCTL(CDROM_GET_MCN)
+COMPATIBLE_IOCTL(CDROMRESET)
+COMPATIBLE_IOCTL(CDROMVOLREAD)
+COMPATIBLE_IOCTL(CDROMSEEK)
+COMPATIBLE_IOCTL(CDROMPLAYBLK)
+COMPATIBLE_IOCTL(CDROMCLOSETRAY)
+ULONG_IOCTL(CDROM_SET_OPTIONS)
+ULONG_IOCTL(CDROM_CLEAR_OPTIONS)
+ULONG_IOCTL(CDROM_SELECT_SPEED)
+ULONG_IOCTL(CDROM_SELECT_DISC)
+ULONG_IOCTL(CDROM_MEDIA_CHANGED)
+ULONG_IOCTL(CDROM_DRIVE_STATUS)
+COMPATIBLE_IOCTL(CDROM_DISC_STATUS)
+COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
+ULONG_IOCTL(CDROM_LOCKDOOR)
+ULONG_IOCTL(CDROM_DEBUG)
+COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
+ * not take a struct cdrom_read, instead they take a struct cdrom_msf
+ * which is compatible.
+ */
+COMPATIBLE_IOCTL(CDROMREADMODE2)
+COMPATIBLE_IOCTL(CDROMREADMODE1)
+COMPATIBLE_IOCTL(CDROMREADRAW)
+COMPATIBLE_IOCTL(CDROMREADCOOKED)
+COMPATIBLE_IOCTL(CDROMREADALL)
+/* DVD ioctls */
+COMPATIBLE_IOCTL(DVD_READ_STRUCT)
+COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
+COMPATIBLE_IOCTL(DVD_AUTH)
+/* pktcdvd */
+COMPATIBLE_IOCTL(PACKET_CTRL_CMD)
+/* Big A */
+/* sparc only */
+/* Big Q for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE)
+COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL)
+COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE)
+/* Big T for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_START)
+COMPATIBLE_IOCTL(SNDCTL_TMR_STOP)
+COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT)
+/* Little m for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD)
+/* Big P for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_DSP_RESET)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED)
+COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_POST)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR)
+/* SNDCTL_DSP_MAPINBUF,  XXX needs translation */
+/* SNDCTL_DSP_MAPOUTBUF,  XXX needs translation */
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY)
+COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER)
+/* Big C for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_COPR_RESET)
+COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RUN)
+COMPATIBLE_IOCTL(SNDCTL_COPR_HALT)
+COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG)
+/* Big M for sound/OSS */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR))
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE)
+/* SOUND_MIXER_READ_ENHANCE,  same value as READ_MUTE */
+/* SOUND_MIXER_READ_LOUD,  same value as READ_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3)
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR))
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE)
+/* SOUND_MIXER_WRITE_ENHANCE,  same value as WRITE_MUTE */
+/* SOUND_MIXER_WRITE_LOUD,  same value as WRITE_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS)
+COMPATIBLE_IOCTL(SOUND_MIXER_AGC)
+COMPATIBLE_IOCTL(SOUND_MIXER_3DSE)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
+COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
+COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
+COMPATIBLE_IOCTL(OSS_GETVERSION)
+/* AUTOFS */
+ULONG_IOCTL(AUTOFS_IOC_READY)
+ULONG_IOCTL(AUTOFS_IOC_FAIL)
+COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
+COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
+COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
+COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
+COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
+COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
+/* Raw devices */
+COMPATIBLE_IOCTL(RAW_SETBIND)
+COMPATIBLE_IOCTL(RAW_GETBIND)
+/* SMB ioctls which do not need any translations */
+COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
+/* Little a */
+COMPATIBLE_IOCTL(ATMSIGD_CTRL)
+COMPATIBLE_IOCTL(ATMARPD_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_MCAST)
+COMPATIBLE_IOCTL(ATMLEC_DATA)
+COMPATIBLE_IOCTL(ATM_SETSC)
+COMPATIBLE_IOCTL(SIOCSIFATMTCP)
+COMPATIBLE_IOCTL(SIOCMKCLIP)
+COMPATIBLE_IOCTL(ATMARP_MKIP)
+COMPATIBLE_IOCTL(ATMARP_SETENTRY)
+COMPATIBLE_IOCTL(ATMARP_ENCAP)
+COMPATIBLE_IOCTL(ATMTCP_CREATE)
+COMPATIBLE_IOCTL(ATMTCP_REMOVE)
+COMPATIBLE_IOCTL(ATMMPC_CTRL)
+COMPATIBLE_IOCTL(ATMMPC_DATA)
+/* Watchdog */
+COMPATIBLE_IOCTL(WDIOC_GETSUPPORT)
+COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETTEMP)
+COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
+COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
+COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT)
+COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT)
+/* Big R */
+COMPATIBLE_IOCTL(RNDGETENTCNT)
+COMPATIBLE_IOCTL(RNDADDTOENTCNT)
+COMPATIBLE_IOCTL(RNDGETPOOL)
+COMPATIBLE_IOCTL(RNDADDENTROPY)
+COMPATIBLE_IOCTL(RNDZAPENTCNT)
+COMPATIBLE_IOCTL(RNDCLEARPOOL)
+/* Bluetooth */
+COMPATIBLE_IOCTL(HCIDEVUP)
+COMPATIBLE_IOCTL(HCIDEVDOWN)
+COMPATIBLE_IOCTL(HCIDEVRESET)
+COMPATIBLE_IOCTL(HCIDEVRESTAT)
+COMPATIBLE_IOCTL(HCIGETDEVLIST)
+COMPATIBLE_IOCTL(HCIGETDEVINFO)
+COMPATIBLE_IOCTL(HCIGETCONNLIST)
+COMPATIBLE_IOCTL(HCIGETCONNINFO)
+COMPATIBLE_IOCTL(HCISETRAW)
+COMPATIBLE_IOCTL(HCISETSCAN)
+COMPATIBLE_IOCTL(HCISETAUTH)
+COMPATIBLE_IOCTL(HCISETENCRYPT)
+COMPATIBLE_IOCTL(HCISETPTYPE)
+COMPATIBLE_IOCTL(HCISETLINKPOL)
+COMPATIBLE_IOCTL(HCISETLINKMODE)
+COMPATIBLE_IOCTL(HCISETACLMTU)
+COMPATIBLE_IOCTL(HCISETSCOMTU)
+COMPATIBLE_IOCTL(HCIINQUIRY)
+COMPATIBLE_IOCTL(HCIUARTSETPROTO)
+COMPATIBLE_IOCTL(HCIUARTGETPROTO)
+COMPATIBLE_IOCTL(RFCOMMCREATEDEV)
+COMPATIBLE_IOCTL(RFCOMMRELEASEDEV)
+COMPATIBLE_IOCTL(RFCOMMGETDEVLIST)
+COMPATIBLE_IOCTL(RFCOMMGETDEVINFO)
+COMPATIBLE_IOCTL(RFCOMMSTEALDLC)
+COMPATIBLE_IOCTL(BNEPCONNADD)
+COMPATIBLE_IOCTL(BNEPCONNDEL)
+COMPATIBLE_IOCTL(BNEPGETCONNLIST)
+COMPATIBLE_IOCTL(BNEPGETCONNINFO)
+COMPATIBLE_IOCTL(CMTPCONNADD)
+COMPATIBLE_IOCTL(CMTPCONNDEL)
+COMPATIBLE_IOCTL(CMTPGETCONNLIST)
+COMPATIBLE_IOCTL(CMTPGETCONNINFO)
+COMPATIBLE_IOCTL(HIDPCONNADD)
+COMPATIBLE_IOCTL(HIDPCONNDEL)
+COMPATIBLE_IOCTL(HIDPGETCONNLIST)
+COMPATIBLE_IOCTL(HIDPGETCONNINFO)
+/* CAPI */
+COMPATIBLE_IOCTL(CAPI_REGISTER)
+COMPATIBLE_IOCTL(CAPI_GET_MANUFACTURER)
+COMPATIBLE_IOCTL(CAPI_GET_VERSION)
+COMPATIBLE_IOCTL(CAPI_GET_SERIAL)
+COMPATIBLE_IOCTL(CAPI_GET_PROFILE)
+COMPATIBLE_IOCTL(CAPI_MANUFACTURER_CMD)
+COMPATIBLE_IOCTL(CAPI_GET_ERRCODE)
+COMPATIBLE_IOCTL(CAPI_INSTALLED)
+COMPATIBLE_IOCTL(CAPI_GET_FLAGS)
+COMPATIBLE_IOCTL(CAPI_SET_FLAGS)
+COMPATIBLE_IOCTL(CAPI_CLR_FLAGS)
+COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT)
+COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT)
+/* Siemens Gigaset */
+COMPATIBLE_IOCTL(GIGASET_REDIR)
+COMPATIBLE_IOCTL(GIGASET_CONFIG)
+COMPATIBLE_IOCTL(GIGASET_BRKCHARS)
+COMPATIBLE_IOCTL(GIGASET_VERSION)
+/* Misc. */
+COMPATIBLE_IOCTL(0x41545900)           /* ATYIO_CLKR */
+COMPATIBLE_IOCTL(0x41545901)           /* ATYIO_CLKW */
+COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
+COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
+/* USB */
+COMPATIBLE_IOCTL(USBDEVFS_RESETEP)
+COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION)
+COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER)
+COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB)
+COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
+COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
+COMPATIBLE_IOCTL(USBDEVFS_RESET)
+COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
+COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
+/* MTD */
+COMPATIBLE_IOCTL(MEMGETINFO)
+COMPATIBLE_IOCTL(MEMERASE)
+COMPATIBLE_IOCTL(MEMLOCK)
+COMPATIBLE_IOCTL(MEMUNLOCK)
+COMPATIBLE_IOCTL(MEMGETREGIONCOUNT)
+COMPATIBLE_IOCTL(MEMGETREGIONINFO)
+COMPATIBLE_IOCTL(MEMGETBADBLOCK)
+COMPATIBLE_IOCTL(MEMSETBADBLOCK)
+/* NBD */
+ULONG_IOCTL(NBD_SET_SOCK)
+ULONG_IOCTL(NBD_SET_BLKSIZE)
+ULONG_IOCTL(NBD_SET_SIZE)
+COMPATIBLE_IOCTL(NBD_DO_IT)
+COMPATIBLE_IOCTL(NBD_CLEAR_SOCK)
+COMPATIBLE_IOCTL(NBD_CLEAR_QUE)
+COMPATIBLE_IOCTL(NBD_PRINT_DEBUG)
+ULONG_IOCTL(NBD_SET_SIZE_BLOCKS)
+COMPATIBLE_IOCTL(NBD_DISCONNECT)
+/* i2c */
+COMPATIBLE_IOCTL(I2C_SLAVE)
+COMPATIBLE_IOCTL(I2C_SLAVE_FORCE)
+COMPATIBLE_IOCTL(I2C_TENBIT)
+COMPATIBLE_IOCTL(I2C_PEC)
+COMPATIBLE_IOCTL(I2C_RETRIES)
+COMPATIBLE_IOCTL(I2C_TIMEOUT)
+/* wireless */
+COMPATIBLE_IOCTL(SIOCSIWCOMMIT)
+COMPATIBLE_IOCTL(SIOCGIWNAME)
+COMPATIBLE_IOCTL(SIOCSIWNWID)
+COMPATIBLE_IOCTL(SIOCGIWNWID)
+COMPATIBLE_IOCTL(SIOCSIWFREQ)
+COMPATIBLE_IOCTL(SIOCGIWFREQ)
+COMPATIBLE_IOCTL(SIOCSIWMODE)
+COMPATIBLE_IOCTL(SIOCGIWMODE)
+COMPATIBLE_IOCTL(SIOCSIWSENS)
+COMPATIBLE_IOCTL(SIOCGIWSENS)
+COMPATIBLE_IOCTL(SIOCSIWRANGE)
+COMPATIBLE_IOCTL(SIOCSIWPRIV)
+COMPATIBLE_IOCTL(SIOCGIWPRIV)
+COMPATIBLE_IOCTL(SIOCSIWSTATS)
+COMPATIBLE_IOCTL(SIOCGIWSTATS)
+COMPATIBLE_IOCTL(SIOCSIWAP)
+COMPATIBLE_IOCTL(SIOCGIWAP)
+COMPATIBLE_IOCTL(SIOCSIWSCAN)
+COMPATIBLE_IOCTL(SIOCSIWRATE)
+COMPATIBLE_IOCTL(SIOCGIWRATE)
+COMPATIBLE_IOCTL(SIOCSIWRTS)
+COMPATIBLE_IOCTL(SIOCGIWRTS)
+COMPATIBLE_IOCTL(SIOCSIWFRAG)
+COMPATIBLE_IOCTL(SIOCGIWFRAG)
+COMPATIBLE_IOCTL(SIOCSIWTXPOW)
+COMPATIBLE_IOCTL(SIOCGIWTXPOW)
+COMPATIBLE_IOCTL(SIOCSIWRETRY)
+COMPATIBLE_IOCTL(SIOCGIWRETRY)
+COMPATIBLE_IOCTL(SIOCSIWPOWER)
+COMPATIBLE_IOCTL(SIOCGIWPOWER)
+/* hiddev */
+COMPATIBLE_IOCTL(HIDIOCGVERSION)
+COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
+COMPATIBLE_IOCTL(HIDIOCGDEVINFO)
+COMPATIBLE_IOCTL(HIDIOCGSTRING)
+COMPATIBLE_IOCTL(HIDIOCINITREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORT)
+COMPATIBLE_IOCTL(HIDIOCSREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORTINFO)
+COMPATIBLE_IOCTL(HIDIOCGFIELDINFO)
+COMPATIBLE_IOCTL(HIDIOCGUSAGE)
+COMPATIBLE_IOCTL(HIDIOCSUSAGE)
+COMPATIBLE_IOCTL(HIDIOCGUCODE)
+COMPATIBLE_IOCTL(HIDIOCGFLAG)
+COMPATIBLE_IOCTL(HIDIOCSFLAG)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
+/* dvb */
+COMPATIBLE_IOCTL(AUDIO_STOP)
+COMPATIBLE_IOCTL(AUDIO_PLAY)
+COMPATIBLE_IOCTL(AUDIO_PAUSE)
+COMPATIBLE_IOCTL(AUDIO_CONTINUE)
+COMPATIBLE_IOCTL(AUDIO_SELECT_SOURCE)
+COMPATIBLE_IOCTL(AUDIO_SET_MUTE)
+COMPATIBLE_IOCTL(AUDIO_SET_AV_SYNC)
+COMPATIBLE_IOCTL(AUDIO_SET_BYPASS_MODE)
+COMPATIBLE_IOCTL(AUDIO_CHANNEL_SELECT)
+COMPATIBLE_IOCTL(AUDIO_GET_STATUS)
+COMPATIBLE_IOCTL(AUDIO_GET_CAPABILITIES)
+COMPATIBLE_IOCTL(AUDIO_CLEAR_BUFFER)
+COMPATIBLE_IOCTL(AUDIO_SET_ID)
+COMPATIBLE_IOCTL(AUDIO_SET_MIXER)
+COMPATIBLE_IOCTL(AUDIO_SET_STREAMTYPE)
+COMPATIBLE_IOCTL(AUDIO_SET_EXT_ID)
+COMPATIBLE_IOCTL(AUDIO_SET_ATTRIBUTES)
+COMPATIBLE_IOCTL(AUDIO_SET_KARAOKE)
+COMPATIBLE_IOCTL(DMX_START)
+COMPATIBLE_IOCTL(DMX_STOP)
+COMPATIBLE_IOCTL(DMX_SET_FILTER)
+COMPATIBLE_IOCTL(DMX_SET_PES_FILTER)
+COMPATIBLE_IOCTL(DMX_SET_BUFFER_SIZE)
+COMPATIBLE_IOCTL(DMX_GET_PES_PIDS)
+COMPATIBLE_IOCTL(DMX_GET_CAPS)
+COMPATIBLE_IOCTL(DMX_SET_SOURCE)
+COMPATIBLE_IOCTL(DMX_GET_STC)
+COMPATIBLE_IOCTL(FE_GET_INFO)
+COMPATIBLE_IOCTL(FE_DISEQC_RESET_OVERLOAD)
+COMPATIBLE_IOCTL(FE_DISEQC_SEND_MASTER_CMD)
+COMPATIBLE_IOCTL(FE_DISEQC_RECV_SLAVE_REPLY)
+COMPATIBLE_IOCTL(FE_DISEQC_SEND_BURST)
+COMPATIBLE_IOCTL(FE_SET_TONE)
+COMPATIBLE_IOCTL(FE_SET_VOLTAGE)
+COMPATIBLE_IOCTL(FE_ENABLE_HIGH_LNB_VOLTAGE)
+COMPATIBLE_IOCTL(FE_READ_STATUS)
+COMPATIBLE_IOCTL(FE_READ_BER)
+COMPATIBLE_IOCTL(FE_READ_SIGNAL_STRENGTH)
+COMPATIBLE_IOCTL(FE_READ_SNR)
+COMPATIBLE_IOCTL(FE_READ_UNCORRECTED_BLOCKS)
+COMPATIBLE_IOCTL(FE_SET_FRONTEND)
+COMPATIBLE_IOCTL(FE_GET_FRONTEND)
+COMPATIBLE_IOCTL(FE_GET_EVENT)
+COMPATIBLE_IOCTL(FE_DISHNETWORK_SEND_LEGACY_CMD)
+COMPATIBLE_IOCTL(VIDEO_STOP)
+COMPATIBLE_IOCTL(VIDEO_PLAY)
+COMPATIBLE_IOCTL(VIDEO_FREEZE)
+COMPATIBLE_IOCTL(VIDEO_CONTINUE)
+COMPATIBLE_IOCTL(VIDEO_SELECT_SOURCE)
+COMPATIBLE_IOCTL(VIDEO_SET_BLANK)
+COMPATIBLE_IOCTL(VIDEO_GET_STATUS)
+COMPATIBLE_IOCTL(VIDEO_SET_DISPLAY_FORMAT)
+COMPATIBLE_IOCTL(VIDEO_FAST_FORWARD)
+COMPATIBLE_IOCTL(VIDEO_SLOWMOTION)
+COMPATIBLE_IOCTL(VIDEO_GET_CAPABILITIES)
+COMPATIBLE_IOCTL(VIDEO_CLEAR_BUFFER)
+COMPATIBLE_IOCTL(VIDEO_SET_ID)
+COMPATIBLE_IOCTL(VIDEO_SET_STREAMTYPE)
+COMPATIBLE_IOCTL(VIDEO_SET_FORMAT)
+COMPATIBLE_IOCTL(VIDEO_SET_SYSTEM)
+COMPATIBLE_IOCTL(VIDEO_SET_HIGHLIGHT)
+COMPATIBLE_IOCTL(VIDEO_SET_SPU)
+COMPATIBLE_IOCTL(VIDEO_GET_NAVI)
+COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
+COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
+COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
+
+/* now things that need handlers */
 HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
 HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
 #ifdef CONFIG_NET
@@ -2638,4 +3474,156 @@ IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
 };
 
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
+#define IOCTL_HASHSIZE 256
+static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+
+static inline unsigned long ioctl32_hash(unsigned long cmd)
+{
+       return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
+}
+
+static void compat_ioctl_error(struct file *filp, unsigned int fd,
+               unsigned int cmd, unsigned long arg)
+{
+       char buf[10];
+       char *fn = "?";
+       char *path;
+
+       /* find the name of the device. */
+       path = (char *)__get_free_page(GFP_KERNEL);
+       if (path) {
+               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
+               if (IS_ERR(fn))
+                       fn = "?";
+       }
+
+        sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
+       if (!isprint(buf[1]))
+               sprintf(buf, "%02x", buf[1]);
+       compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
+                       "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
+                       current->comm, current->pid,
+                       (int)fd, (unsigned int)cmd, buf,
+                       (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
+                       (unsigned int)arg, fn);
+
+       if (path)
+               free_page((unsigned long)path);
+}
+
+asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct file *filp;
+       int error = -EBADF;
+       struct ioctl_trans *t;
+       int fput_needed;
+
+       filp = fget_light(fd, &fput_needed);
+       if (!filp)
+               goto out;
+
+       /* RED-PEN how should LSM module know it's handling 32bit? */
+       error = security_file_ioctl(filp, cmd, arg);
+       if (error)
+               goto out_fput;
+
+       /*
+        * To allow the compat_ioctl handlers to be self contained
+        * we need to check the common ioctls here first.
+        * Just handle them with the standard handlers below.
+        */
+       switch (cmd) {
+       case FIOCLEX:
+       case FIONCLEX:
+       case FIONBIO:
+       case FIOASYNC:
+       case FIOQSIZE:
+               break;
+
+       case FIBMAP:
+       case FIGETBSZ:
+       case FIONREAD:
+               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+                       break;
+               /*FALL THROUGH*/
+
+       default:
+               if (filp->f_op && filp->f_op->compat_ioctl) {
+                       error = filp->f_op->compat_ioctl(filp, cmd, arg);
+                       if (error != -ENOIOCTLCMD)
+                               goto out_fput;
+               }
+
+               if (!filp->f_op ||
+                   (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
+                       goto do_ioctl;
+               break;
+       }
+
+       for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
+               if (t->cmd == cmd)
+                       goto found_handler;
+       }
+
+       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
+           cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+               error = siocdevprivate_ioctl(fd, cmd, arg);
+       } else {
+               static int count;
+
+               if (++count <= 50)
+                       compat_ioctl_error(filp, fd, cmd, arg);
+               error = -EINVAL;
+       }
+
+       goto out_fput;
+
+ found_handler:
+       if (t->handler) {
+               lock_kernel();
+               error = t->handler(fd, cmd, arg, filp);
+               unlock_kernel();
+               goto out_fput;
+       }
+
+ do_ioctl:
+       error = vfs_ioctl(filp, fd, cmd, arg);
+ out_fput:
+       fput_light(filp, fput_needed);
+ out:
+       return error;
+}
+
+static void ioctl32_insert_translation(struct ioctl_trans *trans)
+{
+       unsigned long hash;
+       struct ioctl_trans *t;
+
+       hash = ioctl32_hash (trans->cmd);
+       if (!ioctl32_hash_table[hash])
+               ioctl32_hash_table[hash] = trans;
+       else {
+               t = ioctl32_hash_table[hash];
+               while (t->next)
+                       t = t->next;
+               trans->next = NULL;
+               t->next = trans;
+       }
+}
+
+static int __init init_sys32_ioctl(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ioctl_start); i++) {
+               if (ioctl_start[i].next != 0) {
+                       printk("ioctl translation %d bad\n",i);
+                       return -1;
+               }
+
+               ioctl32_insert_translation(&ioctl_start[i]);
+       }
+       return 0;
+}
+__initcall(init_sys32_ioctl);
index d98be5e013280e7708e825d4b458acc3219c5a62..3527c7c6def898cb39d1118738b8d7a89475edc7 100644 (file)
@@ -77,36 +77,6 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
        return ret;
 }
 
-
-/**
- *     flush_read_buffer - push buffer to userspace.
- *     @buffer:        data buffer for file.
- *     @userbuf:       user-passed buffer.
- *     @count:         number of bytes requested.
- *     @ppos:          file position.
- *
- *     Copy the buffer we filled in fill_read_buffer() to userspace.
- *     This is done at the reader's leisure, copying and advancing
- *     the amount they specify each time.
- *     This may be called continuously until the buffer is empty.
- */
-static int flush_read_buffer(struct configfs_buffer * buffer, char __user * buf,
-                            size_t count, loff_t * ppos)
-{
-       int error;
-
-       if (*ppos > buffer->count)
-               return 0;
-
-       if (count > (buffer->count - *ppos))
-               count = buffer->count - *ppos;
-
-       error = copy_to_user(buf,buffer->page + *ppos,count);
-       if (!error)
-               *ppos += count;
-       return error ? -EFAULT : count;
-}
-
 /**
  *     configfs_read_file - read an attribute.
  *     @file:  file pointer.
@@ -139,7 +109,8 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
                 __FUNCTION__, count, *ppos, buffer->page);
-       retval = flush_read_buffer(buffer,buf,count,ppos);
+       retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
+                                        buffer->count);
 out:
        up(&buffer->sem);
        return retval;
index d1bf5d8aeb5a98a3f1d6ea3289897617b802165e..0e73aa0a0e8b66a1bf213ed53ad579bbabe7b2f3 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/fsnotify.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/hash.h>
 #include <linux/cache.h>
 #include <linux/module.h>
@@ -121,6 +120,28 @@ static void dentry_iput(struct dentry * dentry)
        }
 }
 
+/**
+ * d_kill - kill dentry and return parent
+ * @dentry: dentry to kill
+ *
+ * Called with dcache_lock and d_lock, releases both.  The dentry must
+ * already be unhashed and removed from the LRU.
+ *
+ * If this is the root of the dentry tree, return NULL.
+ */
+static struct dentry *d_kill(struct dentry *dentry)
+{
+       struct dentry *parent;
+
+       list_del(&dentry->d_u.d_child);
+       dentry_stat.nr_dentry--;        /* For d_free, below */
+       /*drops the locks, at that point nobody can reach this dentry */
+       dentry_iput(dentry);
+       parent = dentry->d_parent;
+       d_free(dentry);
+       return dentry == parent ? NULL : parent;
+}
+
 /* 
  * This is dput
  *
@@ -189,28 +210,17 @@ repeat:
 
 unhash_it:
        __d_drop(dentry);
-
-kill_it: {
-               struct dentry *parent;
-
-               /* If dentry was on d_lru list
-                * delete it from there
-                */
-               if (!list_empty(&dentry->d_lru)) {
-                       list_del(&dentry->d_lru);
-                       dentry_stat.nr_unused--;
-               }
-               list_del(&dentry->d_u.d_child);
-               dentry_stat.nr_dentry--;        /* For d_free, below */
-               /*drops the locks, at that point nobody can reach this dentry */
-               dentry_iput(dentry);
-               parent = dentry->d_parent;
-               d_free(dentry);
-               if (dentry == parent)
-                       return;
-               dentry = parent;
-               goto repeat;
+kill_it:
+       /* If dentry was on d_lru list
+        * delete it from there
+        */
+       if (!list_empty(&dentry->d_lru)) {
+               list_del(&dentry->d_lru);
+               dentry_stat.nr_unused--;
        }
+       dentry = d_kill(dentry);
+       if (dentry)
+               goto repeat;
 }
 
 /**
@@ -371,22 +381,40 @@ restart:
  * Throw away a dentry - free the inode, dput the parent.  This requires that
  * the LRU list has already been removed.
  *
+ * If prune_parents is true, try to prune ancestors as well.
+ *
  * Called with dcache_lock, drops it and then regains.
  * Called with dentry->d_lock held, drops it.
  */
-static void prune_one_dentry(struct dentry * dentry)
+static void prune_one_dentry(struct dentry * dentry, int prune_parents)
 {
-       struct dentry * parent;
-
        __d_drop(dentry);
-       list_del(&dentry->d_u.d_child);
-       dentry_stat.nr_dentry--;        /* For d_free, below */
-       dentry_iput(dentry);
-       parent = dentry->d_parent;
-       d_free(dentry);
-       if (parent != dentry)
-               dput(parent);
+       dentry = d_kill(dentry);
+       if (!prune_parents) {
+               dput(dentry);
+               spin_lock(&dcache_lock);
+               return;
+       }
+
+       /*
+        * Prune ancestors.  Locking is simpler than in dput(),
+        * because dcache_lock needs to be taken anyway.
+        */
        spin_lock(&dcache_lock);
+       while (dentry) {
+               if (!atomic_dec_and_lock(&dentry->d_count, &dentry->d_lock))
+                       return;
+
+               if (dentry->d_op && dentry->d_op->d_delete)
+                       dentry->d_op->d_delete(dentry);
+               if (!list_empty(&dentry->d_lru)) {
+                       list_del(&dentry->d_lru);
+                       dentry_stat.nr_unused--;
+               }
+               __d_drop(dentry);
+               dentry = d_kill(dentry);
+               spin_lock(&dcache_lock);
+       }
 }
 
 /**
@@ -394,6 +422,7 @@ static void prune_one_dentry(struct dentry * dentry)
  * @count: number of entries to try and free
  * @sb: if given, ignore dentries for other superblocks
  *         which are being unmounted.
+ * @prune_parents: if true, try to prune ancestors as well in one go
  *
  * Shrink the dcache. This is done when we need
  * more memory, or simply when we need to unmount
@@ -404,7 +433,7 @@ static void prune_one_dentry(struct dentry * dentry)
  * all the dentries are in use.
  */
  
-static void prune_dcache(int count, struct super_block *sb)
+static void prune_dcache(int count, struct super_block *sb, int prune_parents)
 {
        spin_lock(&dcache_lock);
        for (; count ; count--) {
@@ -464,7 +493,7 @@ static void prune_dcache(int count, struct super_block *sb)
                 * without taking the s_umount lock (I already hold it).
                 */
                if (sb && dentry->d_sb == sb) {
-                       prune_one_dentry(dentry);
+                       prune_one_dentry(dentry, prune_parents);
                        continue;
                }
                /*
@@ -479,7 +508,7 @@ static void prune_dcache(int count, struct super_block *sb)
                s_umount = &dentry->d_sb->s_umount;
                if (down_read_trylock(s_umount)) {
                        if (dentry->d_sb->s_root != NULL) {
-                               prune_one_dentry(dentry);
+                               prune_one_dentry(dentry, prune_parents);
                                up_read(s_umount);
                                continue;
                        }
@@ -550,7 +579,7 @@ repeat:
                        spin_unlock(&dentry->d_lock);
                        continue;
                }
-               prune_one_dentry(dentry);
+               prune_one_dentry(dentry, 1);
                cond_resched_lock(&dcache_lock);
                goto repeat;
        }
@@ -829,7 +858,7 @@ void shrink_dcache_parent(struct dentry * parent)
        int found;
 
        while ((found = select_parent(parent)) != 0)
-               prune_dcache(found, parent->d_sb);
+               prune_dcache(found, parent->d_sb, 1);
 }
 
 /*
@@ -849,7 +878,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
        if (nr) {
                if (!(gfp_mask & __GFP_FS))
                        return -1;
-               prune_dcache(nr, NULL);
+               prune_dcache(nr, NULL, 1);
        }
        return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
@@ -1823,6 +1852,16 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
        struct vfsmount *rootmnt;
        struct dentry *root;
 
+       /*
+        * We have various synthetic filesystems that never get mounted.  On
+        * these filesystems dentries are never used for lookup purposes, and
+        * thus don't need to be hashed.  They also don't need a name until a
+        * user wants to identify the object in /proc/pid/fd/.  The little hack
+        * below allows us to generate a name for these objects on demand:
+        */
+       if (dentry->d_op && dentry->d_op->d_dname)
+               return dentry->d_op->d_dname(dentry, buf, buflen);
+
        read_lock(&current->fs->lock);
        rootmnt = mntget(current->fs->rootmnt);
        root = dget(current->fs->root);
@@ -1835,6 +1874,27 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
        return res;
 }
 
+/*
+ * Helper function for dentry_operations.d_dname() members
+ */
+char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
+                       const char *fmt, ...)
+{
+       va_list args;
+       char temp[64];
+       int sz;
+
+       va_start(args, fmt);
+       sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
+       va_end(args);
+
+       if (sz > sizeof(temp) || sz > buflen)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       buffer += buflen - sz;
+       return memcpy(buffer, temp, sz);
+}
+
 /*
  * NOTE! The user-level library version returns a
  * character pointer. The kernel system call just
index 643e57b622bd64c9e88d09f61355e55fd0220a8e..06ef9a255c76f7c8657176bc850b5f4c81909f75 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/tty.h>
 #include <linux/devpts_fs.h>
 #include <linux/parser.h>
+#include <linux/fsnotify.h>
 
 #define DEVPTS_SUPER_MAGIC 0x1cd1
 
@@ -178,8 +179,10 @@ int devpts_pty_new(struct tty_struct *tty)
        inode->i_private = tty;
 
        dentry = get_node(number);
-       if (!IS_ERR(dentry) && !dentry->d_inode)
+       if (!IS_ERR(dentry) && !dentry->d_inode) {
                d_instantiate(dentry, inode);
+               fsnotify_create(devpts_root->d_inode, dentry);
+       }
 
        mutex_unlock(&devpts_root->d_inode->i_mutex);
 
index d9d0833444f59da15dc8be42420c13366429d402..8593f3dfd2990a013b6fd580e22e1e82b83d4fbf 100644 (file)
@@ -439,7 +439,7 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
  * Wait on and process all in-flight BIOs.  This must only be called once
  * all bios have been issued so that the refcount can only decrease.
  * This just waits for all bios to make it through dio_bio_complete.  IO
- * errors are propogated through dio->io_error and should be propogated via
+ * errors are propagated through dio->io_error and should be propagated via
  * dio_complete().
  */
 static void dio_await_completion(struct dio *dio)
@@ -867,7 +867,6 @@ static int do_direct_IO(struct dio *dio)
 do_holes:
                        /* Handle holes */
                        if (!buffer_mapped(map_bh)) {
-                               char *kaddr;
                                loff_t i_size_aligned;
 
                                /* AKPM: eargh, -ENOTBLK is a hack */
@@ -888,11 +887,8 @@ do_holes:
                                        page_cache_release(page);
                                        goto out;
                                }
-                               kaddr = kmap_atomic(page, KM_USER0);
-                               memset(kaddr + (block_in_page << blkbits),
-                                               0, 1 << blkbits);
-                               flush_dcache_page(page);
-                               kunmap_atomic(kaddr, KM_USER0);
+                               zero_user_page(page, block_in_page << blkbits,
+                                               1 << blkbits, KM_USER0);
                                dio->block_in_file++;
                                block_in_page++;
                                goto next_block;
index 0a5febc159f25b03ecc70f2a22090f3c3fa4fe33..3a995841de90e0f648dc915ba450a2aaf7fa9674 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -475,7 +474,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
                spin_lock(&dq_list_lock);
                dirty = &dqopt->info[cnt].dqi_dirty_list;
                while (!list_empty(dirty)) {
-                       dquot = list_entry(dirty->next, struct dquot, dq_dirty);
+                       dquot = list_first_entry(dirty, struct dquot, dq_dirty);
                        /* Dirty and inactive can be only bad dquot... */
                        if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
                                clear_dquot_dirty(dquot);
@@ -721,7 +720,8 @@ static inline int dqput_blocks(struct dquot *dquot)
 
 /* Remove references to dquots from inode - add dquot to list for freeing if needed */
 /* We can't race with anybody because we hold dqptr_sem for writing... */
-int remove_inode_dquot_ref(struct inode *inode, int type, struct list_head *tofree_head)
+static int remove_inode_dquot_ref(struct inode *inode, int type,
+                                 struct list_head *tofree_head)
 {
        struct dquot *dquot = inode->i_dquot[type];
 
index 7a7d25d541e727cb4515acb771c3e077773c5a20..9881b5c5de59b6f564435cc26dc17f5a638e32bc 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/security.h>
-#include <linux/smp_lock.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
 #include "ecryptfs_kernel.h"
index 3ae644e7e8606cddcdc1cb02791e51dfc73cb941..b5c7ca584939acb628cd3f7644a99c3c53d0681d 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/hash.h>
@@ -185,7 +184,7 @@ struct eppoll_entry {
 
 /*
  * Each file descriptor added to the eventpoll interface will
- * have an entry of this type linked to the hash.
+ * have an entry of this type linked to the "rbr" RB tree.
  */
 struct epitem {
        /* RB-Tree node used to link this structure to the eventpoll rb-tree */
@@ -217,15 +216,6 @@ struct epitem {
 
        /* List header used to link this item to the "struct file" items list */
        struct list_head fllink;
-
-       /* List header used to link the item to the transfer list */
-       struct list_head txlink;
-
-       /*
-        * This is used during the collection/transfer of events to userspace
-        * to pin items empty events set.
-        */
-       unsigned int revents;
 };
 
 /* Wrapper struct used by poll queueing */
@@ -258,11 +248,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi);
 static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key);
 static int ep_eventpoll_close(struct inode *inode, struct file *file);
 static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
-static int ep_collect_ready_items(struct eventpoll *ep,
-                                 struct list_head *txlist, int maxevents);
 static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
-                         struct epoll_event __user *events);
-static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist);
+                         struct epoll_event __user *events, int maxevents);
 static int ep_events_transfer(struct eventpoll *ep,
                              struct epoll_event __user *events,
                              int maxevents);
@@ -355,17 +342,6 @@ static inline int ep_rb_linked(struct rb_node *n)
        return rb_parent(n) != n;
 }
 
-/*
- * Remove the item from the list and perform its initialization.
- * This is useful for us because we can test if the item is linked
- * using "ep_is_linked(p)".
- */
-static inline void ep_list_del(struct list_head *p)
-{
-       list_del(p);
-       INIT_LIST_HEAD(p);
-}
-
 /* Tells us if the item is currently linked */
 static inline int ep_is_linked(struct list_head *p)
 {
@@ -385,7 +361,7 @@ static inline struct epitem * ep_item_from_epqueue(poll_table *p)
 }
 
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
-static inline int ep_op_hash_event(int op)
+static inline int ep_op_has_event(int op)
 {
        return op != EPOLL_CTL_DEL;
 }
@@ -477,10 +453,10 @@ void eventpoll_release_file(struct file *file)
        mutex_lock(&epmutex);
 
        while (!list_empty(lsthead)) {
-               epi = list_entry(lsthead->next, struct epitem, fllink);
+               epi = list_first_entry(lsthead, struct epitem, fllink);
 
                ep = epi->ep;
-               ep_list_del(&epi->fllink);
+               list_del_init(&epi->fllink);
                down_write(&ep->sem);
                ep_remove(ep, epi);
                up_write(&ep->sem);
@@ -557,7 +533,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
                     current, epfd, op, fd, event));
 
        error = -EFAULT;
-       if (ep_op_hash_event(op) &&
+       if (ep_op_has_event(op) &&
            copy_from_user(&epds, event, sizeof(struct epoll_event)))
                goto eexit_1;
 
@@ -594,7 +570,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
 
        down_write(&ep->sem);
 
-       /* Try to lookup the file inside our hash table */
+       /* Try to lookup the file inside our RB tree */
        epi = ep_find(ep, tfile, fd);
 
        error = -EINVAL;
@@ -876,7 +852,7 @@ static void ep_free(struct eventpoll *ep)
        }
 
        /*
-        * Walks through the whole hash by freeing each "struct epitem". At this
+        * Walks through the whole tree by freeing each "struct epitem". At this
         * point we are sure no poll callbacks will be lingering around, and also by
         * write-holding "sem" we can be sure that no file cleanup code will hit
         * us during this operation. So we can avoid the lock on "ep->lock".
@@ -891,7 +867,7 @@ static void ep_free(struct eventpoll *ep)
 
 
 /*
- * Search the file inside the eventpoll hash. It add usage count to
+ * Search the file inside the eventpoll tree. It add usage count to
  * the returned item, so the caller must call ep_release_epitem()
  * after finished using the "struct epitem".
  */
@@ -1011,7 +987,6 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
        ep_rb_initnode(&epi->rbn);
        INIT_LIST_HEAD(&epi->rdllink);
        INIT_LIST_HEAD(&epi->fllink);
-       INIT_LIST_HEAD(&epi->txlink);
        INIT_LIST_HEAD(&epi->pwqlist);
        epi->ep = ep;
        ep_set_ffd(&epi->ffd, tfile, fd);
@@ -1080,7 +1055,7 @@ eexit_2:
         */
        write_lock_irqsave(&ep->lock, flags);
        if (ep_is_linked(&epi->rdllink))
-               ep_list_del(&epi->rdllink);
+               list_del_init(&epi->rdllink);
        write_unlock_irqrestore(&ep->lock, flags);
 
        kmem_cache_free(epi_cache, epi);
@@ -1119,7 +1094,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
        epi->event.data = event->data;
 
        /*
-        * If the item is not linked to the hash it means that it's on its
+        * If the item is not linked to the RB tree it means that it's on its
         * way toward the removal. Do nothing in this case.
         */
        if (ep_rb_linked(&epi->rbn)) {
@@ -1168,9 +1143,9 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
 
        if (nwait) {
                while (!list_empty(lsthead)) {
-                       pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
+                       pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
 
-                       ep_list_del(&pwq->llink);
+                       list_del_init(&pwq->llink);
                        remove_wait_queue(pwq->whead, &pwq->wait);
                        kmem_cache_free(pwq_cache, pwq);
                }
@@ -1213,7 +1188,7 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
         * we want to remove it from this list to avoid stale events.
         */
        if (ep_is_linked(&epi->rdllink))
-               ep_list_del(&epi->rdllink);
+               list_del_init(&epi->rdllink);
 
        error = 0;
 eexit_1:
@@ -1226,7 +1201,7 @@ eexit_1:
 
 
 /*
- * Removes a "struct epitem" from the eventpoll hash and deallocates
+ * Removes a "struct epitem" from the eventpoll RB tree and deallocates
  * all the associated resources.
  */
 static int ep_remove(struct eventpoll *ep, struct epitem *epi)
@@ -1248,13 +1223,13 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        /* Remove the current item from the list of epoll hooks */
        spin_lock(&file->f_ep_lock);
        if (ep_is_linked(&epi->fllink))
-               ep_list_del(&epi->fllink);
+               list_del_init(&epi->fllink);
        spin_unlock(&file->f_ep_lock);
 
        /* We need to acquire the write IRQ lock before calling ep_unlink() */
        write_lock_irqsave(&ep->lock, flags);
 
-       /* Really unlink the item from the hash */
+       /* Really unlink the item from the RB tree */
        error = ep_unlink(ep, epi);
 
        write_unlock_irqrestore(&ep->lock, flags);
@@ -1361,72 +1336,31 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
 }
 
 
-/*
- * Since we have to release the lock during the __copy_to_user() operation and
- * during the f_op->poll() call, we try to collect the maximum number of items
- * by reducing the irqlock/irqunlock switching rate.
- */
-static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist, int maxevents)
-{
-       int nepi;
-       unsigned long flags;
-       struct list_head *lsthead = &ep->rdllist, *lnk;
-       struct epitem *epi;
-
-       write_lock_irqsave(&ep->lock, flags);
-
-       for (nepi = 0, lnk = lsthead->next; lnk != lsthead && nepi < maxevents;) {
-               epi = list_entry(lnk, struct epitem, rdllink);
-
-               lnk = lnk->next;
-
-               /* If this file is already in the ready list we exit soon */
-               if (!ep_is_linked(&epi->txlink)) {
-                       /*
-                        * This is initialized in this way so that the default
-                        * behaviour of the reinjecting code will be to push back
-                        * the item inside the ready list.
-                        */
-                       epi->revents = epi->event.events;
-
-                       /* Link the ready item into the transfer list */
-                       list_add(&epi->txlink, txlist);
-                       nepi++;
-
-                       /*
-                        * Unlink the item from the ready list.
-                        */
-                       ep_list_del(&epi->rdllink);
-               }
-       }
-
-       write_unlock_irqrestore(&ep->lock, flags);
-
-       return nepi;
-}
-
-
 /*
  * This function is called without holding the "ep->lock" since the call to
  * __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ
  * because of the way poll() is traditionally implemented in Linux.
  */
 static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
-                         struct epoll_event __user *events)
+                         struct epoll_event __user *events, int maxevents)
 {
-       int eventcnt = 0;
+       int eventcnt, error = -EFAULT, pwake = 0;
        unsigned int revents;
-       struct list_head *lnk;
+       unsigned long flags;
        struct epitem *epi;
+       struct list_head injlist;
+
+       INIT_LIST_HEAD(&injlist);
 
        /*
         * We can loop without lock because this is a task private list.
-        * The test done during the collection loop will guarantee us that
-        * another task will not try to collect this file. Also, items
-        * cannot vanish during the loop because we are holding "sem".
+        * We just splice'd out the ep->rdllist in ep_collect_ready_items().
+        * Items cannot vanish during the loop because we are holding "sem" in
+        * read.
         */
-       list_for_each(lnk, txlist) {
-               epi = list_entry(lnk, struct epitem, txlink);
+       for (eventcnt = 0; !list_empty(txlist) && eventcnt < maxevents;) {
+               epi = list_first_entry(txlist, struct epitem, rdllink);
+               prefetch(epi->rdllink.next);
 
                /*
                 * Get the ready file event set. We can safely use the file
@@ -1434,64 +1368,65 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
                 * guarantee that both the file and the item will not vanish.
                 */
                revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL);
+               revents &= epi->event.events;
 
                /*
-                * Set the return event set for the current file descriptor.
-                * Note that only the task task was successfully able to link
-                * the item to its "txlist" will write this field.
+                * Is the event mask intersect the caller-requested one,
+                * deliver the event to userspace. Again, we are holding
+                * "sem" in read, so no operations coming from userspace
+                * can change the item.
                 */
-               epi->revents = revents & epi->event.events;
-
-               if (epi->revents) {
-                       if (__put_user(epi->revents,
+               if (revents) {
+                       if (__put_user(revents,
                                       &events[eventcnt].events) ||
                            __put_user(epi->event.data,
                                       &events[eventcnt].data))
-                               return -EFAULT;
+                               goto errxit;
                        if (epi->event.events & EPOLLONESHOT)
                                epi->event.events &= EP_PRIVATE_BITS;
                        eventcnt++;
                }
-       }
-       return eventcnt;
-}
-
-
-/*
- * Walk through the transfer list we collected with ep_collect_ready_items()
- * and, if 1) the item is still "alive" 2) its event set is not empty 3) it's
- * not already linked, links it to the ready list. Same as above, we are holding
- * "sem" so items cannot vanish underneath our nose.
- */
-static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
-{
-       int ricnt = 0, pwake = 0;
-       unsigned long flags;
-       struct epitem *epi;
-
-       write_lock_irqsave(&ep->lock, flags);
-
-       while (!list_empty(txlist)) {
-               epi = list_entry(txlist->next, struct epitem, txlink);
-
-               /* Unlink the current item from the transfer list */
-               ep_list_del(&epi->txlink);
 
                /*
-                * If the item is no more linked to the interest set, we don't
-                * have to push it inside the ready list because the following
-                * ep_release_epitem() is going to drop it. Also, if the current
-                * item is set to have an Edge Triggered behaviour, we don't have
-                * to push it back either.
+                * This is tricky. We are holding the "sem" in read, and this
+                * means that the operations that can change the "linked" status
+                * of the epoll item (epi->rbn and epi->rdllink), cannot touch
+                * them.  Also, since we are "linked" from a epi->rdllink POV
+                * (the item is linked to our transmission list we just
+                * spliced), the ep_poll_callback() cannot touch us either,
+                * because of the check present in there. Another parallel
+                * epoll_wait() will not get the same result set, since we
+                * spliced the ready list before.  Note that list_del() still
+                * shows the item as linked to the test in ep_poll_callback().
                 */
-               if (ep_rb_linked(&epi->rbn) && !(epi->event.events & EPOLLET) &&
-                   (epi->revents & epi->event.events) && !ep_is_linked(&epi->rdllink)) {
-                       list_add_tail(&epi->rdllink, &ep->rdllist);
-                       ricnt++;
+               list_del(&epi->rdllink);
+               if (!(epi->event.events & EPOLLET) &&
+                               (revents & epi->event.events))
+                       list_add_tail(&epi->rdllink, &injlist);
+               else {
+                       /*
+                        * Be sure the item is totally detached before re-init
+                        * the list_head. After INIT_LIST_HEAD() is committed,
+                        * the ep_poll_callback() can requeue the item again,
+                        * but we don't care since we are already past it.
+                        */
+                       smp_mb();
+                       INIT_LIST_HEAD(&epi->rdllink);
                }
        }
+       error = 0;
 
-       if (ricnt) {
+       errxit:
+
+       /*
+        * If the re-injection list or the txlist are not empty, re-splice
+        * them to the ready list and do proper wakeups.
+        */
+       if (!list_empty(&injlist) || !list_empty(txlist)) {
+               write_lock_irqsave(&ep->lock, flags);
+
+               list_splice(txlist, &ep->rdllist);
+               list_splice(&injlist, &ep->rdllist);
                /*
                 * Wake up ( if active ) both the eventpoll wait list and the ->poll()
                 * wait list.
@@ -1501,13 +1436,15 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
                                         TASK_INTERRUPTIBLE);
                if (waitqueue_active(&ep->poll_wait))
                        pwake++;
-       }
 
-       write_unlock_irqrestore(&ep->lock, flags);
+               write_unlock_irqrestore(&ep->lock, flags);
+       }
 
        /* We have to call this outside the lock */
        if (pwake)
                ep_poll_safewake(&psw, &ep->poll_wait);
+
+       return eventcnt == 0 ? error: eventcnt;
 }
 
 
@@ -1517,7 +1454,8 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
 static int ep_events_transfer(struct eventpoll *ep,
                              struct epoll_event __user *events, int maxevents)
 {
-       int eventcnt = 0;
+       int eventcnt;
+       unsigned long flags;
        struct list_head txlist;
 
        INIT_LIST_HEAD(&txlist);
@@ -1528,14 +1466,17 @@ static int ep_events_transfer(struct eventpoll *ep,
         */
        down_read(&ep->sem);
 
-       /* Collect/extract ready items */
-       if (ep_collect_ready_items(ep, &txlist, maxevents) > 0) {
-               /* Build result set in userspace */
-               eventcnt = ep_send_events(ep, &txlist, events);
+       /*
+        * Steal the ready list, and re-init the original one to the
+        * empty list.
+        */
+       write_lock_irqsave(&ep->lock, flags);
+       list_splice(&ep->rdllist, &txlist);
+       INIT_LIST_HEAD(&ep->rdllist);
+       write_unlock_irqrestore(&ep->lock, flags);
 
-               /* Reinject ready items into the ready list */
-               ep_reinject_items(ep, &txlist);
-       }
+       /* Build result set in userspace */
+       eventcnt = ep_send_events(ep, &txlist, events, maxevents);
 
        up_read(&ep->sem);
 
@@ -1612,14 +1553,12 @@ retry:
        return res;
 }
 
-
 static int eventpollfs_delete_dentry(struct dentry *dentry)
 {
 
        return 1;
 }
 
-
 static struct inode *ep_eventpoll_inode(void)
 {
        int error = -ENOMEM;
@@ -1647,7 +1586,6 @@ eexit_1:
        return ERR_PTR(error);
 }
 
-
 static int
 eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
                   const char *dev_name, void *data, struct vfsmount *mnt)
index 3155e915307aa7256f9f7d9e0d01a93a42aa76a0..1ba85c7fc6af7e4290ac494563f3fc6c8d8587bd 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -100,6 +100,7 @@ int unregister_binfmt(struct linux_binfmt * fmt)
        while (*tmp) {
                if (fmt == *tmp) {
                        *tmp = fmt->next;
+                       fmt->next = NULL;
                        write_unlock(&binfmt_lock);
                        return 0;
                }
@@ -982,33 +983,51 @@ void compute_creds(struct linux_binprm *bprm)
        task_unlock(current);
        security_bprm_post_apply_creds(bprm);
 }
-
 EXPORT_SYMBOL(compute_creds);
 
+/*
+ * Arguments are '\0' separated strings found at the location bprm->p
+ * points to; chop off the first by relocating brpm->p to right after
+ * the first '\0' encountered.
+ */
 void remove_arg_zero(struct linux_binprm *bprm)
 {
        if (bprm->argc) {
-               unsigned long offset;
-               char * kaddr;
-               struct page *page;
+               char ch;
 
-               offset = bprm->p % PAGE_SIZE;
-               goto inside;
+               do {
+                       unsigned long offset;
+                       unsigned long index;
+                       char *kaddr;
+                       struct page *page;
 
-               while (bprm->p++, *(kaddr+offset++)) {
-                       if (offset != PAGE_SIZE)
-                               continue;
-                       offset = 0;
-                       kunmap_atomic(kaddr, KM_USER0);
-inside:
-                       page = bprm->page[bprm->p/PAGE_SIZE];
+                       offset = bprm->p & ~PAGE_MASK;
+                       index = bprm->p >> PAGE_SHIFT;
+
+                       page = bprm->page[index];
                        kaddr = kmap_atomic(page, KM_USER0);
-               }
-               kunmap_atomic(kaddr, KM_USER0);
+
+                       /* run through page until we reach end or find NUL */
+                       do {
+                               ch = *(kaddr + offset);
+
+                               /* discard that character... */
+                               bprm->p++;
+                               offset++;
+                       } while (offset < PAGE_SIZE && ch != '\0');
+
+                       kunmap_atomic(kaddr, KM_USER0);
+
+                       /* free the old page */
+                       if (offset == PAGE_SIZE) {
+                               __free_page(page);
+                               bprm->page[index] = NULL;
+                       }
+               } while (ch != '\0');
+
                bprm->argc--;
        }
 }
-
 EXPORT_SYMBOL(remove_arg_zero);
 
 /*
index 93e77c3d24906af5156254b29ee1cd3e39ba1ac3..e98f6cd7200cd65fd709bf7ba4339a3e4f977216 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/namei.h>
 
 struct export_operations export_op_default;
index 1d1e7e30d70e1fd21e0890a82c64fb5fc340acb0..2bf49d7ef841423d03c44527e1578f7f8c4a2f38 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "ext2.h"
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 typedef struct ext2_dir_entry_2 ext2_dirent;
 
index e2a0ea50af1dc6039ad22dc75b62a99ac78002fc..9fd0ec5ba0d0f5e586051e332f15776a9269ea3c 100644 (file)
@@ -133,6 +133,7 @@ extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
 extern void ext2_truncate (struct inode *);
 extern int ext2_setattr (struct dentry *, struct iattr *);
 extern void ext2_set_inode_flags(struct inode *inode);
+extern void ext2_get_inode_flags(struct ext2_inode_info *);
 
 /* ioctl.c */
 extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
index 7806b9e8155bfd8c8b8043faa872e968c2a41369..fc66c93fcb5c931b5df829ddccf85fc53f3887a6 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include "ext2.h"
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>         /* for sync_mapping_buffers() */
 
 
index dd4e14c221e0e07c67c96e2ae06e6c3b755f225e..0079b2cd5314bdebca35c89ab67dc90a637e5697 100644 (file)
@@ -1055,6 +1055,25 @@ void ext2_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_DIRSYNC;
 }
 
+/* Propagate flags from i_flags to EXT2_I(inode)->i_flags */
+void ext2_get_inode_flags(struct ext2_inode_info *ei)
+{
+       unsigned int flags = ei->vfs_inode.i_flags;
+
+       ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL|
+                       EXT2_IMMUTABLE_FL|EXT2_NOATIME_FL|EXT2_DIRSYNC_FL);
+       if (flags & S_SYNC)
+               ei->i_flags |= EXT2_SYNC_FL;
+       if (flags & S_APPEND)
+               ei->i_flags |= EXT2_APPEND_FL;
+       if (flags & S_IMMUTABLE)
+               ei->i_flags |= EXT2_IMMUTABLE_FL;
+       if (flags & S_NOATIME)
+               ei->i_flags |= EXT2_NOATIME_FL;
+       if (flags & S_DIRSYNC)
+               ei->i_flags |= EXT2_DIRSYNC_FL;
+}
+
 void ext2_read_inode (struct inode * inode)
 {
        struct ext2_inode_info *ei = EXT2_I(inode);
@@ -1079,9 +1098,9 @@ void ext2_read_inode (struct inode * inode)
        }
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
        inode->i_size = le32_to_cpu(raw_inode->i_size);
-       inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
-       inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
-       inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+       inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
+       inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
+       inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
        inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
        ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
        /* We now have enough fields to check if the inode was active or not.
@@ -1188,6 +1207,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
        if (ei->i_state & EXT2_STATE_NEW)
                memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size);
 
+       ext2_get_inode_flags(ei);
        raw_inode->i_mode = cpu_to_le16(inode->i_mode);
        if (!(test_opt(sb, NO_UID32))) {
                raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid));
index 4b099d3107128bff377fff8d4774ca97e9d27cb4..e85c48218239b604948bfad7f41889df2dfbba1e 100644 (file)
@@ -27,6 +27,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 
        switch (cmd) {
        case EXT2_IOC_GETFLAGS:
+               ext2_get_inode_flags(ei);
                flags = ei->i_flags & EXT2_FL_USER_VISIBLE;
                return put_user(flags, (int __user *) arg);
        case EXT2_IOC_SETFLAGS: {
index a26612798471ce2d5732889c87b92be3a25faaa8..eaa23d2d5213ae7dcfa70875ebddf40cc7774ce4 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext2_fs.h>
 #include <linux/security.h>
 #include "xattr.h"
index f28a6a499c9650bb6d612947d9b78ff7650151db..83ee149f353db383d657e01a5feb8cd0fac82655 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext2_fs.h>
 #include "xattr.h"
 
index 665adee99b311fbfce6ada8fb94ee163b4969bc4..852869840f240ccc4834ca321c0f6958889c477a 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
 
index a5b150f7e8a2ccb0a46957241ef90e3be0932fe0..a6cb6171c3af7af846769d8e9632ac92854b090e 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/time.h>
 #include <linux/ext3_jbd.h>
 #include <linux/jbd.h>
-#include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
@@ -1768,7 +1767,6 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
        struct inode *inode = mapping->host;
        struct buffer_head *bh;
        int err = 0;
-       void *kaddr;
 
        blocksize = inode->i_sb->s_blocksize;
        length = blocksize - (offset & (blocksize - 1));
@@ -1780,10 +1778,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
         */
        if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
             ext3_should_writeback_data(inode) && PageUptodate(page)) {
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + offset, 0, length);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, offset, length, KM_USER0);
                set_page_dirty(page);
                goto unlock;
        }
@@ -1836,11 +1831,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
                        goto unlock;
        }
 
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr + offset, 0, length);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
-
+       zero_user_page(page, offset, length, KM_USER0);
        BUFFER_TRACE(bh, "zeroed end of block");
 
        err = 0;
@@ -2581,6 +2572,25 @@ void ext3_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_DIRSYNC;
 }
 
+/* Propagate flags from i_flags to EXT3_I(inode)->i_flags */
+void ext3_get_inode_flags(struct ext3_inode_info *ei)
+{
+       unsigned int flags = ei->vfs_inode.i_flags;
+
+       ei->i_flags &= ~(EXT3_SYNC_FL|EXT3_APPEND_FL|
+                       EXT3_IMMUTABLE_FL|EXT3_NOATIME_FL|EXT3_DIRSYNC_FL);
+       if (flags & S_SYNC)
+               ei->i_flags |= EXT3_SYNC_FL;
+       if (flags & S_APPEND)
+               ei->i_flags |= EXT3_APPEND_FL;
+       if (flags & S_IMMUTABLE)
+               ei->i_flags |= EXT3_IMMUTABLE_FL;
+       if (flags & S_NOATIME)
+               ei->i_flags |= EXT3_NOATIME_FL;
+       if (flags & S_DIRSYNC)
+               ei->i_flags |= EXT3_DIRSYNC_FL;
+}
+
 void ext3_read_inode(struct inode * inode)
 {
        struct ext3_iloc iloc;
@@ -2608,9 +2618,9 @@ void ext3_read_inode(struct inode * inode)
        }
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
        inode->i_size = le32_to_cpu(raw_inode->i_size);
-       inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
-       inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
-       inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+       inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
+       inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
+       inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
        inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
 
        ei->i_state = 0;
@@ -2736,6 +2746,7 @@ static int ext3_do_update_inode(handle_t *handle,
        if (ei->i_state & EXT3_STATE_NEW)
                memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
 
+       ext3_get_inode_flags(ei);
        raw_inode->i_mode = cpu_to_le16(inode->i_mode);
        if(!(test_opt(inode->i_sb, NO_UID32))) {
                raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
index 9b8090d94e6c4c1702914478a6ba859c93e2ed22..965006dba6be8d22715dff9f52c2c5038c072c01 100644 (file)
@@ -28,6 +28,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 
        switch (cmd) {
        case EXT3_IOC_GETFLAGS:
+               ext3_get_inode_flags(ei);
                flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
                return put_user(flags, (int __user *) arg);
        case EXT3_IOC_SETFLAGS: {
index 49159f13cc1f900d4b514a265ea3e97cbaf811a4..9bb046df827a7a7a4d694dad36d727a71237a652 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
-#include <linux/smp_lock.h>
 
 #include "namei.h"
 #include "xattr.h"
@@ -969,6 +968,7 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
                                  (block<<EXT3_BLOCK_SIZE_BITS(sb))
                                          +((char *)de - bh->b_data))) {
                                brelse (bh);
+                               *err = ERR_BAD_DX_DIR;
                                goto errout;
                        }
                        *res_dir = de;
@@ -1134,9 +1134,9 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        char *data1 = (*bh)->b_data, *data2;
        unsigned split;
        struct ext3_dir_entry_2 *de = NULL, *de2;
-       int     err;
+       int     err = 0;
 
-       bh2 = ext3_append (handle, dir, &newblock, error);
+       bh2 = ext3_append (handle, dir, &newblock, &err);
        if (!(bh2)) {
                brelse(*bh);
                *bh = NULL;
@@ -1145,14 +1145,9 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 
        BUFFER_TRACE(*bh, "get_write_access");
        err = ext3_journal_get_write_access(handle, *bh);
-       if (err) {
-       journal_error:
-               brelse(*bh);
-               brelse(bh2);
-               *bh = NULL;
-               ext3_std_error(dir->i_sb, err);
-               goto errout;
-       }
+       if (err)
+               goto journal_error;
+
        BUFFER_TRACE(frame->bh, "get_write_access");
        err = ext3_journal_get_write_access(handle, frame->bh);
        if (err)
@@ -1195,8 +1190,16 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                goto journal_error;
        brelse (bh2);
        dxtrace(dx_show_index ("frame", frame->entries));
-errout:
        return de;
+
+journal_error:
+       brelse(*bh);
+       brelse(bh2);
+       *bh = NULL;
+       ext3_std_error(dir->i_sb, err);
+errout:
+       *error = err;
+       return NULL;
 }
 #endif
 
index ecf89904c1134800e609486cee2c74ff489e1f90..2c97e09c6c6b2a3048898f69d76cb0522061f389 100644 (file)
@@ -11,7 +11,6 @@
 
 #define EXT3FS_DEBUG
 
-#include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 
 #include <linux/errno.h>
index b9c40c15647bb709e0991c2fbf25663bd4a0fa1f..821efaf2b94e55b7556903d2835493c5ec5a9252 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/security.h>
index 86d91f1186dce11da40650e0c716cfc2214cbb6d..0327497a55ce0a58baa9ce2d855cd7ecad762625 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
 #include "xattr.h"
index a85a0a17c4fd4bc8d5981f9da79d48289876e1ad..1abd8f92c4402a86a992e10e8e3261fd635eea10 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
 #include "xattr.h"
index da80368b66f0f7ca4310b03ccb59b359ff80118e..e8ad06e283187fc0ca11985994205024d77a25d9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/jbd2.h>
 #include <linux/ext4_fs.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
 
index 7916b50f9a13ffe0122689b69b4865eec064de4a..a0f0c04e79b2bb47ca670fe7edd9875afb937d97 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/time.h>
 #include <linux/ext4_jbd2.h>
 #include <linux/jbd.h>
-#include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
index 810b6d6474bf787d20049c417474010e90aee7df..b34182b6ee4d1ea9cba530ea5dac87a787a8b7c1 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/time.h>
 #include <linux/ext4_jbd2.h>
 #include <linux/jbd2.h>
-#include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
@@ -2611,9 +2610,9 @@ void ext4_read_inode(struct inode * inode)
        }
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
        inode->i_size = le32_to_cpu(raw_inode->i_size);
-       inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
-       inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
-       inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+       inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
+       inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
+       inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
        inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
 
        ei->i_state = 0;
index e7e1d79a7d75496c3f0bff48eb6680a6ff2703e9..4ec57be5baf5df659a4f9c2d9330c8bfbe10c796 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
-#include <linux/smp_lock.h>
 
 #include "namei.h"
 #include "xattr.h"
@@ -967,6 +966,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
                                  (block<<EXT4_BLOCK_SIZE_BITS(sb))
                                          +((char *)de - bh->b_data))) {
                                brelse (bh);
+                               *err = ERR_BAD_DX_DIR;
                                goto errout;
                        }
                        *res_dir = de;
@@ -1132,9 +1132,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        char *data1 = (*bh)->b_data, *data2;
        unsigned split;
        struct ext4_dir_entry_2 *de = NULL, *de2;
-       int     err;
+       int     err = 0;
 
-       bh2 = ext4_append (handle, dir, &newblock, error);
+       bh2 = ext4_append (handle, dir, &newblock, &err);
        if (!(bh2)) {
                brelse(*bh);
                *bh = NULL;
@@ -1143,14 +1143,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 
        BUFFER_TRACE(*bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, *bh);
-       if (err) {
-       journal_error:
-               brelse(*bh);
-               brelse(bh2);
-               *bh = NULL;
-               ext4_std_error(dir->i_sb, err);
-               goto errout;
-       }
+       if (err)
+               goto journal_error;
+
        BUFFER_TRACE(frame->bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, frame->bh);
        if (err)
@@ -1193,8 +1188,16 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                goto journal_error;
        brelse (bh2);
        dxtrace(dx_show_index ("frame", frame->entries));
-errout:
        return de;
+
+journal_error:
+       brelse(*bh);
+       brelse(bh2);
+       *bh = NULL;
+       ext4_std_error(dir->i_sb, err);
+errout:
+       *error = err;
+       return NULL;
 }
 #endif
 
index ea99f6c97f565fe0e2911c8a082265380ad9551c..aa11d7dbe9700106725f79c682aebda39a97bc9f 100644 (file)
@@ -11,7 +11,6 @@
 
 #define EXT4FS_DEBUG
 
-#include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 
 #include <linux/errno.h>
index b6a6861951f9d8e5be9a0c60b1ef72a30b74ef4b..f17eaf2321b9da564b303b5abfdccc0e2ff11018 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 #include <linux/ext4_fs.h>
 #include <linux/security.h>
index b76f2dbc82daf64f80b2457e76addcad71c1621f..e0f05acdafece0e0826c2985fc0a59c556fa5159 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 #include <linux/ext4_fs.h>
 #include "xattr.h"
index c53cded0761ac3f01284affae0c29eed7270ad11..7ed3d8ebf09686d2315e3a1ebdc92ccff5ada1ad 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 #include <linux/ext4_fs.h>
 #include "xattr.h"
index c16af246d245ddd45daf90a59ef0612fe5904dac..ccf161dffb63de4f9798f4b04dd61b176f40bcd3 100644 (file)
@@ -422,7 +422,7 @@ EODir:
 EXPORT_SYMBOL_GPL(fat_search_long);
 
 struct fat_ioctl_filldir_callback {
-       struct dirent __user *dirent;
+       void __user *dirent;
        int result;
        /* for dir ioctl */
        const char *longname;
@@ -647,62 +647,85 @@ static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
        return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
 }
 
-static int fat_ioctl_filldir(void *__buf, const char *name, int name_len,
-                            loff_t offset, u64 ino, unsigned int d_type)
+#define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type)                         \
+static int func(void *__buf, const char *name, int name_len,              \
+                            loff_t offset, u64 ino, unsigned int d_type)  \
+{                                                                         \
+       struct fat_ioctl_filldir_callback *buf = __buf;                    \
+       struct dirent_type __user *d1 = buf->dirent;                       \
+       struct dirent_type __user *d2 = d1 + 1;                            \
+                                                                          \
+       if (buf->result)                                                   \
+               return -EINVAL;                                            \
+       buf->result++;                                                     \
+                                                                          \
+       if (name != NULL) {                                                \
+               /* dirent has only short name */                           \
+               if (name_len >= sizeof(d1->d_name))                        \
+                       name_len = sizeof(d1->d_name) - 1;                 \
+                                                                          \
+               if (put_user(0, d2->d_name)                     ||         \
+                   put_user(0, &d2->d_reclen)                  ||         \
+                   copy_to_user(d1->d_name, name, name_len)    ||         \
+                   put_user(0, d1->d_name + name_len)          ||         \
+                   put_user(name_len, &d1->d_reclen))                     \
+                       goto efault;                                       \
+       } else {                                                           \
+               /* dirent has short and long name */                       \
+               const char *longname = buf->longname;                      \
+               int long_len = buf->long_len;                              \
+               const char *shortname = buf->shortname;                    \
+               int short_len = buf->short_len;                            \
+                                                                          \
+               if (long_len >= sizeof(d1->d_name))                        \
+                       long_len = sizeof(d1->d_name) - 1;                 \
+               if (short_len >= sizeof(d1->d_name))                       \
+                       short_len = sizeof(d1->d_name) - 1;                \
+                                                                          \
+               if (copy_to_user(d2->d_name, longname, long_len)        || \
+                   put_user(0, d2->d_name + long_len)                  || \
+                   put_user(long_len, &d2->d_reclen)                   || \
+                   put_user(ino, &d2->d_ino)                           || \
+                   put_user(offset, &d2->d_off)                        || \
+                   copy_to_user(d1->d_name, shortname, short_len)      || \
+                   put_user(0, d1->d_name + short_len)                 || \
+                   put_user(short_len, &d1->d_reclen))                    \
+                       goto efault;                                       \
+       }                                                                  \
+       return 0;                                                          \
+efault:                                                                           \
+       buf->result = -EFAULT;                                             \
+       return -EFAULT;                                                    \
+}
+
+FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, dirent)
+
+static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
+                            void __user *dirent, filldir_t filldir,
+                            int short_only, int both)
 {
-       struct fat_ioctl_filldir_callback *buf = __buf;
-       struct dirent __user *d1 = buf->dirent;
-       struct dirent __user *d2 = d1 + 1;
-
-       if (buf->result)
-               return -EINVAL;
-       buf->result++;
-
-       if (name != NULL) {
-               /* dirent has only short name */
-               if (name_len >= sizeof(d1->d_name))
-                       name_len = sizeof(d1->d_name) - 1;
-
-               if (put_user(0, d2->d_name)                     ||
-                   put_user(0, &d2->d_reclen)                  ||
-                   copy_to_user(d1->d_name, name, name_len)    ||
-                   put_user(0, d1->d_name + name_len)          ||
-                   put_user(name_len, &d1->d_reclen))
-                       goto efault;
-       } else {
-               /* dirent has short and long name */
-               const char *longname = buf->longname;
-               int long_len = buf->long_len;
-               const char *shortname = buf->shortname;
-               int short_len = buf->short_len;
-
-               if (long_len >= sizeof(d1->d_name))
-                       long_len = sizeof(d1->d_name) - 1;
-               if (short_len >= sizeof(d1->d_name))
-                       short_len = sizeof(d1->d_name) - 1;
-
-               if (copy_to_user(d2->d_name, longname, long_len)        ||
-                   put_user(0, d2->d_name + long_len)                  ||
-                   put_user(long_len, &d2->d_reclen)                   ||
-                   put_user(ino, &d2->d_ino)                           ||
-                   put_user(offset, &d2->d_off)                        ||
-                   copy_to_user(d1->d_name, shortname, short_len)      ||
-                   put_user(0, d1->d_name + short_len)                 ||
-                   put_user(short_len, &d1->d_reclen))
-                       goto efault;
+       struct fat_ioctl_filldir_callback buf;
+       int ret;
+
+       buf.dirent = dirent;
+       buf.result = 0;
+       mutex_lock(&inode->i_mutex);
+       ret = -ENOENT;
+       if (!IS_DEADDIR(inode)) {
+               ret = __fat_readdir(inode, filp, &buf, filldir,
+                                   short_only, both);
        }
-       return 0;
-efault:
-       buf->result = -EFAULT;
-       return -EFAULT;
+       mutex_unlock(&inode->i_mutex);
+       if (ret >= 0)
+               ret = buf.result;
+       return ret;
 }
 
-static int fat_dir_ioctl(struct inode * inode, struct file * filp,
-                 unsigned int cmd, unsigned long arg)
+static int fat_dir_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg)
 {
-       struct fat_ioctl_filldir_callback buf;
-       struct dirent __user *d1;
-       int ret, short_only, both;
+       struct dirent __user *d1 = (struct dirent __user *)arg;
+       int short_only, both;
 
        switch (cmd) {
        case VFAT_IOCTL_READDIR_SHORT:
@@ -717,7 +740,6 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
                return fat_generic_ioctl(inode, filp, cmd, arg);
        }
 
-       d1 = (struct dirent __user *)arg;
        if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
                return -EFAULT;
        /*
@@ -728,69 +750,48 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
        if (put_user(0, &d1->d_reclen))
                return -EFAULT;
 
-       buf.dirent = d1;
-       buf.result = 0;
-       mutex_lock(&inode->i_mutex);
-       ret = -ENOENT;
-       if (!IS_DEADDIR(inode)) {
-               ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir,
-                                   short_only, both);
-       }
-       mutex_unlock(&inode->i_mutex);
-       if (ret >= 0)
-               ret = buf.result;
-       return ret;
+       return fat_ioctl_readdir(inode, filp, d1, fat_ioctl_filldir,
+                                short_only, both);
 }
 
 #ifdef CONFIG_COMPAT
 #define        VFAT_IOCTL_READDIR_BOTH32       _IOR('r', 1, struct compat_dirent[2])
 #define        VFAT_IOCTL_READDIR_SHORT32      _IOR('r', 2, struct compat_dirent[2])
 
-static long fat_compat_put_dirent32(struct dirent *d,
-                                   struct compat_dirent __user *d32)
-{
-        if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
-                return -EFAULT;
-
-        __put_user(d->d_ino, &d32->d_ino);
-        __put_user(d->d_off, &d32->d_off);
-        __put_user(d->d_reclen, &d32->d_reclen);
-        if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
-               return -EFAULT;
+FAT_IOCTL_FILLDIR_FUNC(fat_compat_ioctl_filldir, compat_dirent)
 
-        return 0;
-}
-
-static long fat_compat_dir_ioctl(struct file *file, unsigned cmd,
+static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
                                 unsigned long arg)
 {
-       struct compat_dirent __user *p = compat_ptr(arg);
-       int ret;
-       mm_segment_t oldfs = get_fs();
-       struct dirent d[2];
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       struct compat_dirent __user *d1 = compat_ptr(arg);
+       int short_only, both;
 
        switch (cmd) {
-       case VFAT_IOCTL_READDIR_BOTH32:
-               cmd = VFAT_IOCTL_READDIR_BOTH;
-               break;
        case VFAT_IOCTL_READDIR_SHORT32:
-               cmd = VFAT_IOCTL_READDIR_SHORT;
+               short_only = 1;
+               both = 0;
+               break;
+       case VFAT_IOCTL_READDIR_BOTH32:
+               short_only = 0;
+               both = 1;
                break;
        default:
                return -ENOIOCTLCMD;
        }
 
-       set_fs(KERNEL_DS);
-       lock_kernel();
-       ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file,
-                           cmd, (unsigned long) &d);
-       unlock_kernel();
-       set_fs(oldfs);
-       if (ret >= 0) {
-               ret |= fat_compat_put_dirent32(&d[0], p);
-               ret |= fat_compat_put_dirent32(&d[1], p + 1);
-       }
-       return ret;
+       if (!access_ok(VERIFY_WRITE, d1, sizeof(struct compat_dirent[2])))
+               return -EFAULT;
+       /*
+        * Yes, we don't need this put_user() absolutely. However old
+        * code didn't return the right value. So, app use this value,
+        * in order to check whether it is EOF.
+        */
+       if (put_user(0, &d1->d_reclen))
+               return -EFAULT;
+
+       return fat_ioctl_readdir(inode, filp, d1, fat_compat_ioctl_filldir,
+                                short_only, both);
 }
 #endif /* CONFIG_COMPAT */
 
index 65cb54bde4814ea2296bb1617feb10a05af909d2..2c55e8dce7932cfaa2b8b7b026633267a6c82b0f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/parser.h>
 #include <linux/uio.h>
 #include <linux/writeback.h>
+#include <linux/log2.h>
 #include <asm/unaligned.h>
 
 #ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -824,6 +825,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
        }
        if (opts->name_check != 'n')
                seq_printf(m, ",check=%c", opts->name_check);
+       if (opts->usefree)
+               seq_puts(m, ",usefree");
        if (opts->quiet)
                seq_puts(m, ",quiet");
        if (opts->showexec)
@@ -849,7 +852,7 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
 
 enum {
        Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
-       Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase,
+       Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase,
        Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,
        Opt_dots, Opt_nodots,
        Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
@@ -871,6 +874,7 @@ static match_table_t fat_tokens = {
        {Opt_dmask, "dmask=%o"},
        {Opt_fmask, "fmask=%o"},
        {Opt_codepage, "codepage=%u"},
+       {Opt_usefree, "usefree"},
        {Opt_nocase, "nocase"},
        {Opt_quiet, "quiet"},
        {Opt_showexec, "showexec"},
@@ -950,7 +954,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
        opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK =  0;
        opts->utf8 = opts->unicode_xlate = 0;
        opts->numtail = 1;
-       opts->nocase = 0;
+       opts->usefree = opts->nocase = 0;
        *debug = 0;
 
        if (!options)
@@ -978,6 +982,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_check_n:
                        opts->name_check = 'n';
                        break;
+               case Opt_usefree:
+                       opts->usefree = 1;
+                       break;
                case Opt_nocase:
                        if (!is_vfat)
                                opts->nocase = 1;
@@ -1217,8 +1224,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        }
        logical_sector_size =
                le16_to_cpu(get_unaligned((__le16 *)&b->sector_size));
-       if (!logical_sector_size
-           || (logical_sector_size & (logical_sector_size - 1))
+       if (!is_power_of_2(logical_sector_size)
            || (logical_sector_size < 512)
            || (PAGE_CACHE_SIZE < logical_sector_size)) {
                if (!silent)
@@ -1228,8 +1234,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                goto out_invalid;
        }
        sbi->sec_per_clus = b->sec_per_clus;
-       if (!sbi->sec_per_clus
-           || (sbi->sec_per_clus & (sbi->sec_per_clus - 1))) {
+       if (!is_power_of_2(sbi->sec_per_clus)) {
                if (!silent)
                        printk(KERN_ERR "FAT: bogus sectors per cluster %u\n",
                               sbi->sec_per_clus);
@@ -1305,7 +1310,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                               le32_to_cpu(fsinfo->signature2),
                               sbi->fsinfo_sector);
                } else {
-                       sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters);
+                       if (sbi->options.usefree)
+                               sbi->free_clusters =
+                                       le32_to_cpu(fsinfo->free_clusters);
                        sbi->prev_free = le32_to_cpu(fsinfo->next_cluster);
                }
 
index 49035b174b48af51a20b319d133ead21736eefc0..6e7df72567823747dd6005825aba23a42fb13bf5 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -11,7 +11,6 @@
 
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/pipe_fs_i.h>
 
index 4c17a18d8c10c4889295d52250afb800aba9190b..d17fd691b8325c8dab7c4ab086bfb1900687b1e0 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/file.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/eventpoll.h>
index 7a4f61aa05f8a63697be13231d69316ef5c365a9..f37f87262837aaf6e47526d4895a000f1f9024c2 100644 (file)
@@ -41,11 +41,12 @@ void put_filesystem(struct file_system_type *fs)
        module_put(fs->owner);
 }
 
-static struct file_system_type **find_filesystem(const char *name)
+static struct file_system_type **find_filesystem(const char *name, unsigned len)
 {
        struct file_system_type **p;
        for (p=&file_systems; *p; p=&(*p)->next)
-               if (strcmp((*p)->name,name) == 0)
+               if (strlen((*p)->name) == len &&
+                   strncmp((*p)->name, name, len) == 0)
                        break;
        return p;
 }
@@ -68,11 +69,12 @@ int register_filesystem(struct file_system_type * fs)
        int res = 0;
        struct file_system_type ** p;
 
+       BUG_ON(strchr(fs->name, '.'));
        if (fs->next)
                return -EBUSY;
        INIT_LIST_HEAD(&fs->fs_supers);
        write_lock(&file_systems_lock);
-       p = find_filesystem(fs->name);
+       p = find_filesystem(fs->name, strlen(fs->name));
        if (*p)
                res = -EBUSY;
        else
@@ -215,19 +217,26 @@ int get_filesystem_list(char * buf)
 struct file_system_type *get_fs_type(const char *name)
 {
        struct file_system_type *fs;
+       const char *dot = strchr(name, '.');
+       unsigned len = dot ? dot - name : strlen(name);
 
        read_lock(&file_systems_lock);
-       fs = *(find_filesystem(name));
+       fs = *(find_filesystem(name, len));
        if (fs && !try_module_get(fs->owner))
                fs = NULL;
        read_unlock(&file_systems_lock);
-       if (!fs && (request_module("%s", name) == 0)) {
+       if (!fs && (request_module("%.*s", len, name) == 0)) {
                read_lock(&file_systems_lock);
-               fs = *(find_filesystem(name));
+               fs = *(find_filesystem(name, len));
                if (fs && !try_module_get(fs->owner))
                        fs = NULL;
                read_unlock(&file_systems_lock);
        }
+
+       if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
+               put_filesystem(fs);
+               fs = NULL;
+       }
        return fs;
 }
 
index 2d71128bd8d6b3503098b25039e30e183cd23ab5..f86fd3cacd5ab77f6741ce9fcb1dc2d8ee746c01 100644 (file)
@@ -137,7 +137,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 
                bp = sb_bread(ip->i_sb,
                                indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
-               if (!buffer_mapped(bp))
+               if (!bp || !buffer_mapped(bp))
                        return 0;
 
                typ = ((struct vxfs_typed *)bp->b_data) +
index 098a915fd9a1da65aeb0902350bee828fab46996..d1f7c5b5b3c350d0656a4f33b7d841b4f450e1b3 100644 (file)
@@ -99,7 +99,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
        offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
        bp = sb_bread(sbp, block);
 
-       if (buffer_mapped(bp)) {
+       if (bp && buffer_mapped(bp)) {
                struct vxfs_inode_info  *vip;
                struct vxfs_dinode      *dip;
 
index d8003be56e0593e392d51c55539c86939ab5f4c9..1397018ff47665e28bead1fb5a75592703c762c9 100644 (file)
@@ -636,6 +636,7 @@ static int fuse_get_sb(struct file_system_type *fs_type,
 static struct file_system_type fuse_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuse",
+       .fs_flags       = FS_HAS_SUBTYPE,
        .get_sb         = fuse_get_sb,
        .kill_sb        = kill_anon_super,
 };
@@ -652,6 +653,7 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type,
 static struct file_system_type fuseblk_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuseblk",
+       .fs_flags       = FS_HAS_SUBTYPE,
        .get_sb         = fuse_get_sb_blk,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
index 39c8ae23bd9c04a8b47b0cec2a371a597b5a2450..7b82657a991096bea7291522f2bd357a5213d24e 100644 (file)
@@ -163,10 +163,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
                if (ip) {
                        struct address_space *mapping = ip->i_inode.i_mapping;
                        int error = filemap_fdatawait(mapping);
-                       if (error == -ENOSPC)
-                               set_bit(AS_ENOSPC, &mapping->flags);
-                       else if (error)
-                               set_bit(AS_EIO, &mapping->flags);
+                       mapping_set_error(mapping, error);
                }
                clear_bit(GLF_DIRTY, &gl->gl_flags);
                gfs2_ail_empty_gl(gl);
index 5cc1dfa7944a2ee3ff9f14c4f6447768063dfc22..0d149c8c493a36ce1b9bb31593c5e9cfdb75465e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/lm_interface.h>
 
 struct nolock_lockspace {
index c6bac6b694204b010cad1bd18460f5fa38b522a5..a6fdc52f554a43d5d195a8282319028d63d54873 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
index 329c4dcdecdbe7c36feec90549c058834ec44427..064df8804582b1f99b9003a78fb2ff39b2a2c254 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/uio.h>
 #include <linux/blkdev.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/ext2_fs.h>
index 5fd0ed71f92331c3553ef9d563c0543e9fc9e9f6..8a3a650abc87a9ed4520318a811fb76619933a7e 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/pagemap.h>
+#include <linux/log2.h>
 
 #include "btree.h"
 
@@ -76,7 +77,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        tree->depth = be16_to_cpu(head->depth);
 
        size = tree->node_size;
-       if (!size || size & (size - 1))
+       if (!is_power_of_2(size))
                goto fail_page;
        if (!tree->node_count)
                goto fail_page;
index a9b9e872e29a6296ecd4d327bd8f2653beeb7a3e..90ebab753d306d8da95227644ab24480ef8649ca 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/log2.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
@@ -69,7 +70,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        }
 
        size = tree->node_size;
-       if (!size || size & (size - 1))
+       if (!is_power_of_2(size))
                goto fail_page;
        if (!tree->node_count)
                goto fail_page;
index 70543b17e4c733315d73089537e3a85b8b7cf96a..06e5930515fe749f52d5e74164cb4db066ae998f 100644 (file)
@@ -55,7 +55,7 @@ extern int stat_file(const char *path, unsigned long long *inode_out,
                     int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
                     unsigned long long *size_out, struct timespec *atime_out,
                     struct timespec *mtime_out, struct timespec *ctime_out,
-                    int *blksize_out, unsigned long long *blocks_out);
+                    int *blksize_out, unsigned long long *blocks_out, int fd);
 extern int access_file(char *path, int r, int w, int x);
 extern int open_file(char *path, int r, int w, int append);
 extern int file_type(const char *path, int *maj, int *min);
@@ -71,7 +71,7 @@ extern int lseek_file(int fd, long long offset, int whence);
 extern int fsync_file(int fd, int datasync);
 extern int file_create(char *name, int ur, int uw, int ux, int gr,
                       int gw, int gx, int or, int ow, int ox);
-extern int set_attr(const char *file, struct hostfs_iattr *attrs);
+extern int set_attr(const char *file, struct hostfs_iattr *attrs, int fd);
 extern int make_symlink(const char *from, const char *to);
 extern int unlink_file(const char *file);
 extern int do_mkdir(const char *file, int mode);
@@ -87,14 +87,3 @@ extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
                     long *spare_out);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index fd301a91012243e25fe2ab9a77db3a9bda9b6acd..8286491dbf31dbccca606b241ae755d5cd77cee8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  *
  * Ported the filesystem routines to 2.5.
@@ -31,14 +31,14 @@ struct hostfs_inode_info {
 
 static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
 {
-       return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
+       return list_entry(inode, struct hostfs_inode_info, vfs_inode);
 }
 
 #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
 
 int hostfs_d_delete(struct dentry *dentry)
 {
-       return(1);
+       return 1;
 }
 
 struct dentry_operations hostfs_dentry_ops = {
@@ -79,7 +79,7 @@ static int __init hostfs_args(char *options, int *add)
                }
                options = ptr;
        }
-       return(0);
+       return 0;
 }
 
 __uml_setup("hostfs=", hostfs_args,
@@ -110,7 +110,8 @@ static char *dentry_name(struct dentry *dentry, int extra)
        root = HOSTFS_I(parent->d_inode)->host_filename;
        len += strlen(root);
        name = kmalloc(len + extra + 1, GFP_KERNEL);
-       if(name == NULL) return(NULL);
+       if(name == NULL)
+               return NULL;
 
        name[len] = '\0';
        parent = dentry;
@@ -122,7 +123,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
                parent = parent->d_parent;
        }
        strncpy(name, root, strlen(root));
-       return(name);
+       return name;
 }
 
 static char *inode_name(struct inode *ino, int extra)
@@ -130,7 +131,7 @@ static char *inode_name(struct inode *ino, int extra)
        struct dentry *dentry;
 
        dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
-       return(dentry_name(dentry, extra));
+       return dentry_name(dentry, extra);
 }
 
 static int read_name(struct inode *ino, char *name)
@@ -147,16 +148,16 @@ static int read_name(struct inode *ino, char *name)
 
        err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
                        &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
-                       &ino->i_ctime, &i_blksize, &i_blocks);
+                       &ino->i_ctime, &i_blksize, &i_blocks, -1);
        if(err)
-               return(err);
+               return err;
 
        ino->i_ino = i_ino;
        ino->i_mode = i_mode;
        ino->i_nlink = i_nlink;
        ino->i_size = i_size;
        ino->i_blocks = i_blocks;
-       return(0);
+       return 0;
 }
 
 static char *follow_link(char *link)
@@ -181,11 +182,11 @@ static char *follow_link(char *link)
                goto out_free;
 
        if(*name == '/')
-               return(name);
+               return name;
 
        end = strrchr(link, '/');
        if(end == NULL)
-               return(name);
+               return name;
 
        *(end + 1) = '\0';
        len = strlen(link) + strlen(name) + 1;
@@ -199,12 +200,12 @@ static char *follow_link(char *link)
        sprintf(resolved, "%s%s", link, name);
        kfree(name);
        kfree(link);
-       return(resolved);
+       return resolved;
 
  out_free:
        kfree(name);
  out:
-       return(ERR_PTR(n));
+       return ERR_PTR(n);
 }
 
 static int read_inode(struct inode *ino)
@@ -234,7 +235,7 @@ static int read_inode(struct inode *ino)
        err = read_name(ino, name);
        kfree(name);
  out:
-       return(err);
+       return err;
 }
 
 int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
@@ -254,14 +255,15 @@ int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
                        &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
                        &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
                        &sf->f_namelen, sf->f_spare);
-       if(err) return(err);
+       if(err)
+               return err;
        sf->f_blocks = f_blocks;
        sf->f_bfree = f_bfree;
        sf->f_bavail = f_bavail;
        sf->f_files = f_files;
        sf->f_ffree = f_ffree;
        sf->f_type = HOSTFS_SUPER_MAGIC;
-       return(0);
+       return 0;
 }
 
 static struct inode *hostfs_alloc_inode(struct super_block *sb)
@@ -270,13 +272,13 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
 
        hi = kmalloc(sizeof(*hi), GFP_KERNEL);
        if(hi == NULL)
-               return(NULL);
+               return NULL;
 
        *hi = ((struct hostfs_inode_info) { .host_filename      = NULL,
                                            .fd                 = -1,
                                            .mode               = 0 });
        inode_init_once(&hi->vfs_inode);
-       return(&hi->vfs_inode);
+       return &hi->vfs_inode;
 }
 
 static void hostfs_delete_inode(struct inode *inode)
@@ -325,10 +327,12 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
        int error, len;
 
        name = dentry_name(file->f_path.dentry, 0);
-       if(name == NULL) return(-ENOMEM);
+       if(name == NULL)
+               return -ENOMEM;
        dir = open_dir(name, &error);
        kfree(name);
-       if(dir == NULL) return(-error);
+       if(dir == NULL)
+               return -error;
        next = file->f_pos;
        while((name = read_dir(dir, &next, &ino, &len)) != NULL){
                error = (*filldir)(ent, name, len, file->f_pos,
@@ -337,7 +341,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
                file->f_pos = next;
        }
        close_dir(dir);
-       return(0);
+       return 0;
 }
 
 int hostfs_file_open(struct inode *ino, struct file *file)
@@ -347,7 +351,7 @@ int hostfs_file_open(struct inode *ino, struct file *file)
 
        mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
        if((mode & HOSTFS_I(ino)->mode) == mode)
-               return(0);
+               return 0;
 
        /* The file may already have been opened, but with the wrong access,
         * so this resets things and reopens the file with the new access.
@@ -367,14 +371,15 @@ int hostfs_file_open(struct inode *ino, struct file *file)
 
        name = dentry_name(file->f_path.dentry, 0);
        if(name == NULL)
-               return(-ENOMEM);
+               return -ENOMEM;
 
        fd = open_file(name, r, w, append);
        kfree(name);
-       if(fd < 0) return(fd);
+       if(fd < 0)
+               return fd;
        FILE_HOSTFS_I(file)->fd = fd;
 
-       return(0);
+       return 0;
 }
 
 int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
@@ -458,7 +463,7 @@ int hostfs_readpage(struct file *file, struct page *page)
  out:
        kunmap(page);
        unlock_page(page);
-       return(err);
+       return err;
 }
 
 int hostfs_prepare_write(struct file *file, struct page *page,
@@ -485,7 +490,7 @@ int hostfs_prepare_write(struct file *file, struct page *page,
        err = 0;
  out:
        kunmap(page);
-       return(err);
+       return err;
 }
 
 int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
@@ -511,7 +516,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
                inode->i_size = start;
 
        kunmap(page);
-       return(err);
+       return err;
 }
 
 static const struct address_space_operations hostfs_aops = {
@@ -569,7 +574,7 @@ static int init_inode(struct inode *inode, struct dentry *dentry)
                break;
        }
  out:
-       return(err);
+       return err;
 }
 
 int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
@@ -607,16 +612,16 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
        HOSTFS_I(inode)->fd = fd;
        HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
        d_instantiate(dentry, inode);
-       return(0);
+       return 0;
 
  out_put:
        iput(inode);
  out:
-       return(error);
+       return error;
 }
 
 struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
-                            struct nameidata *nd)
+                            struct nameidata *nd)
 {
        struct inode *inode;
        char *name;
@@ -647,44 +652,45 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
 
        d_add(dentry, inode);
        dentry->d_op = &hostfs_dentry_ops;
-       return(NULL);
+       return NULL;
 
  out_put:
        iput(inode);
  out:
-       return(ERR_PTR(err));
+       return ERR_PTR(err);
 }
 
 static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
 {
-        char *file;
+       char *file;
        int len;
 
        file = inode_name(ino, dentry->d_name.len + 1);
-       if(file == NULL) return(NULL);
-        strcat(file, "/");
+       if(file == NULL)
+               return NULL;
+       strcat(file, "/");
        len = strlen(file);
-        strncat(file, dentry->d_name.name, dentry->d_name.len);
+       strncat(file, dentry->d_name.name, dentry->d_name.len);
        file[len + dentry->d_name.len] = '\0';
-        return(file);
+       return file;
 }
 
 int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
 {
-        char *from_name, *to_name;
-        int err;
+       char *from_name, *to_name;
+       int err;
 
-        if((from_name = inode_dentry_name(ino, from)) == NULL)
-                return(-ENOMEM);
-        to_name = dentry_name(to, 0);
+       if((from_name = inode_dentry_name(ino, from)) == NULL)
+               return -ENOMEM;
+       to_name = dentry_name(to, 0);
        if(to_name == NULL){
                kfree(from_name);
-               return(-ENOMEM);
+               return -ENOMEM;
        }
-        err = link_file(to_name, from_name);
-        kfree(from_name);
-        kfree(to_name);
-        return(err);
+       err = link_file(to_name, from_name);
+       kfree(from_name);
+       kfree(to_name);
+       return err;
 }
 
 int hostfs_unlink(struct inode *ino, struct dentry *dentry)
@@ -692,13 +698,14 @@ int hostfs_unlink(struct inode *ino, struct dentry *dentry)
        char *file;
        int err;
 
-       if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+       if((file = inode_dentry_name(ino, dentry)) == NULL)
+               return -ENOMEM;
        if(append)
-               return(-EPERM);
+               return -EPERM;
 
        err = unlink_file(file);
        kfree(file);
-       return(err);
+       return err;
 }
 
 int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
@@ -706,10 +713,11 @@ int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
        char *file;
        int err;
 
-       if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+       if((file = inode_dentry_name(ino, dentry)) == NULL)
+               return -ENOMEM;
        err = make_symlink(file, to);
        kfree(file);
-       return(err);
+       return err;
 }
 
 int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
@@ -717,10 +725,11 @@ int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
        char *file;
        int err;
 
-       if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+       if((file = inode_dentry_name(ino, dentry)) == NULL)
+               return -ENOMEM;
        err = do_mkdir(file, mode);
        kfree(file);
-       return(err);
+       return err;
 }
 
 int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
@@ -728,10 +737,11 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
        char *file;
        int err;
 
-       if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+       if((file = inode_dentry_name(ino, dentry)) == NULL)
+               return -ENOMEM;
        err = do_rmdir(file);
        kfree(file);
-       return(err);
+       return err;
 }
 
 int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
@@ -764,14 +774,14 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
                goto out_put;
 
        d_instantiate(dentry, inode);
-       return(0);
+       return 0;
 
  out_free:
        kfree(name);
  out_put:
        iput(inode);
  out:
-       return(err);
+       return err;
 }
 
 int hostfs_rename(struct inode *from_ino, struct dentry *from,
@@ -781,15 +791,15 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
        int err;
 
        if((from_name = inode_dentry_name(from_ino, from)) == NULL)
-               return(-ENOMEM);
+               return -ENOMEM;
        if((to_name = inode_dentry_name(to_ino, to)) == NULL){
                kfree(from_name);
-               return(-ENOMEM);
+               return -ENOMEM;
        }
        err = rename_file(from_name, to_name);
        kfree(from_name);
        kfree(to_name);
-       return(err);
+       return err;
 }
 
 int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
@@ -801,7 +811,8 @@ int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
        if (desired & MAY_WRITE) w = 1;
        if (desired & MAY_EXEC) x = 1;
        name = inode_name(ino, 0);
-       if (name == NULL) return(-ENOMEM);
+       if (name == NULL)
+               return -ENOMEM;
 
        if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
                        S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
@@ -820,6 +831,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
        char *name;
        int err;
 
+       int fd = HOSTFS_I(dentry->d_inode)->fd;
+
        err = inode_change_ok(dentry->d_inode, attr);
        if (err)
                return err;
@@ -863,20 +876,21 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
                attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
        }
        name = dentry_name(dentry, 0);
-       if(name == NULL) return(-ENOMEM);
-       err = set_attr(name, &attrs);
+       if(name == NULL)
+               return -ENOMEM;
+       err = set_attr(name, &attrs, fd);
        kfree(name);
        if(err)
-               return(err);
+               return err;
 
-       return(inode_setattr(dentry->d_inode, attr));
+       return inode_setattr(dentry->d_inode, attr);
 }
 
 int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
           struct kstat *stat)
 {
        generic_fillattr(dentry->d_inode, stat);
-       return(0);
+       return 0;
 }
 
 static const struct inode_operations hostfs_iops = {
@@ -915,7 +929,8 @@ int hostfs_link_readpage(struct file *file, struct page *page)
 
        buffer = kmap(page);
        name = inode_name(page->mapping->host, 0);
-       if(name == NULL) return(-ENOMEM);
+       if(name == NULL)
+               return -ENOMEM;
        err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
        kfree(name);
        if(err == PAGE_CACHE_SIZE)
@@ -928,7 +943,7 @@ int hostfs_link_readpage(struct file *file, struct page *page)
        }
        kunmap(page);
        unlock_page(page);
-       return(err);
+       return err;
 }
 
 static const struct address_space_operations hostfs_link_aops = {
@@ -978,20 +993,20 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
 
        err = read_inode(root_inode);
        if(err){
-                /* No iput in this case because the dput does that for us */
-                dput(sb->s_root);
-                sb->s_root = NULL;
+               /* No iput in this case because the dput does that for us */
+               dput(sb->s_root);
+               sb->s_root = NULL;
                goto out;
-        }
+       }
 
-       return(0);
+       return 0;
 
- out_put:
-        iput(root_inode);
- out_free:
+out_put:
+       iput(root_inode);
+out_free:
        kfree(host_root_path);
- out:
-       return(err);
+out:
+       return err;
 }
 
 static int hostfs_read_sb(struct file_system_type *type,
@@ -1011,7 +1026,7 @@ static struct file_system_type hostfs_type = {
 
 static int __init init_hostfs(void)
 {
-       return(register_filesystem(&hostfs_type));
+       return register_filesystem(&hostfs_type);
 }
 
 static void __exit exit_hostfs(void)
@@ -1022,14 +1037,3 @@ static void __exit exit_hostfs(void)
 module_init(init_hostfs)
 module_exit(exit_hostfs)
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 1ed5ea389f15bcda52f32171bb725fa9f0ce7c39..5625e2481dd31b56f95a8532119501519331b739 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
@@ -21,12 +21,16 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
              int *nlink_out, int *uid_out, int *gid_out,
              unsigned long long *size_out, struct timespec *atime_out,
              struct timespec *mtime_out, struct timespec *ctime_out,
-             int *blksize_out, unsigned long long *blocks_out)
+             int *blksize_out, unsigned long long *blocks_out, int fd)
 {
        struct stat64 buf;
 
-       if(lstat64(path, &buf) < 0)
-               return(-errno);
+       if(fd >= 0) {
+               if (fstat64(fd, &buf) < 0)
+                       return -errno;
+       } else if(lstat64(path, &buf) < 0) {
+               return -errno;
+       }
 
        if(inode_out != NULL) *inode_out = buf.st_ino;
        if(mode_out != NULL) *mode_out = buf.st_mode;
@@ -48,7 +52,7 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
        }
        if(blksize_out != NULL) *blksize_out = buf.st_blksize;
        if(blocks_out != NULL) *blocks_out = buf.st_blocks;
-       return(0);
+       return 0;
 }
 
 int file_type(const char *path, int *maj, int *min)
@@ -56,7 +60,7 @@ int file_type(const char *path, int *maj, int *min)
        struct stat64 buf;
 
        if(lstat64(path, &buf) < 0)
-               return(-errno);
+               return -errno;
        /*We cannot pass rdev as is because glibc and the kernel disagree
         *about its definition.*/
        if(maj != NULL)
@@ -64,13 +68,13 @@ int file_type(const char *path, int *maj, int *min)
        if(min != NULL)
                *min = minor(buf.st_rdev);
 
-       if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-       else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-       else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-       else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-       else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO);
-       else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK);
-       else return(OS_TYPE_FILE);
+       if(S_ISDIR(buf.st_mode)) return OS_TYPE_DIR;
+       else if(S_ISLNK(buf.st_mode)) return OS_TYPE_SYMLINK;
+       else if(S_ISCHR(buf.st_mode)) return OS_TYPE_CHARDEV;
+       else if(S_ISBLK(buf.st_mode)) return OS_TYPE_BLOCKDEV;
+       else if(S_ISFIFO(buf.st_mode))return OS_TYPE_FIFO;
+       else if(S_ISSOCK(buf.st_mode))return OS_TYPE_SOCK;
+       else return OS_TYPE_FILE;
 }
 
 int access_file(char *path, int r, int w, int x)
@@ -80,8 +84,9 @@ int access_file(char *path, int r, int w, int x)
        if(r) mode = R_OK;
        if(w) mode |= W_OK;
        if(x) mode |= X_OK;
-       if(access(path, mode) != 0) return(-errno);
-       else return(0);
+       if(access(path, mode) != 0)
+               return -errno;
+       else return 0;
 }
 
 int open_file(char *path, int r, int w, int append)
@@ -99,8 +104,9 @@ int open_file(char *path, int r, int w, int append)
        if(append)
                mode |= O_APPEND;
        fd = open64(path, mode);
-       if(fd < 0) return(-errno);
-       else return(fd);
+       if(fd < 0)
+               return -errno;
+       else return fd;
 }
 
 void *open_dir(char *path, int *err_out)
@@ -109,8 +115,9 @@ void *open_dir(char *path, int *err_out)
 
        dir = opendir(path);
        *err_out = errno;
-       if(dir == NULL) return(NULL);
-       return(dir);
+       if(dir == NULL)
+               return NULL;
+       return dir;
 }
 
 char *read_dir(void *stream, unsigned long long *pos,
@@ -121,11 +128,12 @@ char *read_dir(void *stream, unsigned long long *pos,
 
        seekdir(dir, *pos);
        ent = readdir(dir);
-       if(ent == NULL) return(NULL);
+       if(ent == NULL)
+               return NULL;
        *len_out = strlen(ent->d_name);
        *ino_out = ent->d_ino;
        *pos = telldir(dir);
-       return(ent->d_name);
+       return ent->d_name;
 }
 
 int read_file(int fd, unsigned long long *offset, char *buf, int len)
@@ -133,9 +141,10 @@ int read_file(int fd, unsigned long long *offset, char *buf, int len)
        int n;
 
        n = pread64(fd, buf, len, *offset);
-       if(n < 0) return(-errno);
+       if(n < 0)
+               return -errno;
        *offset += n;
-       return(n);
+       return n;
 }
 
 int write_file(int fd, unsigned long long *offset, const char *buf, int len)
@@ -143,9 +152,10 @@ int write_file(int fd, unsigned long long *offset, const char *buf, int len)
        int n;
 
        n = pwrite64(fd, buf, len, *offset);
-       if(n < 0) return(-errno);
+       if(n < 0)
+               return -errno;
        *offset += n;
-       return(n);
+       return n;
 }
 
 int lseek_file(int fd, long long offset, int whence)
@@ -154,8 +164,8 @@ int lseek_file(int fd, long long offset, int whence)
 
        ret = lseek64(fd, offset, whence);
        if(ret < 0)
-               return(-errno);
-       return(0);
+               return -errno;
+       return 0;
 }
 
 int fsync_file(int fd, int datasync)
@@ -198,65 +208,90 @@ int file_create(char *name, int ur, int uw, int ux, int gr,
        mode |= ox ? S_IXOTH : 0;
        fd = open64(name, O_CREAT | O_RDWR, mode);
        if(fd < 0)
-               return(-errno);
-       return(fd);
+               return -errno;
+       return fd;
 }
 
-int set_attr(const char *file, struct hostfs_iattr *attrs)
+int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
 {
-       struct utimbuf buf;
+       struct timeval times[2];
+       struct timespec atime_ts, mtime_ts;
        int err, ma;
 
-       if(attrs->ia_valid & HOSTFS_ATTR_MODE){
-               if(chmod(file, attrs->ia_mode) != 0) return(-errno);
-       }
-       if(attrs->ia_valid & HOSTFS_ATTR_UID){
-               if(chown(file, attrs->ia_uid, -1)) return(-errno);
+       if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
+               if (fd >= 0) {
+                       if (fchmod(fd, attrs->ia_mode) != 0)
+                               return (-errno);
+               } else if (chmod(file, attrs->ia_mode) != 0) {
+                       return -errno;
+               }
        }
-       if(attrs->ia_valid & HOSTFS_ATTR_GID){
-               if(chown(file, -1, attrs->ia_gid)) return(-errno);
+       if (attrs->ia_valid & HOSTFS_ATTR_UID) {
+               if (fd >= 0) {
+                       if (fchown(fd, attrs->ia_uid, -1))
+                               return -errno;
+               } else if(chown(file, attrs->ia_uid, -1)) {
+                       return -errno;
+               }
        }
-       if(attrs->ia_valid & HOSTFS_ATTR_SIZE){
-               if(truncate(file, attrs->ia_size)) return(-errno);
+       if (attrs->ia_valid & HOSTFS_ATTR_GID) {
+               if (fd >= 0) {
+                       if (fchown(fd, -1, attrs->ia_gid))
+                               return -errno;
+               } else if (chown(file, -1, attrs->ia_gid)) {
+                       return -errno;
+               }
        }
-       ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET;
-       if((attrs->ia_valid & ma) == ma){
-               buf.actime = attrs->ia_atime.tv_sec;
-               buf.modtime = attrs->ia_mtime.tv_sec;
-               if(utime(file, &buf) != 0) return(-errno);
+       if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
+               if (fd >= 0) {
+                       if (ftruncate(fd, attrs->ia_size))
+                               return -errno;
+               } else if (truncate(file, attrs->ia_size)) {
+                       return -errno;
+               }
        }
-       else {
-               struct timespec ts;
-
-               if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
-                       err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, &ts, NULL, NULL, NULL);
-                       if(err != 0)
-                               return(err);
-                       buf.actime = attrs->ia_atime.tv_sec;
-                       buf.modtime = ts.tv_sec;
-                       if(utime(file, &buf) != 0)
-                               return(-errno);
+
+       /* Update accessed and/or modified time, in two parts: first set
+        * times according to the changes to perform, and then call futimes()
+        * or utimes() to apply them. */
+       ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
+       if (attrs->ia_valid & ma) {
+               err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
+                               &atime_ts, &mtime_ts, NULL, NULL, NULL, fd);
+               if (err != 0)
+                       return err;
+
+               times[0].tv_sec = atime_ts.tv_sec;
+               times[0].tv_usec = atime_ts.tv_nsec * 1000;
+               times[1].tv_sec = mtime_ts.tv_sec;
+               times[1].tv_usec = mtime_ts.tv_nsec * 1000;
+
+               if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
+                       times[0].tv_sec = attrs->ia_atime.tv_sec;
+                       times[0].tv_usec = attrs->ia_atime.tv_nsec * 1000;
+               }
+               if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
+                       times[1].tv_sec = attrs->ia_mtime.tv_sec;
+                       times[1].tv_usec = attrs->ia_mtime.tv_nsec * 1000;
                }
-               if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
-                       err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, &ts, NULL, NULL, NULL, NULL);
-                       if(err != 0)
-                               return(err);
-                       buf.actime = ts.tv_sec;
-                       buf.modtime = attrs->ia_mtime.tv_sec;
-                       if(utime(file, &buf) != 0)
-                               return(-errno);
+
+               if (fd >= 0) {
+                       if (futimes(fd, times) != 0)
+                               return -errno;
+               } else if (utimes(file, times) != 0) {
+                       return -errno;
                }
        }
+
        if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
        if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
                err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
                                &attrs->ia_atime, &attrs->ia_mtime, NULL,
-                               NULL, NULL);
-               if(err != 0) return(err);
+                               NULL, NULL, fd);
+               if(err != 0)
+                       return err;
        }
-       return(0);
+       return 0;
 }
 
 int make_symlink(const char *from, const char *to)
@@ -264,8 +299,9 @@ int make_symlink(const char *from, const char *to)
        int err;
 
        err = symlink(to, from);
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int unlink_file(const char *file)
@@ -273,8 +309,9 @@ int unlink_file(const char *file)
        int err;
 
        err = unlink(file);
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int do_mkdir(const char *file, int mode)
@@ -282,8 +319,9 @@ int do_mkdir(const char *file, int mode)
        int err;
 
        err = mkdir(file, mode);
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int do_rmdir(const char *file)
@@ -291,8 +329,9 @@ int do_rmdir(const char *file)
        int err;
 
        err = rmdir(file);
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
@@ -300,8 +339,9 @@ int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
        int err;
 
        err = mknod(file, mode, makedev(major, minor));
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int link_file(const char *to, const char *from)
@@ -309,8 +349,9 @@ int link_file(const char *to, const char *from)
        int err;
 
        err = link(to, from);
-       if(err) return(-errno);
-       return(0);
+       if(err)
+               return -errno;
+       return 0;
 }
 
 int do_readlink(char *file, char *buf, int size)
@@ -319,10 +360,10 @@ int do_readlink(char *file, char *buf, int size)
 
        n = readlink(file, buf, size);
        if(n < 0)
-               return(-errno);
+               return -errno;
        if(n < size)
                buf[n] = '\0';
-       return(n);
+       return n;
 }
 
 int rename_file(char *from, char *to)
@@ -330,8 +371,9 @@ int rename_file(char *from, char *to)
        int err;
 
        err = rename(from, to);
-       if(err < 0) return(-errno);
-       return(0);
+       if(err < 0)
+               return -errno;
+       return 0;
 }
 
 int do_statfs(char *root, long *bsize_out, long long *blocks_out,
@@ -344,7 +386,9 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
        int err;
 
        err = statfs64(root, &buf);
-       if(err < 0) return(-errno);
+       if(err < 0)
+               return -errno;
+
        *bsize_out = buf.f_bsize;
        *blocks_out = buf.f_blocks;
        *bfree_out = buf.f_bfree;
@@ -360,16 +404,5 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
        spare_out[2] = buf.f_spare[2];
        spare_out[3] = buf.f_spare[3];
        spare_out[4] = buf.f_spare[4];
-       return(0);
+       return 0;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index b4296bf62739727ea0370e59a59c3f76cb477600..df2ef15d03d256157c70b4a8b8be0b751d1dfab1 100644 (file)
@@ -250,7 +250,7 @@ void clear_inode(struct inode *inode)
        BUG_ON(inode->i_state & I_CLEAR);
        wait_on_inode(inode);
        DQUOT_DROP(inode);
-       if (inode->i_sb && inode->i_sb->s_op->clear_inode)
+       if (inode->i_sb->s_op->clear_inode)
                inode->i_sb->s_op->clear_inode(inode);
        if (S_ISBLK(inode->i_mode) && inode->i_bdev)
                bd_forget(inode);
@@ -275,7 +275,7 @@ static void dispose_list(struct list_head *head)
        while (!list_empty(head)) {
                struct inode *inode;
 
-               inode = list_entry(head->next, struct inode, i_list);
+               inode = list_first_entry(head, struct inode, i_list);
                list_del(&inode->i_list);
 
                if (inode->i_data.nrpages)
@@ -524,7 +524,12 @@ repeat:
  */
 struct inode *new_inode(struct super_block *sb)
 {
-       static unsigned long last_ino;
+       /*
+        * On a 32bit, non LFS stat() call, glibc will generate an EOVERFLOW
+        * error if st_ino won't fit in target struct field. Use 32bit counter
+        * here to attempt to avoid that.
+        */
+       static unsigned int last_ino;
        struct inode * inode;
 
        spin_lock_prefetch(&inode_lock);
@@ -683,27 +688,28 @@ static unsigned long hash(struct super_block *sb, unsigned long hashval)
  */
 ino_t iunique(struct super_block *sb, ino_t max_reserved)
 {
-       static ino_t counter;
+       /*
+        * On a 32bit, non LFS stat() call, glibc will generate an EOVERFLOW
+        * error if st_ino won't fit in target struct field. Use 32bit counter
+        * here to attempt to avoid that.
+        */
+       static unsigned int counter;
        struct inode *inode;
-       struct hlist_head * head;
+       struct hlist_head *head;
        ino_t res;
+
        spin_lock(&inode_lock);
-retry:
-       if (counter > max_reserved) {
-               head = inode_hashtable + hash(sb,counter);
+       do {
+               if (counter <= max_reserved)
+                       counter = max_reserved + 1;
                res = counter++;
+               head = inode_hashtable + hash(sb, res);
                inode = find_inode_fast(sb, head, res);
-               if (!inode) {
-                       spin_unlock(&inode_lock);
-                       return res;
-               }
-       } else {
-               counter = max_reserved + 1;
-       }
-       goto retry;
-       
-}
+       } while (inode != NULL);
+       spin_unlock(&inode_lock);
 
+       return res;
+}
 EXPORT_SYMBOL(iunique);
 
 struct inode *igrab(struct inode *inode)
@@ -1040,7 +1046,7 @@ static void generic_forget_inode(struct inode *inode)
                if (!(inode->i_state & (I_DIRTY|I_LOCK)))
                        list_move(&inode->i_list, &inode_unused);
                inodes_stat.nr_unused++;
-               if (!sb || (sb->s_flags & MS_ACTIVE)) {
+               if (sb->s_flags & MS_ACTIVE) {
                        spin_unlock(&inode_lock);
                        return;
                }
index f5099d86fd91fba6d3574e804be85a26e2201d68..7457501b95656087cfe27339b94d3bace7585782 100644 (file)
@@ -509,7 +509,7 @@ void inotify_destroy(struct inotify_handle *ih)
                        mutex_unlock(&ih->mutex);
                        break;
                }
-               watch = list_entry(watches->next, struct inotify_watch, h_list);
+               watch = list_first_entry(watches, struct inotify_watch, h_list);
                get_inotify_watch(watch);
                mutex_unlock(&ih->mutex);
 
index ea00126c9a5932aac9d56d02a075b7d6ae9c9093..392e8ccd6fc421c825cc1d9ccc3d3023178ca40d 100644 (file)
@@ -9,8 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/ioctl32.h>
-
 struct super_block;
 
 /*
@@ -41,14 +39,6 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
  */
 extern void __init chrdev_init(void);
 
-/*
- * compat_ioctl.c
- */
-#ifdef CONFIG_COMPAT
-extern struct ioctl_trans ioctl_start[];
-extern int ioctl_table_size;
-#endif
-
 /*
  * namespace.c
  */
index ff61772ceedd88362c35e9a9a550ca3cf1d8752a..479c1038ed4a4f7d3354e5939f6eae6a910e1d4f 100644 (file)
@@ -67,8 +67,6 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
                        return put_user(res, p);
                }
                case FIGETBSZ:
-                       if (inode->i_sb == NULL)
-                               return -EBADF;
                        return put_user(inode->i_sb->s_blocksize, p);
                case FIONREAD:
                        return put_user(i_size_read(inode) - filp->f_pos, p);
index 0208cc7ac5d0f0835ed0bceb206cce2baef5fae5..47552d4a6324effeb085c603c91dfcf945ed46f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/checkpoint.c
+ * linux/fs/jbd/checkpoint.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
index be4648bc7a2f8febe584a999040599bac87edfb6..1facfaff97cbe42e46a251b045b49e51fda772a9 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
index 10fff94439387ab98b55dabb8d6f1af1e7a5384a..46fe7439fb919b6c602e8e751e33cc42e94c1b8e 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/jbd.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/freezer.h>
@@ -211,10 +210,16 @@ end_loop:
        return 0;
 }
 
-static void journal_start_thread(journal_t *journal)
+static int journal_start_thread(journal_t *journal)
 {
-       kthread_run(kjournald, journal, "kjournald");
+       struct task_struct *t;
+
+       t = kthread_run(kjournald, journal, "kjournald");
+       if (IS_ERR(t))
+               return PTR_ERR(t);
+
        wait_event(journal->j_wait_done_commit, journal->j_task != 0);
+       return 0;
 }
 
 static void journal_kill_thread(journal_t *journal)
@@ -840,8 +845,7 @@ static int journal_reset(journal_t *journal)
 
        /* Add the dynamic fields and write it to disk. */
        journal_update_superblock(journal, 1);
-       journal_start_thread(journal);
-       return 0;
+       return journal_start_thread(journal);
 }
 
 /**
index 11563fe2a52bed60eafe259d92ae3aedbfa64e98..2a5f4b833e353626d6b3d6199e6ea13f2989e3de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/recovery.c
+ * linux/fs/jbd/recovery.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
index d204ab394f36bb0001c36d22b88fa0a1217c21f1..824e3b7d4ec15266e9f0825cccaeeb2231e5b54c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/revoke.c
+ * linux/fs/jbd/revoke.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
  *
@@ -66,7 +66,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #endif
 
index cceaf57e37781304df0b553ca2f8e9957fd65ecb..772b6531a2a25fe09f5499dd9d2b359e8edf18bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/transaction.c
+ * linux/fs/jbd/transaction.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
  *
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 
index 68039fa9a566be70de4fb9f89cd3dab25621f923..3fccde7ba008cb7b760f8128f9b571038e83b67c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/checkpoint.c
+ * linux/fs/jbd2/checkpoint.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
index 6bd8005e3d34434d95fac5037d79d4042af34678..2856e1100a5fc302a3582991c081aa3bc3d1c316 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
index 44fc32bfd7f1d2d847bb3b84c423b00a9d07f8b8..78d63b818f0b2daac94a2432396577480522ee84 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/freezer.h>
@@ -211,10 +210,16 @@ end_loop:
        return 0;
 }
 
-static void jbd2_journal_start_thread(journal_t *journal)
+static int jbd2_journal_start_thread(journal_t *journal)
 {
-       kthread_run(kjournald2, journal, "kjournald2");
+       struct task_struct *t;
+
+       t = kthread_run(kjournald2, journal, "kjournald2");
+       if (IS_ERR(t))
+               return PTR_ERR(t);
+
        wait_event(journal->j_wait_done_commit, journal->j_task != 0);
+       return 0;
 }
 
 static void journal_kill_thread(journal_t *journal)
@@ -840,8 +845,7 @@ static int journal_reset(journal_t *journal)
 
        /* Add the dynamic fields and write it to disk. */
        jbd2_journal_update_superblock(journal, 1);
-       jbd2_journal_start_thread(journal);
-       return 0;
+       return jbd2_journal_start_thread(journal);
 }
 
 /**
index 9f10acafaf70cee2482d68cad762e6e7dff59781..395c92a04ac93beea84b4c456c65670c6fe2e250 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/recovery.c
+ * linux/fs/jbd2/recovery.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
index f506646ad0ffaa17369e68c4120e18b1aff7003f..9246e763da78f1491d53b9f0ae12d89579494eaf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/revoke.c
+ * linux/fs/jbd2/revoke.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
  *
@@ -66,7 +66,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #endif
 
index 3a8700153cb087bdade5965990201eeddee9da5c..7946ff43fc40b5d91290efe2d5401e3aa3bf0d07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/transaction.c
+ * linux/fs/jbd2/transaction.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
  *
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 
diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h
deleted file mode 100644 (file)
index fa3dac1..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#define BIT_DIVIDER_MIPS 1043
-static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */
index 6aff38930b50619475e4e2974341427f185298b8..4884d5edfe658282d626c6674497231a9ff4d20a 100644 (file)
@@ -219,9 +219,9 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                struct jffs2_tmp_dnode_info *tn)
 {
        uint32_t fn_end = tn->fn->ofs + tn->fn->size;
-       struct jffs2_tmp_dnode_info *insert_point = NULL, *this;
+       struct jffs2_tmp_dnode_info *this;
 
-       dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version);
+       dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
 
        /* If a node has zero dsize, we only have to keep if it if it might be the
           node with highest version -- i.e. the one which will end up as f->metadata.
@@ -240,23 +240,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 
        /* Find the earliest node which _may_ be relevant to this one */
        this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
-       if (!this) {
-               /* First addition to empty tree. $DEITY how I love the easy cases */
-               rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node);
-               rb_insert_color(&tn->rb, &rii->tn_root);
-               dbg_readinode("keep new frag\n");
-               return 0;
-       }
-
-       /* If we add a new node it'll be somewhere under here. */
-       insert_point = this;
-
-       /* If the node is coincident with another at a lower address,
-          back up until the other node is found. It may be relevant */
-       while (tn->overlapped)
-               tn = tn_prev(tn);
+       if (this) {
+               /* If the node is coincident with another at a lower address,
+                  back up until the other node is found. It may be relevant */
+               while (this->overlapped)
+                       this = tn_prev(this);
 
-       dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+               /* First node should never be marked overlapped */
+               BUG_ON(!this);
+               dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+       }
 
        while (this) {
                if (this->fn->ofs > fn_end)
@@ -274,11 +267,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                return 0;
                        } else {
                                /* Who cares if the new one is good; keep it for now anyway. */
+                               dbg_readinode("Like new node. Throw away old\n");
                                rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
-                               /* Same overlapping from in front and behind */
-                               tn->overlapped = this->overlapped;
                                jffs2_kill_tn(c, this);
-                               dbg_readinode("Like new node. Throw away old\n");
+                               /* Same overlapping from in front and behind */
                                return 0;
                        }
                }
@@ -291,13 +283,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                jffs2_kill_tn(c, tn);
                                return 0;
                        }
-                       /* ... and is good. Kill 'this'... */
-                       rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
-                       tn->overlapped = this->overlapped;
-                       jffs2_kill_tn(c, this);
-                       /* ... and any subsequent nodes which are also overlapped */
-                       this = tn_next(tn);
-                       while (this && this->fn->ofs + this->fn->size < fn_end) {
+                       /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
+                       while (this && this->fn->ofs + this->fn->size <= fn_end) {
                                struct jffs2_tmp_dnode_info *next = tn_next(this);
                                if (this->version < tn->version) {
                                        tn_erase(this, &rii->tn_root);
@@ -308,8 +295,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                }
                                this = next;
                        }
-                       dbg_readinode("Done inserting new\n");
-                       return 0;
+                       dbg_readinode("Done killing overlapped nodes\n");
+                       continue;
                }
                if (this->version > tn->version &&
                    this->fn->ofs <= tn->fn->ofs &&
@@ -321,29 +308,21 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                return 0;
                        }
                        /* ... but 'this' was bad. Replace it... */
-                       rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
                        dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
+                       tn_erase(this, &rii->tn_root);
                        jffs2_kill_tn(c, this);
-                       return 0;
+                       break;
                }
-               /* We want to be inserted under the last node which is
-                  either at a lower offset _or_ has a smaller range */
-               if (this->fn->ofs < tn->fn->ofs ||
-                   (this->fn->ofs == tn->fn->ofs &&
-                    this->fn->size <= tn->fn->size))
-                       insert_point = this;
 
                this = tn_next(this);
        }
-       dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n",
-                     insert_point, insert_point->version, insert_point->fn->ofs,
-                     insert_point->fn->ofs+insert_point->fn->size,
-                     insert_point->overlapped);
+
        /* We neither completely obsoleted nor were completely
-          obsoleted by an earlier node. Insert under insert_point */
+          obsoleted by an earlier node. Insert into the tree */
        {
-               struct rb_node *parent = &insert_point->rb;
-               struct rb_node **link = &parent;
+               struct rb_node *parent;
+               struct rb_node **link = &rii->tn_root.rb_node;
+               struct jffs2_tmp_dnode_info *insert_point = NULL;
 
                while (*link) {
                        parent = *link;
@@ -359,6 +338,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                rb_link_node(&tn->rb, &insert_point->rb, link);
                rb_insert_color(&tn->rb, &rii->tn_root);
        }
+
        /* If there's anything behind that overlaps us, note it */
        this = tn_prev(tn);
        if (this) {
@@ -457,7 +437,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
        this = tn_last(&rii->tn_root);
        while (this) {
                dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs,
-                            this->fn->ofs+this->fn->size, this->overlapped);
+                             this->fn->ofs+this->fn->size, this->overlapped);
                this = tn_prev(this);
        }
 #endif
@@ -483,7 +463,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
                        vers_next = tn_prev(this);
                        eat_last(&ver_root, &this->rb);
                        if (check_tn_node(c, this)) {
-                               dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n",
+                               dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n",
                                             this->version, this->fn->ofs,
                                             this->fn->ofs+this->fn->size);
                                jffs2_kill_tn(c, this);
@@ -496,7 +476,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
                                        high_ver = this->version;
                                        rii->latest_ref = this->fn->raw;
                                }
-                               dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n",
+                               dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n",
                                             this, this->version, this->fn->ofs,
                                             this->fn->ofs+this->fn->size, this->overlapped);
 
@@ -850,7 +830,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                return ret;
        }
 #ifdef JFFS2_DBG_READINODE_MESSAGES
-       dbg_readinode("After adding ver %d:\n", tn->version);
+       dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version));
        tn = tn_first(&rii->tn_root);
        while (tn) {
                dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
index c556e85a565cea44fbceca308514fa51e5c80c3e..91d1d0f1c66c72c1d0c925d383f8e2a02973e2c4 100644 (file)
@@ -637,7 +637,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 
        memset(c->wbuf,0xff,c->wbuf_pagesize);
        /* adjust write buffer offset, else we get a non contiguous write bug */
-       c->wbuf_ofs += c->wbuf_pagesize;
+       if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize))
+               c->wbuf_ofs += c->wbuf_pagesize;
+       else
+               c->wbuf_ofs = 0xffffffff;
        c->wbuf_len = 0;
        return 0;
 }
index e285022f006c0d916e5d79ae20cc1ba9de756639..3467dde27e5a95ed0d7ca4e7924b0ed1feb92fea 100644 (file)
@@ -55,7 +55,6 @@ void jfs_read_inode(struct inode *inode)
                inode->i_op = &jfs_file_inode_operations;
                init_special_inode(inode, inode->i_mode, inode->i_rdev);
        }
-       jfs_set_inode_flags(inode);
 }
 
 /*
index ed814b1ff4d9b1908d4c7c0418f5c7a975392db1..fe063af6fd2fb216538d6c4bb0cc82e7ba024d2a 100644 (file)
@@ -59,6 +59,7 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
 
        switch (cmd) {
        case JFS_IOC_GETFLAGS:
+               jfs_get_inode_flags(jfs_inode);
                flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
                flags = jfs_map_ext2(flags, 0);
                return put_user(flags, (int __user *) arg);
@@ -78,6 +79,7 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
                if (!S_ISDIR(inode->i_mode))
                        flags &= ~JFS_DIRSYNC_FL;
 
+               jfs_get_inode_flags(jfs_inode);
                oldflags = jfs_inode->mode2;
 
                /*
index 82b0544bd76d197053d4f7f9557d5f5a87e06b95..f3b1ebb2228036ba4fbdb2a483f0b958323ca16a 100644 (file)
@@ -1507,7 +1507,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
                if (l2nb < budmin) {
 
                        /* search the lower level dmap control pages to get
-                        * the starting block number of the the dmap that
+                        * the starting block number of the dmap that
                         * contains or starts off the free space.
                         */
                        if ((rc =
index aa5124b643b11ee643b9d86d224a58ec90f7a400..c6530227cda66d10b2e18816c419a8f391b0a764 100644 (file)
@@ -386,7 +386,7 @@ int diRead(struct inode *ip)
                return -EIO;
        }
 
-       /* locate the the disk inode requested */
+       /* locate the disk inode requested */
        dp = (struct dinode *) mp->data;
        dp += rel_inode;
 
@@ -1407,7 +1407,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
        inum = pip->i_ino + 1;
        ino = inum & (INOSPERIAG - 1);
 
-       /* back off the the hint if it is outside of the iag */
+       /* back off the hint if it is outside of the iag */
        if (ino == 0)
                inum = pip->i_ino;
 
@@ -3078,6 +3078,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 
        jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
        jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
+       jfs_set_inode_flags(ip);
 
        ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
        if (sbi->umask != -1) {
@@ -3174,6 +3175,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip)
                dip->di_gid = cpu_to_le32(ip->i_gid);
        else
                dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
+       jfs_get_inode_flags(jfs_ip);
        /*
         * mode2 is only needed for storing the higher order bits.
         * Trust i_mode for the lower order ones
index 4c67ed97682b74711ce67fcd37681e5b4e26fb20..ed6574bee51a211ea1c46f82e04d01625308577b 100644 (file)
@@ -45,6 +45,24 @@ void jfs_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_SYNC;
 }
 
+void jfs_get_inode_flags(struct jfs_inode_info *jfs_ip)
+{
+       unsigned int flags = jfs_ip->vfs_inode.i_flags;
+
+       jfs_ip->mode2 &= ~(JFS_IMMUTABLE_FL | JFS_APPEND_FL | JFS_NOATIME_FL |
+                          JFS_DIRSYNC_FL | JFS_SYNC_FL);
+       if (flags & S_IMMUTABLE)
+               jfs_ip->mode2 |= JFS_IMMUTABLE_FL;
+       if (flags & S_APPEND)
+               jfs_ip->mode2 |= JFS_APPEND_FL;
+       if (flags & S_NOATIME)
+               jfs_ip->mode2 |= JFS_NOATIME_FL;
+       if (flags & S_DIRSYNC)
+               jfs_ip->mode2 |= JFS_DIRSYNC_FL;
+       if (flags & S_SYNC)
+               jfs_ip->mode2 |= JFS_SYNC_FL;
+}
+
 /*
  * NAME:       ialloc()
  *
index 6802837f757ee17c7bc6914e8f2d03228c23f870..2374b595f2e1c6e70926c114058381b354e25cf6 100644 (file)
@@ -31,6 +31,7 @@ extern void jfs_truncate(struct inode *);
 extern void jfs_truncate_nolock(struct inode *, loff_t);
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
+extern void jfs_get_inode_flags(struct jfs_inode_info *);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
index df48ece4b7a3cdb7713b32c96121c9408d376e89..ecf04882265ea5f5526da109e7b82761f38c6f21 100644 (file)
@@ -45,7 +45,7 @@ do {                                                  \
                io_schedule();                          \
                lock_cmd;                               \
        }                                               \
-       current->state = TASK_RUNNING;                  \
+       __set_current_state(TASK_RUNNING);                      \
        remove_wait_queue(&wq, &__wait);                \
 } while (0)
 
index 5065baa530b601d2d4ee28a5247ff7bc23e09b60..44a2f33cb98d5d7e3e81ebe7cb0f7c2a12270d29 100644 (file)
@@ -62,7 +62,6 @@
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/kthread.h>
 #include <linux/buffer_head.h>         /* for sync_blockdev() */
@@ -1590,7 +1589,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
                set_current_state(TASK_UNINTERRUPTIBLE);
                LOGGC_UNLOCK(log);
                schedule();
-               current->state = TASK_RUNNING;
+               __set_current_state(TASK_RUNNING);
                LOGGC_LOCK(log);
                remove_wait_queue(&target->gcwait, &__wait);
        }
@@ -1961,7 +1960,7 @@ static void lbmfree(struct lbuf * bp)
 /*
  * NAME:       lbmRedrive
  *
- * FUNCTION:   add a log buffer to the the log redrive list
+ * FUNCTION:   add a log buffer to the log redrive list
  *
  * PARAMETER:
  *     bp      - log buffer
@@ -2354,14 +2353,15 @@ int jfsIOWait(void *arg)
                        lbmStartIO(bp);
                        spin_lock_irq(&log_redrive_lock);
                }
-               spin_unlock_irq(&log_redrive_lock);
 
                if (freezing(current)) {
+                       spin_unlock_irq(&log_redrive_lock);
                        refrigerator();
                } else {
                        set_current_state(TASK_INTERRUPTIBLE);
+                       spin_unlock_irq(&log_redrive_lock);
                        schedule();
-                       current->state = TASK_RUNNING;
+                       __set_current_state(TASK_RUNNING);
                }
        } while (!kthread_should_stop());
 
index 03893acbfda479d15351fb5f45dc9b74b4cd6986..25430d0b0d593a4576cbe9028a5c7c8bdb353d8c 100644 (file)
@@ -44,7 +44,6 @@
 
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/freezer.h>
 #include <linux/module.h>
@@ -136,7 +135,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
        set_current_state(TASK_UNINTERRUPTIBLE);
        TXN_UNLOCK();
        io_schedule();
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(event, &wait);
 }
 
@@ -2798,7 +2797,7 @@ int jfs_lazycommit(void *arg)
                        set_current_state(TASK_INTERRUPTIBLE);
                        LAZY_UNLOCK(flags);
                        schedule();
-                       current->state = TASK_RUNNING;
+                       __set_current_state(TASK_RUNNING);
                        remove_wait_queue(&jfs_commit_thread_wait, &wq);
                }
        } while (!kthread_should_stop());
@@ -2990,7 +2989,7 @@ int jfs_sync(void *arg)
                        set_current_state(TASK_INTERRUPTIBLE);
                        TXN_UNLOCK();
                        schedule();
-                       current->state = TASK_RUNNING;
+                       __set_current_state(TASK_RUNNING);
                }
        } while (!kthread_should_stop());
 
index d93842d3c0a0b66943a0491622e0793971d70de5..5294de1f40c41ba3c2dfcd992c725202967b0dce 100644 (file)
@@ -159,7 +159,10 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                        continue;
 
                                spin_unlock(&dcache_lock);
-                               if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0)
+                               if (filldir(dirent, next->d_name.name, 
+                                           next->d_name.len, filp->f_pos, 
+                                           next->d_inode->i_ino, 
+                                           dt_type(next->d_inode)) < 0)
                                        return 0;
                                spin_lock(&dcache_lock);
                                /* next is still alive */
@@ -220,6 +223,12 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
        root = new_inode(s);
        if (!root)
                goto Enomem;
+       /*
+        * since this is the first inode, make it number 1. New inodes created
+        * after this must take care not to collide with it (by passing
+        * max_reserved of 1 to iunique).
+        */
+       root->i_ino = 1;
        root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
        root->i_uid = root->i_gid = 0;
        root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
@@ -360,6 +369,11 @@ int simple_commit_write(struct file *file, struct page *page,
        return 0;
 }
 
+/*
+ * the inodes created here are not hashed. If you use iunique to generate
+ * unique inode values later for this filesystem, then you must take care
+ * to pass it an appropriate max_reserved value to avoid collisions.
+ */
 int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
 {
        struct inode *inode;
@@ -376,6 +390,11 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
        inode = new_inode(s);
        if (!inode)
                return -ENOMEM;
+       /*
+        * because the root inode is 1, the files array must not contain an
+        * entry at index 1
+        */
+       inode->i_ino = 1;
        inode->i_mode = S_IFDIR | 0755;
        inode->i_uid = inode->i_gid = 0;
        inode->i_blocks = 0;
@@ -391,6 +410,13 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
        for (i = 0; !files->name || files->name[0]; i++, files++) {
                if (!files->name)
                        continue;
+
+               /* warn if it tries to conflict with the root inode */
+               if (unlikely(i == 1))
+                       printk(KERN_WARNING "%s: %s passed in a files array"
+                               "with an index of 1!\n", __func__,
+                               s->s_type->name);
+
                dentry = d_alloc_name(root, files->name);
                if (!dentry)
                        goto out;
index a5c019e1a44762bb63601accb17bb6b7a2671552..a10343bed1607252c24c2ffcad872a0042c6d758 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/fs.h>
 #include <linux/nfs_fs.h>
 #include <linux/utsname.h>
-#include <linux/smp_lock.h>
 #include <linux/freezer.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
index 692a3e578fc8f1102823548dbc5d49a1a1850953..0fb914fc2ee0d2f912137b3922a6b4eebd65f633 100644 (file)
@@ -284,11 +284,9 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
        }
 
        if (first_hole != blocks_per_page) {
-               char *kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + (first_hole << blkbits), 0,
-                               PAGE_CACHE_SIZE - (first_hole << blkbits));
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, first_hole << blkbits,
+                               PAGE_CACHE_SIZE - (first_hole << blkbits),
+                               KM_USER0);
                if (first_hole == 0) {
                        SetPageUptodate(page);
                        unlock_page(page);
@@ -576,14 +574,11 @@ page_is_mapped:
                 * written out to the file."
                 */
                unsigned offset = i_size & (PAGE_CACHE_SIZE - 1);
-               char *kaddr;
 
                if (page->index > end_index || !offset)
                        goto confused;
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, offset, PAGE_CACHE_SIZE - offset,
+                               KM_USER0);
        }
 
        /*
@@ -663,12 +658,7 @@ confused:
        /*
         * The caller has a ref on the inode, so *mapping is stable
         */
-       if (*ret) {
-               if (*ret == -ENOSPC)
-                       set_bit(AS_ENOSPC, &mapping->flags);
-               else
-                       set_bit(AS_EIO, &mapping->flags);
-       }
+       mapping_set_error(mapping, *ret);
 out:
        return bio;
 }
@@ -776,14 +766,7 @@ retry:
 
                        if (writepage) {
                                ret = (*writepage)(page, wbc);
-                               if (ret) {
-                                       if (ret == -ENOSPC)
-                                               set_bit(AS_ENOSPC,
-                                                       &mapping->flags);
-                                       else
-                                               set_bit(AS_EIO,
-                                                       &mapping->flags);
-                               }
+                               mapping_set_error(mapping, ret);
                        } else {
                                bio = __mpage_writepage(bio, page, get_block,
                                                &last_block_in_bio, &ret, wbc,
index 94b2f60aec22b8d25e697382182f7cebf047cc66..b3780e3fc88ea18f2b7f5a2666702312f501b8b5 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/quotaops.h>
 #include <linux/pagemap.h>
 #include <linux/fsnotify.h>
-#include <linux/smp_lock.h>
 #include <linux/personality.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
@@ -1153,14 +1152,12 @@ static int fastcall do_path_lookup(int dfd, const char *name,
 
                fput_light(file, fput_needed);
        }
-       current->total_link_count = 0;
-       retval = link_path_walk(name, nd);
+
+       retval = path_walk(name, nd);
 out:
-       if (likely(retval == 0)) {
-               if (unlikely(!audit_dummy_context() && nd && nd->dentry &&
+       if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
                                nd->dentry->d_inode))
                audit_inode(name, nd->dentry->d_inode);
-       }
 out_fail:
        return retval;
 
@@ -1350,17 +1347,6 @@ struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int le
        return __lookup_hash_kern(&this, base, NULL);
 }
 
-/*
- *     namei()
- *
- * is used by most simple commands to get the inode of a specified name.
- * Open, link etc use their own routines, but this is enough for things
- * like 'chmod' etc.
- *
- * namei exists in two versions: namei/lnamei. The only difference is
- * that namei follows links, while lnamei does not.
- * SMP-safe
- */
 int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
                            struct nameidata *nd)
 {
index fd999cab7b57c07b7729aabb3d96d938e3d8f0d1..b696e3a0d18fcf2d4bb017dcaa36dacb39c565e6 100644 (file)
@@ -377,6 +377,10 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
        seq_putc(m, ' ');
        mangle(m, mnt->mnt_sb->s_type->name);
+       if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) {
+               seq_putc(m, '.');
+               mangle(m, mnt->mnt_sb->s_subtype);
+       }
        seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
        for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
                if (mnt->mnt_sb->s_flags & fs_infop->flag)
@@ -495,7 +499,7 @@ void release_mounts(struct list_head *head)
 {
        struct vfsmount *mnt;
        while (!list_empty(head)) {
-               mnt = list_entry(head->next, struct vfsmount, mnt_hash);
+               mnt = list_first_entry(head, struct vfsmount, mnt_hash);
                list_del_init(&mnt->mnt_hash);
                if (mnt->mnt_parent != mnt) {
                        struct dentry *dentry;
@@ -882,6 +886,9 @@ static int do_change_type(struct nameidata *nd, int flag)
        int recurse = flag & MS_REC;
        int type = flag & ~MS_REC;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        if (nd->dentry != nd->mnt->mnt_root)
                return -EINVAL;
 
@@ -1173,7 +1180,7 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
 
        while (!list_empty(graveyard)) {
                LIST_HEAD(umounts);
-               mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire);
+               mnt = list_first_entry(graveyard, struct vfsmount, mnt_expire);
                list_del_init(&mnt->mnt_expire);
 
                /* don't do anything if the namespace is dead - all the
@@ -1441,10 +1448,9 @@ dput_out:
  * Allocate a new namespace structure and populate it with contents
  * copied from the namespace of the passed in task structure.
  */
-struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
+static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                struct fs_struct *fs)
 {
-       struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns;
        struct mnt_namespace *new_ns;
        struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
        struct vfsmount *p, *q;
@@ -1509,36 +1515,21 @@ struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
        return new_ns;
 }
 
-int copy_mnt_ns(int flags, struct task_struct *tsk)
+struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
+               struct fs_struct *new_fs)
 {
-       struct mnt_namespace *ns = tsk->nsproxy->mnt_ns;
        struct mnt_namespace *new_ns;
-       int err = 0;
-
-       if (!ns)
-               return 0;
 
+       BUG_ON(!ns);
        get_mnt_ns(ns);
 
        if (!(flags & CLONE_NEWNS))
-               return 0;
+               return ns;
 
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       new_ns = dup_mnt_ns(tsk, tsk->fs);
-       if (!new_ns) {
-               err = -ENOMEM;
-               goto out;
-       }
+       new_ns = dup_mnt_ns(ns, new_fs);
 
-       tsk->nsproxy->mnt_ns = new_ns;
-
-out:
        put_mnt_ns(ns);
-       return err;
+       return new_ns;
 }
 
 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
index 6b1f6d27099a8f3a1a962928c543039d662b401e..addfd3147ea7a139138ab81cb32b745067226843 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/smp_lock.h>
 
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
index 5bd03b97002e1e9dd73f1d36aeecaaf76c94da5c..50c6821bad269b50a84a7f8ccb30210d045f9777 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/nfs_mount.h>
 #include <linux/nfs4_mount.h>
 #include <linux/lockd/bind.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/nfs_idmap.h>
index 889de60f8a842bdadc771a32fc3a192ca23873e2..345aa5c0f3824cb78255b50a48d84be61eb17517 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/pagemap.h>
 #include <linux/kref.h>
index 6ef268f7c300a2458a74e4292efec297b21de3b0..234778576f096359ade33cf319633b33cf168702 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/nfs_mount.h>
 #include <linux/nfs4_mount.h>
 #include <linux/lockd/bind.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/nfs_idmap.h>
index 7d0371e2bad53228b8d2cbee4e95b9bf3fe75b25..45268d6def2eda4c9d286ba048ba058156924e87 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
 #include <linux/lockd/bind.h>
-#include <linux/smp_lock.h>
 #include <linux/nfs_mount.h>
 
 #include "iostat.h"
index f5f4430fb2a4c0ba3d488878a9007f26397cae43..0505ca1240344d6096760f83a0d02c37f09c8e6a 100644 (file)
@@ -43,7 +43,6 @@
  * child task framework of the RPC layer?
  */
 
-#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/sched.h>
index 1dcf56de948276c5bef2c62ff91303c30c652611..7be0ee2782cb6395c41eab8818935af27c1916ee 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
 #include <linux/lockd/bind.h>
-#include <linux/smp_lock.h>
 #include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PROC
index bc2821331c29a9a633f36d2bfbb9ed839e7a1629..83e865a16ad1393cc25ce62377bed94855880ff0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/namei.h>
 
 /* Symlink caching in the page cache is even more simplistic
index 5d44b8bd107093c72ac5d0aa50f23a20025ec609..de92b9509d948f7bbcaf07a802a5d85b69cf6104 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/backing-dev.h>
 
 #include <asm/uaccess.h>
-#include <linux/smp_lock.h>
 
 #include "delegation.h"
 #include "internal.h"
@@ -225,7 +224,7 @@ static int nfs_set_page_writeback(struct page *page)
                struct inode *inode = page->mapping->host;
                struct nfs_server *nfss = NFS_SERVER(inode);
 
-               if (atomic_inc_return(&nfss->writeback) >
+               if (atomic_long_inc_return(&nfss->writeback) >
                                NFS_CONGESTION_ON_THRESH)
                        set_bdi_congested(&nfss->backing_dev_info, WRITE);
        }
@@ -238,7 +237,7 @@ static void nfs_end_page_writeback(struct page *page)
        struct nfs_server *nfss = NFS_SERVER(inode);
 
        end_page_writeback(page);
-       if (atomic_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) {
+       if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) {
                clear_bdi_congested(&nfss->backing_dev_info, WRITE);
                congestion_end(WRITE);
        }
index ce341dc76d5ec6366d48c94844f4809a2560ab58..9b118ee2019371e151b69089061b67c3722b52c6 100644 (file)
@@ -11,4 +11,3 @@ nfsd-$(CONFIG_NFSD_V3)        += nfs3proc.o nfs3xdr.o
 nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
 nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
                           nfs4acl.o nfs4callback.o nfs4recover.o
-nfsd-objs              := $(nfsd-y)
index 6f24768272a1f05dcdd9657d3bb22755c06e9dce..79bd03b8bbf868e7638b1e85f90977b7727c88e6 100644 (file)
@@ -469,6 +469,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
        nd.dentry = NULL;
        exp.ex_path = NULL;
 
+       /* fs locations */
+       exp.ex_fslocs.locations = NULL;
+       exp.ex_fslocs.locations_count = 0;
+       exp.ex_fslocs.migrated = 0;
+
+       exp.ex_uuid = NULL;
+
        if (mesg[mlen-1] != '\n')
                return -EINVAL;
        mesg[mlen-1] = 0;
@@ -509,13 +516,6 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
        if (exp.h.expiry_time == 0)
                goto out;
 
-       /* fs locations */
-       exp.ex_fslocs.locations = NULL;
-       exp.ex_fslocs.locations_count = 0;
-       exp.ex_fslocs.migrated = 0;
-
-       exp.ex_uuid = NULL;
-
        /* flags */
        err = get_int(&mesg, &an_int);
        if (err == -ENOENT)
index 7f5bad0393b197915e203004b78dbb79d0eae4b9..eac82830bfd71ea3887c68081479cac4929ba618 100644 (file)
@@ -177,7 +177,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
        if (max_blocksize < resp->count)
                resp->count = max_blocksize;
 
-       svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
+       svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
 
        fh_copy(&resp->fh, &argp->fh);
        nfserr = nfsd_read(rqstp, &resp->fh, NULL,
index 7e4bb0af24d7d48d70a61feae9e5930efbde3e59..10f6e7dcf6336b48746cd6c16d7ed5c1d04cae28 100644 (file)
@@ -239,7 +239,7 @@ static __be32 *
 encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
        struct dentry *dentry = fhp->fh_dentry;
-       if (dentry && dentry->d_inode != NULL) {
+       if (dentry && dentry->d_inode) {
                int err;
                struct kstat stat;
 
@@ -300,9 +300,9 @@ int
 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_sattrargs *args)
 {
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = decode_sattr3(p, &args->attrs)))
+       if (!(p = decode_fh(p, &args->fh)))
                return 0;
+       p = decode_sattr3(p, &args->attrs);
 
        if ((args->check_guard = ntohl(*p++)) != 0) { 
                struct timespec time; 
@@ -343,9 +343,9 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        int v,pn;
        u32 max_blocksize = svc_max_payload(rqstp);
 
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = xdr_decode_hyper(p, &args->offset)))
+       if (!(p = decode_fh(p, &args->fh)))
                return 0;
+       p = xdr_decode_hyper(p, &args->offset);
 
        len = args->count = ntohl(*p++);
 
@@ -369,28 +369,44 @@ int
 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_writeargs *args)
 {
-       unsigned int len, v, hdr;
+       unsigned int len, v, hdr, dlen;
        u32 max_blocksize = svc_max_payload(rqstp);
 
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = xdr_decode_hyper(p, &args->offset)))
+       if (!(p = decode_fh(p, &args->fh)))
                return 0;
+       p = xdr_decode_hyper(p, &args->offset);
 
        args->count = ntohl(*p++);
        args->stable = ntohl(*p++);
        len = args->len = ntohl(*p++);
+       /*
+        * The count must equal the amount of data passed.
+        */
+       if (args->count != args->len)
+               return 0;
 
+       /*
+        * Check to make sure that we got the right number of
+        * bytes.
+        */
        hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-       if (rqstp->rq_arg.len < hdr ||
-           rqstp->rq_arg.len - hdr < len)
+       dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
+               - hdr;
+       /*
+        * Round the length of the data which was specified up to
+        * the next multiple of XDR units and then compare that
+        * against the length which was actually received.
+        */
+       if (dlen != XDR_QUADLEN(len)*4)
                return 0;
 
+       if (args->count > max_blocksize) {
+               args->count = max_blocksize;
+               len = args->len = max_blocksize;
+       }
        rqstp->rq_vec[0].iov_base = (void*)p;
        rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
-
-       if (len > max_blocksize)
-               len = max_blocksize;
-       v=  0;
+       v = 0;
        while (len > rqstp->rq_vec[v].iov_len) {
                len -= rqstp->rq_vec[v].iov_len;
                v++;
@@ -398,9 +414,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
                rqstp->rq_vec[v].iov_len = PAGE_SIZE;
        }
        rqstp->rq_vec[v].iov_len = len;
-       args->vlen = v+1;
-
-       return args->count == args->len && rqstp->rq_vec[0].iov_len > 0;
+       args->vlen = v + 1;
+       return 1;
 }
 
 int
@@ -414,8 +429,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
        switch (args->createmode = ntohl(*p++)) {
        case NFS3_CREATE_UNCHECKED:
        case NFS3_CREATE_GUARDED:
-               if (!(p = decode_sattr3(p, &args->attrs)))
-                       return 0;
+               p = decode_sattr3(p, &args->attrs);
                break;
        case NFS3_CREATE_EXCLUSIVE:
                args->verf = p;
@@ -431,10 +445,10 @@ int
 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_createargs *args)
 {
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = decode_filename(p, &args->name, &args->len))
-        || !(p = decode_sattr3(p, &args->attrs)))
+       if (!(p = decode_fh(p, &args->fh)) ||
+           !(p = decode_filename(p, &args->name, &args->len)))
                return 0;
+       p = decode_sattr3(p, &args->attrs);
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -448,11 +462,12 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
        char *old, *new;
        struct kvec *vec;
 
-       if (!(p = decode_fh(p, &args->ffh))
-        || !(p = decode_filename(p, &args->fname, &args->flen))
-        || !(p = decode_sattr3(p, &args->attrs))
+       if (!(p = decode_fh(p, &args->ffh)) ||
+           !(p = decode_filename(p, &args->fname, &args->flen))
                )
                return 0;
+       p = decode_sattr3(p, &args->attrs);
+
        /* now decode the pathname, which might be larger than the first page.
         * As we have to check for nul's anyway, we copy it into a new page
         * This page appears in the rq_res.pages list, but as pages_len is always
@@ -502,10 +517,8 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
        args->ftype = ntohl(*p++);
 
        if (args->ftype == NF3BLK  || args->ftype == NF3CHR
-        || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
-               if (!(p = decode_sattr3(p, &args->attrs)))
-                       return 0;
-       }
+        || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
+               p = decode_sattr3(p, &args->attrs);
 
        if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
                args->major = ntohl(*p++);
index 673a53c014a3f4d3ad81c7a7bb9b22730b9b6bf9..cc3b7badd4869299f6c86dd14342f42177768acb 100644 (file)
@@ -137,7 +137,6 @@ struct ace_container {
 static short ace2type(struct nfs4_ace *);
 static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
                                unsigned int);
-void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 
 struct nfs4_acl *
 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -785,21 +784,6 @@ nfs4_acl_new(int n)
        return acl;
 }
 
-void
-nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
-               int whotype, uid_t who)
-{
-       struct nfs4_ace *ace = acl->aces + acl->naces;
-
-       ace->type = type;
-       ace->flag = flag;
-       ace->access_mask = access_mask;
-       ace->whotype = whotype;
-       ace->who = who;
-
-       acl->naces++;
-}
-
 static struct {
        char *string;
        int   stringlen;
@@ -851,6 +835,5 @@ nfs4_acl_write_who(int who, char *p)
 }
 
 EXPORT_SYMBOL(nfs4_acl_new);
-EXPORT_SYMBOL(nfs4_acl_add_ace);
 EXPORT_SYMBOL(nfs4_acl_get_whotype);
 EXPORT_SYMBOL(nfs4_acl_write_who);
index e4a83d727afda0e2f85e293783dce44b2e351fd5..45aa21ce678420821953a8e9b5c7e1e442cce6f4 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
-#include <linux/smp_lock.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/nfsd_idmap.h>
 #include <linux/list.h>
index 678f3be88ac04e7cf319e1819835f8a394b53291..3cc8ce422ab1a245a746cc15401be505031f17c2 100644 (file)
@@ -1326,8 +1326,6 @@ do_recall(void *__dp)
 {
        struct nfs4_delegation *dp = __dp;
 
-       daemonize("nfsv4-recall");
-
        nfsd4_cb_recall(dp);
        return 0;
 }
index 5d090f11f2bee92c3e371fbd0ae982df7d6a758d..15809dfd88a594d64d258f98aff7941a878a8be0 100644 (file)
@@ -44,7 +44,6 @@
 
 #include <linux/param.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/vfs.h>
index 8d995bcef806bc99a668b183cf9dee29bfe27bea..6ca2d24fc216d6cf5ccf6f293955b0ad27accb73 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
@@ -324,7 +323,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
         *
         */
 
-       u8 version = 1;
+       u8 version;
        u8 fsid_type = 0;
        struct inode * inode = dentry->d_inode;
        struct dentry *parent = dentry->d_parent;
@@ -342,15 +341,59 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
         * the reference filehandle (if it is in the same export)
         * or the export options.
         */
+ retry:
+       version = 1;
        if (ref_fh && ref_fh->fh_export == exp) {
                version = ref_fh->fh_handle.fh_version;
-               if (version == 0xca)
+               fsid_type = ref_fh->fh_handle.fh_fsid_type;
+
+               if (ref_fh == fhp)
+                       fh_put(ref_fh);
+               ref_fh = NULL;
+
+               switch (version) {
+               case 0xca:
                        fsid_type = FSID_DEV;
-               else
-                       fsid_type = ref_fh->fh_handle.fh_fsid_type;
-               /* We know this version/type works for this export
-                * so there is no need for further checks.
+                       break;
+               case 1:
+                       break;
+               default:
+                       goto retry;
+               }
+
+               /* Need to check that this type works for this
+                * export point.  As the fsid -> filesystem mapping
+                * was guided by user-space, there is no guarantee
+                * that the filesystem actually supports that fsid
+                * type. If it doesn't we loop around again without
+                * ref_fh set.
                 */
+               switch(fsid_type) {
+               case FSID_DEV:
+                       if (!old_valid_dev(ex_dev))
+                               goto retry;
+                       /* FALL THROUGH */
+               case FSID_MAJOR_MINOR:
+               case FSID_ENCODE_DEV:
+                       if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags
+                             & FS_REQUIRES_DEV))
+                               goto retry;
+                       break;
+               case FSID_NUM:
+                       if (! (exp->ex_flags & NFSEXP_FSID))
+                               goto retry;
+                       break;
+               case FSID_UUID8:
+               case FSID_UUID16:
+                       if (!root_export)
+                               goto retry;
+                       /* fall through */
+               case FSID_UUID4_INUM:
+               case FSID_UUID16_INUM:
+                       if (exp->ex_uuid == NULL)
+                               goto retry;
+                       break;
+               }
        } else if (exp->ex_uuid) {
                if (fhp->fh_maxsize >= 64) {
                        if (root_export)
index 5cc2eec981b8763012794ef1f4da0ab5cc50df3d..b2c7147aa921414c9243012a513861dbea3c8133 100644 (file)
@@ -155,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
                                argp->count);
                argp->count = NFSSVC_MAXBLKSIZE_V2;
        }
-       svc_reserve(rqstp, (19<<2) + argp->count + 4);
+       svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
 
        resp->count = argp->count;
        nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
index 0c24b9e24fe866683a357f1a9e8b08bcb2fbe30c..cb3e7fadb772127975898e14a43c6bd3dd4c4d92 100644 (file)
@@ -231,9 +231,10 @@ int
 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd_sattrargs *args)
 {
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = decode_sattr(p, &args->attrs)))
+       p = decode_fh(p, &args->fh);
+       if (!p)
                return 0;
+       p = decode_sattr(p, &args->attrs);
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -284,8 +285,9 @@ int
 nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd_writeargs *args)
 {
-       unsigned int len;
+       unsigned int len, hdr, dlen;
        int v;
+
        if (!(p = decode_fh(p, &args->fh)))
                return 0;
 
@@ -293,11 +295,30 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
        args->offset = ntohl(*p++);     /* offset */
        p++;                            /* totalcount */
        len = args->len = ntohl(*p++);
-       rqstp->rq_vec[0].iov_base = (void*)p;
-       rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len -
-                               (((void*)p) - rqstp->rq_arg.head[0].iov_base);
+       /*
+        * The protocol specifies a maximum of 8192 bytes.
+        */
        if (len > NFSSVC_MAXBLKSIZE_V2)
-               len = NFSSVC_MAXBLKSIZE_V2;
+               return 0;
+
+       /*
+        * Check to make sure that we got the right number of
+        * bytes.
+        */
+       hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
+       dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
+               - hdr;
+
+       /*
+        * Round the length of the data which was specified up to
+        * the next multiple of XDR units and then compare that
+        * against the length which was actually received.
+        */
+       if (dlen != XDR_QUADLEN(len)*4)
+               return 0;
+
+       rqstp->rq_vec[0].iov_base = (void*)p;
+       rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
        v = 0;
        while (len > rqstp->rq_vec[v].iov_len) {
                len -= rqstp->rq_vec[v].iov_len;
@@ -306,18 +327,18 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
                rqstp->rq_vec[v].iov_len = PAGE_SIZE;
        }
        rqstp->rq_vec[v].iov_len = len;
-       args->vlen = v+1;
-       return rqstp->rq_vec[0].iov_len > 0;
+       args->vlen = v + 1;
+       return 1;
 }
 
 int
 nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd_createargs *args)
 {
-       if (!(p = decode_fh(p, &args->fh))
-        || !(p = decode_filename(p, &args->name, &args->len))
-        || !(p = decode_sattr(p, &args->attrs)))
+       if (   !(p = decode_fh(p, &args->fh))
+           || !(p = decode_filename(p, &args->name, &args->len)))
                return 0;
+       p = decode_sattr(p, &args->attrs);
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -361,11 +382,11 @@ int
 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd_symlinkargs *args)
 {
-       if (!(p = decode_fh(p, &args->ffh))
-        || !(p = decode_filename(p, &args->fname, &args->flen))
-        || !(p = decode_pathname(p, &args->tname, &args->tlen))
-        || !(p = decode_sattr(p, &args->attrs)))
+       if (   !(p = decode_fh(p, &args->ffh))
+           || !(p = decode_filename(p, &args->fname, &args->flen))
+           || !(p = decode_pathname(p, &args->tname, &args->tlen)))
                return 0;
+       p = decode_sattr(p, &args->attrs);
 
        return xdr_argsize_check(rqstp, p);
 }
index 74f99a6a369bf757df3670ece2c008292d65ddc5..34314b33dbd409f379df4874894625553edc2880 100644 (file)
@@ -20,7 +20,6 @@
  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
 #include "dir.h"
index dbbac55931064124ae081c0291183843b5f217d6..621de369e6f835ae6ef186a5c742c56c5d115c1d 100644 (file)
@@ -2129,28 +2129,13 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
        loff_t pos;
-       unsigned long seg;
        size_t count;           /* after file limit checks */
        ssize_t written, err;
 
        count = 0;
-       for (seg = 0; seg < nr_segs; seg++) {
-               const struct iovec *iv = &iov[seg];
-               /*
-                * If any segment has a negative length, or the cumulative
-                * length ever wraps negative then return -EINVAL.
-                */
-               count += iv->iov_len;
-               if (unlikely((ssize_t)(count|iv->iov_len) < 0))
-                       return -EINVAL;
-               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-                       continue;
-               if (!seg)
-                       return -EFAULT;
-               nr_segs = seg;
-               count -= iv->iov_len;   /* This segment is no good */
-               break;
-       }
+       err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
+       if (err)
+               return err;
        pos = *ppos;
        vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
        /* We can write back this queue in page reclaim. */
index f8bf8da67ee8f86bb0813b231f55ddbfc5148a46..074791ce4ab27fda0ae007f491662ac5ec95b2a7 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 
 #include "aops.h"
 #include "attrib.h"
index d4e46d067edd3d368352ce8d122df628c608df86..5671cf9d6383529a0b0c278ce304fcf2fc1ebeca 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 
 #include <asm/uaccess.h>
index 024777abc8e32d1d97938541d38430369a342293..d1bd305ef0d7a735f4971a8b36727085bc102f1c 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/crc32.h>
 #include <linux/kthread.h>
 #include <linux/pagemap.h>
index bc844bfe607c8ac8a8716b63bcb07c004e5b9fcb..c53a6763bbbebf7500f4c53e9e1e38ca9806eb15 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include <asm/byteorder.h>
 
index d921a28329dcb81e21525b51e0da41a2aceeec9e..d8b79067dc14778a5d67556c20c62fec9a5e4de7 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
 
 #define MLOG_MASK_PREFIX ML_SUPER
 #include <cluster/masklog.h>
index 4f82a2f0efef9edfa76493d39dce1a1ba9b83d96..66a13ee63d4c7cd2ee496214cd7ea6a2c6b31b65 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 
 #include <cluster/heartbeat.h>
index c989fb4cf7b9ce1bfc479ca7a0b6a4881e333c63..0d515d1619747b00e724471a407f2a6cf6ea51d7 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -7,7 +7,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <linux/quotaops.h>
 #include <linux/fsnotify.h>
 #include <linux/module.h>
@@ -211,6 +210,9 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
                newattrs.ia_valid |= ATTR_FILE;
        }
 
+       /* Remove suid/sgid on truncate too */
+       newattrs.ia_valid |= should_remove_suid(dentry);
+
        mutex_lock(&dentry->d_inode->i_mutex);
        err = notify_change(dentry, &newattrs);
        mutex_unlock(&dentry->d_inode->i_mutex);
index 6e8bb66fe61957afe51b4e7eb00004ba20b0ba96..01207042048b993201b0799b82c6a198ab73001f 100644 (file)
@@ -236,3 +236,12 @@ config EFI_PARTITION
        help
          Say Y here if you would like to use hard disks under Linux which
          were partitioned using EFI GPT.
+
+config SYSV68_PARTITION
+       bool "SYSV68 partition table support" if PARTITION_ADVANCED
+       default y if M68K
+       help
+         Say Y here if you would like to be able to read the hard disk
+         partition table format used by Motorola Delta machines (using
+         sysv68).
+         Otherwise, say N.
index 67e665fdb7fccbde923238532d49f192931d43f9..03af8eac51da81bf4f89cc49d7d9ca466d38c54b 100644 (file)
@@ -17,3 +17,4 @@ obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
+obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
index 6b9dae3f0e6c1d493f6b3990c2a1b5d18db3b8c5..9a3a058f355365405911c3f1173209cfac30150d 100644 (file)
@@ -34,6 +34,7 @@
 #include "ultrix.h"
 #include "efi.h"
 #include "karma.h"
+#include "sysv68.h"
 
 #ifdef CONFIG_BLK_DEV_MD
 extern void md_autodetect_dev(dev_t dev);
@@ -104,6 +105,9 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
 #endif
 #ifdef CONFIG_KARMA_PARTITION
        karma_partition,
+#endif
+#ifdef CONFIG_SYSV68_PARTITION
+       sysv68_partition,
 #endif
        NULL
 };
diff --git a/fs/partitions/sysv68.c b/fs/partitions/sysv68.c
new file mode 100644 (file)
index 0000000..4eba27b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  fs/partitions/sysv68.c
+ *
+ *  Copyright (C) 2007 Philippe De Muyter <phdm@macqel.be>
+ */
+
+#include "check.h"
+#include "sysv68.h"
+
+/*
+ *     Volume ID structure: on first 256-bytes sector of disk
+ */
+
+struct volumeid {
+       u8      vid_unused[248];
+       u8      vid_mac[8];     /* ASCII string "MOTOROLA" */
+};
+
+/*
+ *     config block: second 256-bytes sector on disk
+ */
+
+struct dkconfig {
+       u8      ios_unused0[128];
+       __be32  ios_slcblk;     /* Slice table block number */
+       __be16  ios_slccnt;     /* Number of entries in slice table */
+       u8      ios_unused1[122];
+};
+
+/*
+ *     combined volumeid and dkconfig block
+ */
+
+struct dkblk0 {
+       struct volumeid dk_vid;
+       struct dkconfig dk_ios;
+};
+
+/*
+ *     Slice Table Structure
+ */
+
+struct slice {
+       __be32  nblocks;                /* slice size (in blocks) */
+       __be32  blkoff;                 /* block offset of slice */
+};
+
+
+int sysv68_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+       int i, slices;
+       int slot = 1;
+       Sector sect;
+       unsigned char *data;
+       struct dkblk0 *b;
+       struct slice *slice;
+
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
+               return -1;
+
+       b = (struct dkblk0 *)data;
+       if (memcmp(b->dk_vid.vid_mac, "MOTOROLA", sizeof(b->dk_vid.vid_mac))) {
+               put_dev_sector(sect);
+               return 0;
+       }
+       slices = be16_to_cpu(b->dk_ios.ios_slccnt);
+       i = be32_to_cpu(b->dk_ios.ios_slcblk);
+       put_dev_sector(sect);
+
+       data = read_dev_sector(bdev, i, &sect);
+       if (!data)
+               return -1;
+
+       slices -= 1; /* last slice is the whole disk */
+       printk("sysV68: %s(s%u)", state->name, slices);
+       slice = (struct slice *)data;
+       for (i = 0; i < slices; i++, slice++) {
+               if (slot == state->limit)
+                       break;
+               if (be32_to_cpu(slice->nblocks)) {
+                       put_partition(state, slot,
+                               be32_to_cpu(slice->blkoff),
+                               be32_to_cpu(slice->nblocks));
+                       printk("(s%u)", i);
+               }
+               slot++;
+       }
+       printk("\n");
+       put_dev_sector(sect);
+       return 1;
+}
diff --git a/fs/partitions/sysv68.h b/fs/partitions/sysv68.h
new file mode 100644 (file)
index 0000000..fa733f6
--- /dev/null
@@ -0,0 +1 @@
+extern int sysv68_partition(struct parsed_partitions *state, struct block_device *bdev);
index ebafde7d6abab948f9fa3a23e71f39360c757c71..3a89592bdf577930b4c1698c4811261aa467cbf2 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -841,8 +841,18 @@ static int pipefs_delete_dentry(struct dentry *dentry)
        return 0;
 }
 
+/*
+ * pipefs_dname() is called from d_path().
+ */
+static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+       return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
+                               dentry->d_inode->i_ino);
+}
+
 static struct dentry_operations pipefs_dentry_operations = {
        .d_delete       = pipefs_delete_dentry,
+       .d_dname        = pipefs_dname,
 };
 
 static struct inode * get_pipe_inode(void)
@@ -888,8 +898,7 @@ struct file *create_write_pipe(void)
        struct inode *inode;
        struct file *f;
        struct dentry *dentry;
-       char name[32];
-       struct qstr this;
+       struct qstr name = { .name = "" };
 
        f = get_empty_filp();
        if (!f)
@@ -899,11 +908,8 @@ struct file *create_write_pipe(void)
        if (!inode)
                goto err_file;
 
-       this.len = sprintf(name, "[%lu]", inode->i_ino);
-       this.name = name;
-       this.hash = 0;
        err = -ENOMEM;
-       dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
+       dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
        if (!dentry)
                goto err_inode;
 
index 56aacead836284b7577ad9146aed46582c592a5f..89940f243fc235d2f2f8d9abf27e5b0f6862cd52 100644 (file)
@@ -59,7 +59,7 @@ static int do_make_slave(struct vfsmount *mnt)
        } else {
                struct list_head *p = &mnt->mnt_slave_list;
                while (!list_empty(p)) {
-                        slave_mnt = list_entry(p->next,
+                        slave_mnt = list_first_entry(p,
                                        struct vfsmount, mnt_slave);
                        list_del_init(&slave_mnt->mnt_slave);
                        slave_mnt->mnt_master = NULL;
index 07c9cdbcdcac6f6a2be5fa40f97a340b2f5980a4..74f30e0c0381041d95fc3657077dd22ab3466105 100644 (file)
@@ -410,9 +410,9 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        /* convert nsec -> ticks */
        start_time = nsec_to_clock_t(start_time);
 
-       res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
+       res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n",
                task->pid,
                tcomm,
                state,
index ec158dd02b3ac2b758fbbf527820c1f0f83a486a..a5fa1fdafc4e6df68df2cc87626f0d8d85bd95a6 100644 (file)
@@ -61,9 +61,9 @@
 #include <linux/namei.h>
 #include <linux/mnt_namespace.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/rcupdate.h>
 #include <linux/kallsyms.h>
+#include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
@@ -90,8 +90,8 @@
 #define PROC_NUMBUF 13
 
 struct pid_entry {
-       int len;
        char *name;
+       int len;
        mode_t mode;
        const struct inode_operations *iop;
        const struct file_operations *fop;
@@ -99,8 +99,8 @@ struct pid_entry {
 };
 
 #define NOD(NAME, MODE, IOP, FOP, OP) {                        \
-       .len  = sizeof(NAME) - 1,                       \
        .name = (NAME),                                 \
+       .len  = sizeof(NAME) - 1,                       \
        .mode = MODE,                                   \
        .iop  = IOP,                                    \
        .fop  = FOP,                                    \
@@ -123,6 +123,9 @@ struct pid_entry {
                NULL, &proc_info_file_operations,       \
                { .proc_read = &proc_##OTYPE } )
 
+int maps_protect;
+EXPORT_SYMBOL(maps_protect);
+
 static struct fs_struct *get_fs_struct(struct task_struct *task)
 {
        struct fs_struct *fs;
@@ -275,17 +278,15 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
  */
 static int proc_pid_wchan(struct task_struct *task, char *buffer)
 {
-       char *modname;
-       const char *sym_name;
-       unsigned long wchan, size, offset;
-       char namebuf[KSYM_NAME_LEN+1];
+       unsigned long wchan;
+       char symname[KSYM_NAME_LEN+1];
 
        wchan = get_wchan(task);
 
-       sym_name = kallsyms_lookup(wchan, &size, &offset, &modname, namebuf);
-       if (sym_name)
-               return sprintf(buffer, "%s", sym_name);
-       return sprintf(buffer, "%lu", wchan);
+       if (lookup_symbol_name(wchan, symname) < 0)
+               return sprintf(buffer, "%lu", wchan);
+       else
+               return sprintf(buffer, "%s", symname);
 }
 #endif /* CONFIG_KALLSYMS */
 
@@ -310,7 +311,9 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
        struct timespec uptime;
 
        do_posix_clock_monotonic_gettime(&uptime);
+       read_lock(&tasklist_lock);
        points = badness(task, uptime.tv_sec);
+       read_unlock(&tasklist_lock);
        return sprintf(buffer, "%lu\n", points);
 }
 
@@ -344,11 +347,8 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr)
                return -EPERM;
 
        error = inode_change_ok(inode, attr);
-       if (!error) {
-               error = security_inode_setattr(dentry, attr);
-               if (!error)
-                       error = inode_setattr(inode, attr);
-       }
+       if (!error)
+               error = inode_setattr(inode, attr);
        return error;
 }
 
@@ -660,7 +660,6 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf,
        char buffer[PROC_NUMBUF];
        size_t len;
        int oom_adjust;
-       loff_t __ppos = *ppos;
 
        if (!task)
                return -ESRCH;
@@ -668,14 +667,8 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf,
        put_task_struct(task);
 
        len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust);
-       if (__ppos >= len)
-               return 0;
-       if (count > len-__ppos)
-               count = len-__ppos;
-       if (copy_to_user(buf, buffer + __ppos, count))
-               return -EFAULT;
-       *ppos = __ppos + count;
-       return count;
+
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
 }
 
 static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
@@ -715,6 +708,7 @@ static const struct file_operations proc_oom_adjust_operations = {
        .write          = oom_adjust_write,
 };
 
+#ifdef CONFIG_MMU
 static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
 {
@@ -748,6 +742,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 static struct file_operations proc_clear_refs_operations = {
        .write          = clear_refs_write,
 };
+#endif
 
 #ifdef CONFIG_AUDITSYSCALL
 #define TMPBUFLEN 21
@@ -823,7 +818,6 @@ static ssize_t seccomp_read(struct file *file, char __user *buf,
 {
        struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
        char __buf[20];
-       loff_t __ppos = *ppos;
        size_t len;
 
        if (!tsk)
@@ -831,14 +825,8 @@ static ssize_t seccomp_read(struct file *file, char __user *buf,
        /* no need to print the trailing zero, so use only len */
        len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
        put_task_struct(tsk);
-       if (__ppos >= len)
-               return 0;
-       if (count > len - __ppos)
-               count = len - __ppos;
-       if (copy_to_user(buf, __buf + __ppos, count))
-               return -EFAULT;
-       *ppos = __ppos + count;
-       return count;
+
+       return simple_read_from_buffer(buf, count, ppos, __buf, len);
 }
 
 static ssize_t seccomp_write(struct file *file, const char __user *buf,
@@ -897,7 +885,6 @@ static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
        char buffer[PROC_NUMBUF];
        size_t len;
        int make_it_fail;
-       loff_t __ppos = *ppos;
 
        if (!task)
                return -ESRCH;
@@ -905,14 +892,8 @@ static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
        put_task_struct(task);
 
        len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);
-       if (__ppos >= len)
-               return 0;
-       if (count > len-__ppos)
-               count = len-__ppos;
-       if (copy_to_user(buf, buffer + __ppos, count))
-               return -EFAULT;
-       *ppos = __ppos + count;
-       return count;
+
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
 }
 
 static ssize_t proc_fault_inject_write(struct file * file,
@@ -975,7 +956,7 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
 
        if (!tmp)
                return -ENOMEM;
-               
+
        inode = dentry->d_inode;
        path = d_path(dentry, mnt, tmp, PAGE_SIZE);
        len = PTR_ERR(path);
@@ -1155,7 +1136,8 @@ static struct dentry_operations pid_dentry_operations =
 
 /* Lookups */
 
-typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *);
+typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
+                               struct task_struct *, const void *);
 
 /*
  * Fill a directory entry.
@@ -1171,7 +1153,7 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct tas
  */
 static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        char *name, int len,
-       instantiate_t instantiate, struct task_struct *task, void *ptr)
+       instantiate_t instantiate, struct task_struct *task, const void *ptr)
 {
        struct dentry *child, *dir = filp->f_path.dentry;
        struct inode *inode;
@@ -1233,7 +1215,10 @@ out:
        return ~0U;
 }
 
-static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+#define PROC_FDINFO_MAX 64
+
+static int proc_fd_info(struct inode *inode, struct dentry **dentry,
+                       struct vfsmount **mnt, char *info)
 {
        struct task_struct *task = get_proc_task(inode);
        struct files_struct *files = NULL;
@@ -1252,8 +1237,16 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
-                       *mnt = mntget(file->f_path.mnt);
-                       *dentry = dget(file->f_path.dentry);
+                       if (mnt)
+                               *mnt = mntget(file->f_path.mnt);
+                       if (dentry)
+                               *dentry = dget(file->f_path.dentry);
+                       if (info)
+                               snprintf(info, PROC_FDINFO_MAX,
+                                        "pos:\t%lli\n"
+                                        "flags:\t0%o\n",
+                                        (long long) file->f_pos,
+                                        file->f_flags);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
@@ -1264,6 +1257,12 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
        return -ENOENT;
 }
 
+static int proc_fd_link(struct inode *inode, struct dentry **dentry,
+                       struct vfsmount **mnt)
+{
+       return proc_fd_info(inode, dentry, mnt, NULL);
+}
+
 static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
@@ -1306,9 +1305,9 @@ static struct dentry_operations tid_fd_dentry_operations =
 };
 
 static struct dentry *proc_fd_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, void *ptr)
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
-       unsigned fd = *(unsigned *)ptr;
+       unsigned fd = *(const unsigned *)ptr;
        struct file *file;
        struct files_struct *files;
        struct inode *inode;
@@ -1359,7 +1358,9 @@ out_iput:
        goto out;
 }
 
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_lookupfd_common(struct inode *dir,
+                                          struct dentry *dentry,
+                                          instantiate_t instantiate)
 {
        struct task_struct *task = get_proc_task(dir);
        unsigned fd = name_to_int(dentry);
@@ -1370,23 +1371,15 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
        if (fd == ~0U)
                goto out;
 
-       result = proc_fd_instantiate(dir, dentry, task, &fd);
+       result = instantiate(dir, dentry, task, &fd);
 out:
        put_task_struct(task);
 out_no_task:
        return result;
 }
 
-static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-       struct task_struct *task, int fd)
-{
-       char name[PROC_NUMBUF];
-       int len = snprintf(name, sizeof(name), "%d", fd);
-       return proc_fill_cache(filp, dirent, filldir, name, len,
-                               proc_fd_instantiate, task, &fd);
-}
-
-static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
+static int proc_readfd_common(struct file * filp, void * dirent,
+                             filldir_t filldir, instantiate_t instantiate)
 {
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
@@ -1422,12 +1415,17 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
                        for (fd = filp->f_pos-2;
                             fd < fdt->max_fds;
                             fd++, filp->f_pos++) {
+                               char name[PROC_NUMBUF];
+                               int len;
 
                                if (!fcheck_files(files, fd))
                                        continue;
                                rcu_read_unlock();
 
-                               if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) {
+                               len = snprintf(name, sizeof(name), "%d", fd);
+                               if (proc_fill_cache(filp, dirent, filldir,
+                                                   name, len, instantiate,
+                                                   p, &fd) < 0) {
                                        rcu_read_lock();
                                        break;
                                }
@@ -1442,23 +1440,119 @@ out_no_task:
        return retval;
 }
 
+static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
+                                   struct nameidata *nd)
+{
+       return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
+}
+
+static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
+{
+       return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
+}
+
+static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
+                                     size_t len, loff_t *ppos)
+{
+       char tmp[PROC_FDINFO_MAX];
+       int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, NULL, tmp);
+       if (!err)
+               err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
+       return err;
+}
+
+static const struct file_operations proc_fdinfo_file_operations = {
+       .open           = nonseekable_open,
+       .read           = proc_fdinfo_read,
+};
+
 static const struct file_operations proc_fd_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_readfd,
 };
 
+/*
+ * /proc/pid/fd needs a special permission handler so that a process can still
+ * access /proc/self/fd after it has executed a setuid().
+ */
+static int proc_fd_permission(struct inode *inode, int mask,
+                               struct nameidata *nd)
+{
+       int rv;
+
+       rv = generic_permission(inode, mask, NULL);
+       if (rv == 0)
+               return 0;
+       if (task_pid(current) == proc_pid(inode))
+               rv = 0;
+       return rv;
+}
+
 /*
  * proc directories can do almost nothing..
  */
 static const struct inode_operations proc_fd_inode_operations = {
        .lookup         = proc_lookupfd,
+       .permission     = proc_fd_permission,
+       .setattr        = proc_setattr,
+};
+
+static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
+{
+       unsigned fd = *(unsigned *)ptr;
+       struct inode *inode;
+       struct proc_inode *ei;
+       struct dentry *error = ERR_PTR(-ENOENT);
+
+       inode = proc_pid_make_inode(dir->i_sb, task);
+       if (!inode)
+               goto out;
+       ei = PROC_I(inode);
+       ei->fd = fd;
+       inode->i_mode = S_IFREG | S_IRUSR;
+       inode->i_fop = &proc_fdinfo_file_operations;
+       dentry->d_op = &tid_fd_dentry_operations;
+       d_add(dentry, inode);
+       /* Close the race of the process dying before we return the dentry */
+       if (tid_fd_revalidate(dentry, NULL))
+               error = NULL;
+
+ out:
+       return error;
+}
+
+static struct dentry *proc_lookupfdinfo(struct inode *dir,
+                                       struct dentry *dentry,
+                                       struct nameidata *nd)
+{
+       return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
+}
+
+static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
+{
+       return proc_readfd_common(filp, dirent, filldir,
+                                 proc_fdinfo_instantiate);
+}
+
+static const struct file_operations proc_fdinfo_operations = {
+       .read           = generic_read_dir,
+       .readdir        = proc_readfdinfo,
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+static const struct inode_operations proc_fdinfo_inode_operations = {
+       .lookup         = proc_lookupfdinfo,
        .setattr        = proc_setattr,
 };
 
+
 static struct dentry *proc_pident_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, void *ptr)
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
-       struct pid_entry *p = ptr;
+       const struct pid_entry *p = ptr;
        struct inode *inode;
        struct proc_inode *ei;
        struct dentry *error = ERR_PTR(-EINVAL);
@@ -1487,13 +1581,13 @@ out:
 
 static struct dentry *proc_pident_lookup(struct inode *dir, 
                                         struct dentry *dentry,
-                                        struct pid_entry *ents,
+                                        const struct pid_entry *ents,
                                         unsigned int nents)
 {
        struct inode *inode;
        struct dentry *error;
        struct task_struct *task = get_proc_task(dir);
-       struct pid_entry *p, *last;
+       const struct pid_entry *p, *last;
 
        error = ERR_PTR(-ENOENT);
        inode = NULL;
@@ -1522,8 +1616,8 @@ out_no_task:
        return error;
 }
 
-static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-       struct task_struct *task, struct pid_entry *p)
+static int proc_pident_fill_cache(struct file *filp, void *dirent,
+       filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
 {
        return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
                                proc_pident_instantiate, task, p);
@@ -1531,14 +1625,14 @@ static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t fil
 
 static int proc_pident_readdir(struct file *filp,
                void *dirent, filldir_t filldir,
-               struct pid_entry *ents, unsigned int nents)
+               const struct pid_entry *ents, unsigned int nents)
 {
        int i;
        int pid;
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
-       struct pid_entry *p, *last;
+       const struct pid_entry *p, *last;
        ino_t ino;
        int ret;
 
@@ -1653,7 +1747,7 @@ static const struct file_operations proc_pid_attr_operations = {
        .write          = proc_pid_attr_write,
 };
 
-static struct pid_entry attr_dir_stuff[] = {
+static const struct pid_entry attr_dir_stuff[] = {
        REG("current",    S_IRUGO|S_IWUGO, pid_attr),
        REG("prev",       S_IRUGO,         pid_attr),
        REG("exec",       S_IRUGO|S_IWUGO, pid_attr),
@@ -1719,7 +1813,7 @@ static const struct inode_operations proc_self_inode_operations = {
  * that properly belong to the /proc filesystem, as they describe
  * describe something that is process related.
  */
-static struct pid_entry proc_base_stuff[] = {
+static const struct pid_entry proc_base_stuff[] = {
        NOD("self", S_IFLNK|S_IRWXUGO,
                &proc_self_inode_operations, NULL, {}),
 };
@@ -1748,9 +1842,9 @@ static struct dentry_operations proc_base_dentry_operations =
 };
 
 static struct dentry *proc_base_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, void *ptr)
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
-       struct pid_entry *p = ptr;
+       const struct pid_entry *p = ptr;
        struct inode *inode;
        struct proc_inode *ei;
        struct dentry *error = ERR_PTR(-EINVAL);
@@ -1798,7 +1892,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
 {
        struct dentry *error;
        struct task_struct *task = get_proc_task(dir);
-       struct pid_entry *p, *last;
+       const struct pid_entry *p, *last;
 
        error = ERR_PTR(-ENOENT);
 
@@ -1824,8 +1918,8 @@ out_no_task:
        return error;
 }
 
-static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-       struct task_struct *task, struct pid_entry *p)
+static int proc_base_fill_cache(struct file *filp, void *dirent,
+       filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
 {
        return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
                                proc_base_instantiate, task, p);
@@ -1862,9 +1956,10 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
 static const struct file_operations proc_task_operations;
 static const struct inode_operations proc_task_inode_operations;
 
-static struct pid_entry tgid_base_stuff[] = {
+static const struct pid_entry tgid_base_stuff[] = {
        DIR("task",       S_IRUGO|S_IXUGO, task),
        DIR("fd",         S_IRUSR|S_IXUSR, fd),
+       DIR("fdinfo",     S_IRUSR|S_IXUSR, fdinfo),
        INF("environ",    S_IRUSR, pid_environ),
        INF("auxv",       S_IRUSR, pid_auxv),
        INF("status",     S_IRUGO, pid_status),
@@ -2005,7 +2100,7 @@ out:
 
 static struct dentry *proc_pid_instantiate(struct inode *dir,
                                           struct dentry * dentry,
-                                          struct task_struct *task, void *ptr)
+                                          struct task_struct *task, const void *ptr)
 {
        struct dentry *error = ERR_PTR(-ENOENT);
        struct inode *inode;
@@ -2018,7 +2113,7 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
        inode->i_op = &proc_tgid_base_inode_operations;
        inode->i_fop = &proc_tgid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
-       inode->i_nlink = 4;
+       inode->i_nlink = 5;
 #ifdef CONFIG_SECURITY
        inode->i_nlink += 1;
 #endif
@@ -2120,7 +2215,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
                goto out_no_task;
 
        for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) {
-               struct pid_entry *p = &proc_base_stuff[nr];
+               const struct pid_entry *p = &proc_base_stuff[nr];
                if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
                        goto out;
        }
@@ -2146,8 +2241,9 @@ out_no_task:
 /*
  * Tasks
  */
-static struct pid_entry tid_base_stuff[] = {
+static const struct pid_entry tid_base_stuff[] = {
        DIR("fd",        S_IRUSR|S_IXUSR, fd),
+       DIR("fdinfo",    S_IRUSR|S_IXUSR, fdinfo),
        INF("environ",   S_IRUSR, pid_environ),
        INF("auxv",      S_IRUSR, pid_auxv),
        INF("status",    S_IRUGO, pid_status),
@@ -2216,7 +2312,7 @@ static const struct inode_operations proc_tid_base_inode_operations = {
 };
 
 static struct dentry *proc_task_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, void *ptr)
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
        struct dentry *error = ERR_PTR(-ENOENT);
        struct inode *inode;
@@ -2228,7 +2324,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
        inode->i_op = &proc_tid_base_inode_operations;
        inode->i_fop = &proc_tid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
-       inode->i_nlink = 3;
+       inode->i_nlink = 4;
 #ifdef CONFIG_SECURITY
        inode->i_nlink += 1;
 #endif
index 775fb21294d821419ed6b7e0939d963dd6d00e87..8a40e15f5ecb90333f7eca84ede39c40e7adb945 100644 (file)
@@ -398,6 +398,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
                        if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
                                unsigned int ino = de->low_ino;
 
+                               de_get(de);
                                spin_unlock(&proc_subdir_lock);
                                error = -EINVAL;
                                inode = proc_get_inode(dir->i_sb, ino, de);
@@ -414,6 +415,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
                d_add(dentry, inode);
                return NULL;
        }
+       de_put(de);
        return ERR_PTR(error);
 }
 
@@ -476,14 +478,21 @@ int proc_readdir(struct file * filp,
                        }
 
                        do {
+                               struct proc_dir_entry *next;
+
                                /* filldir passes info to user space */
+                               de_get(de);
                                spin_unlock(&proc_subdir_lock);
                                if (filldir(dirent, de->name, de->namelen, filp->f_pos,
-                                           de->low_ino, de->mode >> 12) < 0)
+                                           de->low_ino, de->mode >> 12) < 0) {
+                                       de_put(de);
                                        goto out;
+                               }
                                spin_lock(&proc_subdir_lock);
                                filp->f_pos++;
-                               de = de->next;
+                               next = de->next;
+                               de_put(de);
+                               de = next;
                        } while (de);
                        spin_unlock(&proc_subdir_lock);
        }
index 22b1158389aed97d50044b64ac2b1383706d7923..b8171907c83b64e30ce98bf6553c7feff60768e1 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "internal.h"
 
-static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
+struct proc_dir_entry *de_get(struct proc_dir_entry *de)
 {
        if (de)
                atomic_inc(&de->count);
@@ -31,7 +31,7 @@ static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
 /*
  * Decrements the use count and checks for deferred deletion.
  */
-static void de_put(struct proc_dir_entry *de)
+void de_put(struct proc_dir_entry *de)
 {
        if (de) {       
                lock_kernel();          
@@ -146,13 +146,6 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 {
        struct inode * inode;
 
-       /*
-        * Increment the use count so the dir entry can't disappear.
-        */
-       de_get(de);
-
-       WARN_ON(de && de->deleted);
-
        if (de != NULL && !try_module_get(de->owner))
                goto out_mod;
 
@@ -184,7 +177,6 @@ out_ino:
        if (de != NULL)
                module_put(de->owner);
 out_mod:
-       de_put(de);
        return NULL;
 }                      
 
@@ -199,6 +191,7 @@ int proc_fill_super(struct super_block *s, void *data, int silent)
        s->s_op = &proc_sops;
        s->s_time_gran = 1;
        
+       de_get(&proc_root);
        root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
        if (!root_inode)
                goto out_no_root;
@@ -212,6 +205,7 @@ int proc_fill_super(struct super_block *s, void *data, int silent)
 out_no_root:
        printk("proc_read_super: get root inode failed\n");
        iput(root_inode);
+       de_put(&proc_root);
        return -ENOMEM;
 }
 MODULE_LICENSE("GPL");
index f771889183c36fe52062267ffde5d139ca18c76b..b215c3524fa685c572c874966128241d6747e9dd 100644 (file)
@@ -37,6 +37,8 @@ do {                                          \
 extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
 #endif
 
+extern int maps_protect;
+
 extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
 extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **);
 extern int proc_tid_stat(struct task_struct *,  char *);
index 75ec6523d29aeb746d51bbce79b178c0e8015e11..5fd49e47f83a7c8a1d20ee07d6d6e13d0df9d6ab 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/signal.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/times.h>
 #include <linux/profile.h>
@@ -429,18 +428,11 @@ static int slabstats_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static int slabstats_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *m = file->private_data;
-       kfree(m->private);
-       return seq_release(inode, file);
-}
-
 static const struct file_operations proc_slabstats_operations = {
        .open           = slabstats_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = slabstats_release,
+       .release        = seq_release_private,
 };
 #endif
 #endif
index 20e8cbb34364e0b18106c690c65d91962c5d76c1..680c429bfa223e67f6097a4636f28e8efdd20d60 100644 (file)
@@ -429,11 +429,8 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
                return -EPERM;
 
        error = inode_change_ok(inode, attr);
-       if (!error) {
-               error = security_inode_setattr(dentry, attr);
-               if (!error)
-                       error = inode_setattr(inode, attr);
-       }
+       if (!error)
+               error = inode_setattr(inode, attr);
 
        return error;
 }
index c1bbfbeb035e4e5b72a9eb64a1bdb507496b93ce..b3a473b0a191a41d9b27fab13b9990fdc7c9463f 100644 (file)
@@ -108,6 +108,8 @@ static void *t_start(struct seq_file *m, loff_t *pos)
 {
        struct list_head *p;
        loff_t l = *pos;
+
+       mutex_lock(&tty_mutex);
        list_for_each(p, &tty_drivers)
                if (!l--)
                        return list_entry(p, struct tty_driver, tty_drivers);
@@ -124,6 +126,7 @@ static void *t_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void t_stop(struct seq_file *m, void *v)
 {
+       mutex_unlock(&tty_mutex);
 }
 
 static struct seq_operations tty_drivers_op = {
index 4008c060f7ef1b2b9ddc51154d30e1ec865906a5..c24d81a5a040e2a91825673434339e3c2f1dcdda 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/highmem.h>
+#include <linux/ptrace.h>
 #include <linux/pagemap.h>
 #include <linux/mempolicy.h>
 
@@ -142,6 +143,9 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
        dev_t dev = 0;
        int len;
 
+       if (maps_protect && !ptrace_may_attach(task))
+               return -EACCES;
+
        if (file) {
                struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
                dev = inode->i_sb->s_dev;
@@ -512,11 +516,22 @@ const struct file_operations proc_maps_operations = {
 #ifdef CONFIG_NUMA
 extern int show_numa_map(struct seq_file *m, void *v);
 
+static int show_numa_map_checked(struct seq_file *m, void *v)
+{
+       struct proc_maps_private *priv = m->private;
+       struct task_struct *task = priv->task;
+
+       if (maps_protect && !ptrace_may_attach(task))
+               return -EACCES;
+
+       return show_numa_map(m, v);
+}
+
 static struct seq_operations proc_pid_numa_maps_op = {
         .start  = m_start,
         .next   = m_next,
         .stop   = m_stop,
-        .show   = show_numa_map
+        .show   = show_numa_map_checked
 };
 
 static int numa_maps_open(struct inode *inode, struct file *file)
index 7cddf6b8635aa612362042e4b3609a270a61555c..d8b8c7183c243d86455390f1246da6c12891d396 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/mount.h>
+#include <linux/ptrace.h>
 #include <linux/seq_file.h>
 #include "internal.h"
 
@@ -143,6 +144,12 @@ out:
 static int show_map(struct seq_file *m, void *_vml)
 {
        struct vm_list_struct *vml = _vml;
+       struct proc_maps_private *priv = m->private;
+       struct task_struct *task = priv->task;
+
+       if (maps_protect && !ptrace_may_attach(task))
+               return -EACCES;
+
        return nommu_vma_show(m, vml->vma);
 }
 
index b9dae76a0b6e2212083efa9ca0281e31661c0375..e9d88fd0eca8f48917871653fd489bdb5d28b554 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/current.h>
 #include <asm/uaccess.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
index d3fd7c6732d289ba8aa46a6452e9c35a5156ad0a..3b481d557edbd01df82c18d5cbef6386fa862bf1 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/ramfs.h>
 #include <linux/quotaops.h>
index ff1f7639707b13c74f90737cf7db579050f2e04e..4ace5d72eae16498a1a2f942f92907655e1258e6 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/ramfs.h>
 
index 1f8dc373ede7755124a0d5da510f05beb7ce784f..4d03008f015b9ae6d2565cdbc179d034687c3d08 100644 (file)
@@ -37,10 +37,10 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
 
        mutex_lock(&inode->i_mutex);
        switch (origin) {
-               case 2:
+               case SEEK_END:
                        offset += inode->i_size;
                        break;
-               case 1:
+               case SEEK_CUR:
                        offset += file->f_pos;
        }
        retval = -EINVAL;
@@ -63,10 +63,10 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
 
        lock_kernel();
        switch (origin) {
-               case 2:
+               case SEEK_END:
                        offset += i_size_read(file->f_path.dentry->d_inode);
                        break;
-               case 1:
+               case SEEK_CUR:
                        offset += file->f_pos;
        }
        retval = -EINVAL;
@@ -94,10 +94,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
 
        lock_kernel();
        switch (origin) {
-               case 2:
+               case SEEK_END:
                        offset += i_size_read(file->f_path.dentry->d_inode);
                        break;
-               case 1:
+               case SEEK_CUR:
                        offset += file->f_pos;
        }
        retval = -EINVAL;
@@ -139,7 +139,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
                goto bad;
 
        retval = -EINVAL;
-       if (origin <= 2) {
+       if (origin <= SEEK_MAX) {
                loff_t res = vfs_llseek(file, offset, origin);
                retval = res;
                if (res != (loff_t)retval)
@@ -166,7 +166,7 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
                goto bad;
 
        retval = -EINVAL;
-       if (origin > 2)
+       if (origin > SEEK_MAX)
                goto out_putf;
 
        offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
index f39f5b3132527243a5eb08979d7bf5aebaaa9f15..efe52e67657719963d5ac1cd22df34e7465d4234 100644 (file)
@@ -4,13 +4,13 @@
  *  Copyright (C) 1995  Linus Torvalds
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/dirent.h>
 #include <linux/security.h>
@@ -52,7 +52,6 @@ EXPORT_SYMBOL(vfs_readdir);
  * case (the low-level handlers don't need to care about this).
  */
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 
 #ifdef __ARCH_WANT_OLD_READDIR
 
@@ -147,7 +146,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
        struct linux_dirent __user * dirent;
        struct getdents_callback * buf = (struct getdents_callback *) __buf;
        unsigned long d_ino;
-       int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
+       int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(long));
 
        buf->error = -EINVAL;   /* only used if we fail.. */
        if (reclen > buf->count)
@@ -220,8 +219,6 @@ out:
        return error;
 }
 
-#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
-
 struct getdents_callback64 {
        struct linux_dirent64 __user * current_dir;
        struct linux_dirent64 __user * previous;
@@ -234,7 +231,7 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
 {
        struct linux_dirent64 __user *dirent;
        struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf;
-       int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1);
+       int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(u64));
 
        buf->error = -EINVAL;   /* only used if we fail.. */
        if (reclen > buf->count)
index 96a2f8889da3a52073805b013cccb6223f706df5..9c23fee3bae9b678d4d3cd6bbca538e07aa3599d 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/fs.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/stat.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 
index abfada2f52db7b2a54f282d968e3a634199df0ad..9e451a68580f6eef3ab4ba8c6eb729ae843d071b 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
@@ -1060,20 +1059,12 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
           maping blocks, since there is none, so we just zero out remaining
           parts of first and last pages in write area (if needed) */
        if ((pos & ~((loff_t) PAGE_CACHE_SIZE - 1)) > inode->i_size) {
-               if (from != 0) {        /* First page needs to be partially zeroed */
-                       char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
-                       memset(kaddr, 0, from);
-                       kunmap_atomic(kaddr, KM_USER0);
-                       flush_dcache_page(prepared_pages[0]);
-               }
-               if (to != PAGE_CACHE_SIZE) {    /* Last page needs to be partially zeroed */
-                       char *kaddr =
-                           kmap_atomic(prepared_pages[num_pages - 1],
-                                       KM_USER0);
-                       memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
-                       kunmap_atomic(kaddr, KM_USER0);
-                       flush_dcache_page(prepared_pages[num_pages - 1]);
-               }
+               if (from != 0)          /* First page needs to be partially zeroed */
+                       zero_user_page(prepared_pages[0], 0, from, KM_USER0);
+
+               if (to != PAGE_CACHE_SIZE)      /* Last page needs to be partially zeroed */
+                       zero_user_page(prepared_pages[num_pages-1], to,
+                                       PAGE_CACHE_SIZE - to, KM_USER0);
 
                /* Since all blocks are new - use already calculated value */
                return blocks;
@@ -1200,13 +1191,9 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        ll_rw_block(READ, 1, &bh);
                                        *wait_bh++ = bh;
                                } else {        /* Not mapped, zero it */
-                                       char *kaddr =
-                                           kmap_atomic(prepared_pages[0],
-                                                       KM_USER0);
-                                       memset(kaddr + block_start, 0,
-                                              from - block_start);
-                                       kunmap_atomic(kaddr, KM_USER0);
-                                       flush_dcache_page(prepared_pages[0]);
+                                       zero_user_page(prepared_pages[0],
+                                                      block_start,
+                                                      from - block_start, KM_USER0);
                                        set_buffer_uptodate(bh);
                                }
                        }
@@ -1238,13 +1225,8 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        ll_rw_block(READ, 1, &bh);
                                        *wait_bh++ = bh;
                                } else {        /* Not mapped, zero it */
-                                       char *kaddr =
-                                           kmap_atomic(prepared_pages
-                                                       [num_pages - 1],
-                                                       KM_USER0);
-                                       memset(kaddr + to, 0, block_end - to);
-                                       kunmap_atomic(kaddr, KM_USER0);
-                                       flush_dcache_page(prepared_pages[num_pages - 1]);
+                                       zero_user_page(prepared_pages[num_pages-1],
+                                                       to, block_end - to, KM_USER0);
                                        set_buffer_uptodate(bh);
                                }
                        }
index 9fcbfe3169776516162b7a68bfbf845975adb639..1272d11399fb26509f60eef52561b12002a8ecee 100644 (file)
@@ -2148,13 +2148,8 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
                length = offset & (blocksize - 1);
                /* if we are not on a block boundary */
                if (length) {
-                       char *kaddr;
-
                        length = blocksize - length;
-                       kaddr = kmap_atomic(page, KM_USER0);
-                       memset(kaddr + offset, 0, length);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
+                       zero_user_page(page, offset, length, KM_USER0);
                        if (buffer_mapped(bh) && bh->b_blocknr != 0) {
                                mark_buffer_dirty(bh);
                        }
@@ -2370,7 +2365,6 @@ static int reiserfs_write_full_page(struct page *page,
         ** last byte in the file
         */
        if (page->index >= end_index) {
-               char *kaddr;
                unsigned last_offset;
 
                last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
@@ -2379,10 +2373,7 @@ static int reiserfs_write_full_page(struct page *page,
                        unlock_page(page);
                        return 0;
                }
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE - last_offset);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_page(page, last_offset, PAGE_CACHE_SIZE - last_offset, KM_USER0);
        }
        bh = head;
        block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
index 7280a23ef3444aa4b8370dcb99b8ee46ee246dec..f25086aeef5f450afa6c4aa604787cd168ae299f 100644 (file)
@@ -1110,7 +1110,7 @@ static int flush_commit_list(struct super_block *s,
        if (!barrier) {
                /* If there was a write error in the journal - we can't commit
                 * this transaction - it will be invalid and, if successful,
-                * will just end up propogating the write error out to
+                * will just end up propagating the write error out to
                 * the file system. */
                if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
                        if (buffer_dirty(jl->j_commit_bh))
@@ -1125,7 +1125,7 @@ static int flush_commit_list(struct super_block *s,
 
        /* If there was a write error in the journal - we can't commit this
         * transaction - it will be invalid and, if successful, will just end
-        * up propogating the write error out to the filesystem. */
+        * up propagating the write error out to the filesystem. */
        if (unlikely(!buffer_uptodate(jl->j_commit_bh))) {
 #ifdef CONFIG_REISERFS_CHECK
                reiserfs_warning(s, "journal-615: buffer write failed");
@@ -2918,7 +2918,7 @@ static void queue_log_writer(struct super_block *s)
        set_current_state(TASK_UNINTERRUPTIBLE);
        if (test_bit(J_WRITERS_QUEUED, &journal->j_state))
                schedule();
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&journal->j_join_wait, &wait);
 }
 
index a2161840bc7c00837e36c6446cb6cf5623f2a5da..b378eea332caefaaf069e91f75db339cc6c9b3b2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
-#include <linux/smp_lock.h>
 #include <linux/quotaops.h>
 
 #define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
index ecc9943202fc571a45d43a511434db39e7f24e5b..9aa7a06e093f0a8bd6b48016387ef41128d4b92a 100644 (file)
 #include <asm/uaccess.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_fs_sb.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
-#if defined( REISERFS_PROC_INFO )
+#ifdef CONFIG_REISERFS_PROC_INFO
 
 /*
  * LOCKING:
index 315684793d1d8d0ff6b61ec08c4e9a5e4dc75d22..976cc7887a0dfe60c4f5933e7d7757acfb6cf8bf 100644 (file)
@@ -131,6 +131,10 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
                        /* don't use read_bitmap_block since it will cache
                         * the uninitialized bitmap */
                        bh = sb_bread(s, i * s->s_blocksize * 8);
+                       if (!bh) {
+                               vfree(bitmap);
+                               return -EIO;
+                       }
                        memset(bh->b_data, 0, sb_blocksize(sb));
                        reiserfs_test_and_set_le_bit(0, bh->b_data);
                        reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
index afb21ea45302a728936a27dc1b568e9eb04c1186..b6f12593c39dd76a1cd2002c93466a9370f04957 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/reiserfs_fs.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/quotaops.h>
 
index 7054aaef049312b82239b34be4dd5a09ebd70b4a..c7762140c4258a3ef8c867236a25da67ad38e51f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
@@ -433,12 +432,13 @@ int remove_save_link(struct inode *inode, int truncate)
 static void reiserfs_kill_sb(struct super_block *s)
 {
        if (REISERFS_SB(s)) {
+#ifdef CONFIG_REISERFS_FS_XATTR
                if (REISERFS_SB(s)->xattr_root) {
                        d_invalidate(REISERFS_SB(s)->xattr_root);
                        dput(REISERFS_SB(s)->xattr_root);
                        REISERFS_SB(s)->xattr_root = NULL;
                }
-
+#endif
                if (REISERFS_SB(s)->priv_root) {
                        d_invalidate(REISERFS_SB(s)->priv_root);
                        dput(REISERFS_SB(s)->priv_root);
@@ -1562,9 +1562,10 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
        /* Preallocate by 16 blocks (17-1) at once */
        REISERFS_SB(s)->s_alloc_options.preallocsize = 17;
+#ifdef CONFIG_REISERFS_FS_XATTR
        /* Initialize the rwsem for xattr dir */
        init_rwsem(&REISERFS_SB(s)->xattr_dir_sem);
-
+#endif
        /* setup default block allocator options */
        reiserfs_init_alloc_options(s);
 
index fe0893afd931e02081eca0b968e30a19e7ce2a73..a974082b0824a8a9935abd42c3471b50a9755410 100644 (file)
  *     of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian).
  */
 
+#include <linux/kernel.h>
 #include <linux/syscalls.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/file.h>
@@ -26,7 +26,6 @@
 
 #include <asm/uaccess.h>
 
-#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
 
 struct poll_table_page {
@@ -65,7 +64,7 @@ EXPORT_SYMBOL(poll_initwait);
 
 static void free_poll_entry(struct poll_table_entry *entry)
 {
-       remove_wait_queue(entry->wait_address,&entry->wait);
+       remove_wait_queue(entry->wait_address, &entry->wait);
        fput(entry->filp);
 }
 
@@ -129,7 +128,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
        entry->filp = filp;
        entry->wait_address = wait_address;
        init_waitqueue_entry(&entry->wait, current);
-       add_wait_queue(wait_address,&entry->wait);
+       add_wait_queue(wait_address, &entry->wait);
 }
 
 #define FDS_IN(fds, n)         (fds->in + n)
@@ -399,7 +398,7 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
                        timeout = -1;   /* infinite */
                else {
-                       timeout = ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
+                       timeout = DIV_ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
                        timeout += tv.tv_sec * HZ;
                }
        }
@@ -454,7 +453,7 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
                if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
                        timeout = -1;   /* infinite */
                else {
-                       timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+                       timeout = DIV_ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
                        timeout += ts.tv_sec * HZ;
                }
        }
@@ -776,7 +775,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
                if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
                        timeout = -1;   /* infinite */
                else {
-                       timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+                       timeout = DIV_ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
                        timeout += ts.tv_sec * HZ;
                }
        }
index 723f7c6676614f6343ad6d3df7ca850c434eb282..c288fbe7953d982e1980fc8dd6db9b7815044030 100644 (file)
@@ -6,6 +6,7 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
@@ -22,8 +23,6 @@
 /* #define SMB_SLAB_DEBUG      (SLAB_RED_ZONE | SLAB_POISON) */
 #define SMB_SLAB_DEBUG 0
 
-#define ROUND_UP(x) (((x)+3) & ~3)
-
 /* cache for request structures */
 static struct kmem_cache *req_cachep;
 
@@ -200,8 +199,8 @@ static int smb_setup_trans2request(struct smb_request *req)
 
        const int smb_parameters = 15;
        const int header = SMB_HEADER_LEN + 2 * smb_parameters + 2;
-       const int oparam = ROUND_UP(header + 3);
-       const int odata  = ROUND_UP(oparam + req->rq_lparm);
+       const int oparam = ALIGN(header + 3, sizeof(u32));
+       const int odata  = ALIGN(oparam + req->rq_lparm, sizeof(u32));
        const int bcc = (req->rq_data ? odata + req->rq_ldata :
                                        oparam + req->rq_lparm) - header;
 
index 89eaf31f1d46c18a42870c604d4b58ced724bfa5..67176af8515f816e28c9d013d5cda91ad9e3afe8 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/dcache.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/net.h>
 #include <linux/kthread.h>
@@ -299,8 +298,6 @@ out:
  */
 static int smbiod(void *unused)
 {
-       allow_signal(SIGKILL);
-
        VERBOSE("SMB Kernel thread starting (%d) ...\n", current->pid);
 
        for (;;) {
index 92ea6b2367d7f69224462396b021d0f23937d4dc..e48bd8235a8e39fd81231cb091ee570569d37b09 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/net.h>
 #include <linux/mm.h>
 #include <linux/netdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/workqueue.h>
 #include <net/scm.h>
 #include <net/tcp_states.h>
index fea20ceb8a5f8fab59f4afe7421614231274d0e8..00b2909bd469e30fc9c074029cd1d2789515f2b8 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/net.h>
 #include <linux/namei.h>
 
index 5428b0ff3b6fcfebe6abd074cb9719ec48c9dbda..12f28281d2b1e1f8d1627995f03efcfeb25a4945 100644 (file)
@@ -289,12 +289,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                nr_pages = PIPE_BUFFERS;
 
        /*
-        * Initiate read-ahead on this page range. however, don't call into
-        * read-ahead if this is a non-zero offset (we are likely doing small
-        * chunk splice and the page is already there) for a single page.
+        * Don't try to 2nd guess the read-ahead logic, call into
+        * page_cache_readahead() like the page cache reads would do.
         */
-       if (!loff || nr_pages > 1)
-               page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
+       page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
 
        /*
         * Now fill in the holes:
@@ -378,10 +376,11 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                         * If in nonblock mode then dont block on waiting
                         * for an in-flight io page
                         */
-                       if (flags & SPLICE_F_NONBLOCK)
-                               break;
-
-                       lock_page(page);
+                       if (flags & SPLICE_F_NONBLOCK) {
+                               if (TestSetPageLocked(page))
+                                       break;
+                       } else
+                               lock_page(page);
 
                        /*
                         * page was truncated, stop here. if this isn't the
index 38a8cb2a28de4292047f93fa6fae59bf1490eb7d..68510068a6414e46f510033f9dc1477a4704672b 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -8,7 +8,6 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
index 8341e4e1d7380f49ce590a428456b12c88e11fed..5260d620c555fbd987eed1642649c0372670ace9 100644 (file)
@@ -107,6 +107,7 @@ out:
 static inline void destroy_super(struct super_block *s)
 {
        security_sb_free(s);
+       kfree(s->s_subtype);
        kfree(s);
 }
 
@@ -907,6 +908,29 @@ out:
 
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
 
+static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
+{
+       int err;
+       const char *subtype = strchr(fstype, '.');
+       if (subtype) {
+               subtype++;
+               err = -EINVAL;
+               if (!subtype[0])
+                       goto err;
+       } else
+               subtype = "";
+
+       mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
+       err = -ENOMEM;
+       if (!mnt->mnt_sb->s_subtype)
+               goto err;
+       return mnt;
+
+ err:
+       mntput(mnt);
+       return ERR_PTR(err);
+}
+
 struct vfsmount *
 do_kern_mount(const char *fstype, int flags, const char *name, void *data)
 {
@@ -915,6 +939,9 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
        if (!type)
                return ERR_PTR(-ENODEV);
        mnt = vfs_kern_mount(type, flags, name, data);
+       if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+           !mnt->mnt_sb->s_subtype)
+               mnt = fs_set_subtype(mnt, fstype);
        put_filesystem(type);
        return mnt;
 }
index 5cb9e7e433835d00333ae712612185b0a1f88c35..2f97576355b8828e2b952782860e5af7b3bebea2 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -229,7 +229,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
                        !S_ISLNK(i_mode))
                goto out_put;
 
-       ret = do_sync_file_range(file, offset, endbyte, flags);
+       ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
 out_put:
        fput_light(file, fput_needed);
 out:
index 0e637adc2b872c31d43aecae810c767c31b79e56..b502c7197ec063777d90af4c49f038e95acd0c9e 100644 (file)
@@ -111,36 +111,6 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
        return ret;
 }
 
-
-/**
- *     flush_read_buffer - push buffer to userspace.
- *     @buffer:        data buffer for file.
- *     @buf:           user-passed buffer.
- *     @count:         number of bytes requested.
- *     @ppos:          file position.
- *
- *     Copy the buffer we filled in fill_read_buffer() to userspace.
- *     This is done at the reader's leisure, copying and advancing 
- *     the amount they specify each time.
- *     This may be called continuously until the buffer is empty.
- */
-static int flush_read_buffer(struct sysfs_buffer * buffer, char __user * buf,
-                            size_t count, loff_t * ppos)
-{
-       int error;
-
-       if (*ppos > buffer->count)
-               return 0;
-
-       if (count > (buffer->count - *ppos))
-               count = buffer->count - *ppos;
-
-       error = copy_to_user(buf,buffer->page + *ppos,count);
-       if (!error)
-               *ppos += count;
-       return error ? -EFAULT : count;
-}
-
 /**
  *     sysfs_read_file - read an attribute. 
  *     @file:  file pointer.
@@ -177,7 +147,8 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
                 __FUNCTION__, count, *ppos, buffer->page);
-       retval = flush_read_buffer(buffer,buf,count,ppos);
+       retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
+                                        buffer->count);
 out:
        up(&buffer->sem);
        return retval;
index 4e48abbd2b5de63ff1e93f7c5599a9b917f18e43..6bd850b7641ae58bb1dd726c5ffb40fef0e0d595 100644 (file)
@@ -13,7 +13,6 @@
  */
 
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include "sysv.h"
 
 static int add_nondir(struct dentry *dentry, struct inode *inode)
index ea521f846d97a4e3109b82feb8bb83f6d9201a1c..4cec9101568135fd6f18a0f50fcaf9ccd9689dc0 100644 (file)
@@ -427,9 +427,9 @@ static void udf_table_free_blocks(struct super_block * sb,
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        uint32_t start, end;
-       uint32_t nextoffset, oextoffset, elen;
-       kernel_lb_addr nbloc, obloc, eloc;
-       struct buffer_head *obh, *nbh;
+       uint32_t elen;
+       kernel_lb_addr eloc;
+       struct extent_position oepos, epos;
        int8_t etype;
        int i;
 
@@ -457,14 +457,13 @@ static void udf_table_free_blocks(struct super_block * sb,
        start = bloc.logicalBlockNum + offset;
        end = bloc.logicalBlockNum + offset + count - 1;
 
-       oextoffset = nextoffset = sizeof(struct unallocSpaceEntry);
+       epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
        elen = 0;
-       obloc = nbloc = UDF_I_LOCATION(table);
-
-       obh = nbh = NULL;
+       epos.block = oepos.block = UDF_I_LOCATION(table);
+       epos.bh = oepos.bh = NULL;
 
        while (count && (etype =
-               udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
                        start))
@@ -482,7 +481,7 @@ static void udf_table_free_blocks(struct super_block * sb,
                                start += count;
                                count = 0;
                        }
-                       udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
+                       udf_write_aext(table, &oepos, eloc, elen, 1);
                }
                else if (eloc.logicalBlockNum == (end + 1))
                {
@@ -502,20 +501,20 @@ static void udf_table_free_blocks(struct super_block * sb,
                                end -= count;
                                count = 0;
                        }
-                       udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
+                       udf_write_aext(table, &oepos, eloc, elen, 1);
                }
 
-               if (nbh != obh)
+               if (epos.bh != oepos.bh)
                {
                        i = -1;
-                       obloc = nbloc;
-                       udf_release_data(obh);
-                       atomic_inc(&nbh->b_count);
-                       obh = nbh;
-                       oextoffset = 0;
+                       oepos.block = epos.block;
+                       brelse(oepos.bh);
+                       get_bh(epos.bh);
+                       oepos.bh = epos.bh;
+                       oepos.offset = 0;
                }
                else
-                       oextoffset = nextoffset;
+                       oepos.offset = epos.offset;
        }
 
        if (count)
@@ -547,55 +546,53 @@ static void udf_table_free_blocks(struct super_block * sb,
                        adsize = sizeof(long_ad);
                else
                {
-                       udf_release_data(obh);
-                       udf_release_data(nbh);
+                       brelse(oepos.bh);
+                       brelse(epos.bh);
                        goto error_return;
                }
 
-               if (nextoffset + (2 * adsize) > sb->s_blocksize)
+               if (epos.offset + (2 * adsize) > sb->s_blocksize)
                {
                        char *sptr, *dptr;
                        int loffset;
        
-                       udf_release_data(obh);
-                       obh = nbh;
-                       obloc = nbloc;
-                       oextoffset = nextoffset;
+                       brelse(oepos.bh);
+                       oepos = epos;
 
                        /* Steal a block from the extent being free'd */
-                       nbloc.logicalBlockNum = eloc.logicalBlockNum;
+                       epos.block.logicalBlockNum = eloc.logicalBlockNum;
                        eloc.logicalBlockNum ++;
                        elen -= sb->s_blocksize;
 
-                       if (!(nbh = udf_tread(sb,
-                               udf_get_lb_pblock(sb, nbloc, 0))))
+                       if (!(epos.bh = udf_tread(sb,
+                               udf_get_lb_pblock(sb, epos.block, 0))))
                        {
-                               udf_release_data(obh);
+                               brelse(oepos.bh);
                                goto error_return;
                        }
-                       aed = (struct allocExtDesc *)(nbh->b_data);
-                       aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
-                       if (nextoffset + adsize > sb->s_blocksize)
+                       aed = (struct allocExtDesc *)(epos.bh->b_data);
+                       aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum);
+                       if (epos.offset + adsize > sb->s_blocksize)
                        {
-                               loffset = nextoffset;
+                               loffset = epos.offset;
                                aed->lengthAllocDescs = cpu_to_le32(adsize);
-                               sptr = UDF_I_DATA(inode) + nextoffset -
+                               sptr = UDF_I_DATA(inode) + epos.offset -
                                        udf_file_entry_alloc_offset(inode) +
                                        UDF_I_LENEATTR(inode) - adsize;
-                               dptr = nbh->b_data + sizeof(struct allocExtDesc);
+                               dptr = epos.bh->b_data + sizeof(struct allocExtDesc);
                                memcpy(dptr, sptr, adsize);
-                               nextoffset = sizeof(struct allocExtDesc) + adsize;
+                               epos.offset = sizeof(struct allocExtDesc) + adsize;
                        }
                        else
                        {
-                               loffset = nextoffset + adsize;
+                               loffset = epos.offset + adsize;
                                aed->lengthAllocDescs = cpu_to_le32(0);
-                               sptr = (obh)->b_data + nextoffset;
-                               nextoffset = sizeof(struct allocExtDesc);
+                               sptr = oepos.bh->b_data + epos.offset;
+                               epos.offset = sizeof(struct allocExtDesc);
 
-                               if (obh)
+                               if (oepos.bh)
                                {
-                                       aed = (struct allocExtDesc *)(obh)->b_data;
+                                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                                        aed->lengthAllocDescs =
                                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                                }
@@ -606,11 +603,11 @@ static void udf_table_free_blocks(struct super_block * sb,
                                }
                        }
                        if (UDF_SB_UDFREV(sb) >= 0x0200)
-                               udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
-                                       nbloc.logicalBlockNum, sizeof(tag));
+                               udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1,
+                                       epos.block.logicalBlockNum, sizeof(tag));
                        else
-                               udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
-                                       nbloc.logicalBlockNum, sizeof(tag));
+                               udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1,
+                                       epos.block.logicalBlockNum, sizeof(tag));
                        switch (UDF_I_ALLOCTYPE(table))
                        {
                                case ICBTAG_FLAG_AD_SHORT:
@@ -619,7 +616,7 @@ static void udf_table_free_blocks(struct super_block * sb,
                                        sad->extLength = cpu_to_le32(
                                                EXT_NEXT_EXTENT_ALLOCDECS |
                                                sb->s_blocksize);
-                                       sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
+                                       sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum);
                                        break;
                                }
                                case ICBTAG_FLAG_AD_LONG:
@@ -628,14 +625,14 @@ static void udf_table_free_blocks(struct super_block * sb,
                                        lad->extLength = cpu_to_le32(
                                                EXT_NEXT_EXTENT_ALLOCDECS |
                                                sb->s_blocksize);
-                                       lad->extLocation = cpu_to_lelb(nbloc);
+                                       lad->extLocation = cpu_to_lelb(epos.block);
                                        break;
                                }
                        }
-                       if (obh)
+                       if (oepos.bh)
                        {
-                               udf_update_tag(obh->b_data, loffset);
-                               mark_buffer_dirty(obh);
+                               udf_update_tag(oepos.bh->b_data, loffset);
+                               mark_buffer_dirty(oepos.bh);
                        }
                        else
                                mark_inode_dirty(table);
@@ -643,26 +640,26 @@ static void udf_table_free_blocks(struct super_block * sb,
 
                if (elen) /* It's possible that stealing the block emptied the extent */
                {
-                       udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
+                       udf_write_aext(table, &epos, eloc, elen, 1);
 
-                       if (!nbh)
+                       if (!epos.bh)
                        {
                                UDF_I_LENALLOC(table) += adsize;
                                mark_inode_dirty(table);
                        }
                        else
                        {
-                               aed = (struct allocExtDesc *)nbh->b_data;
+                               aed = (struct allocExtDesc *)epos.bh->b_data;
                                aed->lengthAllocDescs =
                                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
-                               udf_update_tag(nbh->b_data, nextoffset);
-                               mark_buffer_dirty(nbh);
+                               udf_update_tag(epos.bh->b_data, epos.offset);
+                               mark_buffer_dirty(epos.bh);
                        }
                }
        }
 
-       udf_release_data(nbh);
-       udf_release_data(obh);
+       brelse(epos.bh);
+       brelse(oepos.bh);
 
 error_return:
        sb->s_dirt = 1;
@@ -677,9 +674,9 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        int alloc_count = 0;
-       uint32_t extoffset, elen, adsize;
-       kernel_lb_addr bloc, eloc;
-       struct buffer_head *bh;
+       uint32_t elen, adsize;
+       kernel_lb_addr eloc;
+       struct extent_position epos;
        int8_t etype = -1;
 
        if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
@@ -693,14 +690,13 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
                return 0;
 
        mutex_lock(&sbi->s_alloc_mutex);
-       extoffset = sizeof(struct unallocSpaceEntry);
-       bloc = UDF_I_LOCATION(table);
-
-       bh = NULL;
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.bh = NULL;
        eloc.logicalBlockNum = 0xFFFFFFFF;
 
        while (first_block != eloc.logicalBlockNum && (etype =
-               udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                udf_debug("eloc=%d, elen=%d, first_block=%d\n",
                        eloc.logicalBlockNum, elen, first_block);
@@ -709,7 +705,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 
        if (first_block == eloc.logicalBlockNum)
        {
-               extoffset -= adsize;
+               epos.offset -= adsize;
 
                alloc_count = (elen >> sb->s_blocksize_bits);
                if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
@@ -719,15 +715,15 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
                        alloc_count = block_count;
                        eloc.logicalBlockNum += alloc_count;
                        elen -= (alloc_count << sb->s_blocksize_bits);
-                       udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1);
+                       udf_write_aext(table, &epos, eloc, (etype << 30) | elen, 1);
                }
                else
-                       udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
+                       udf_delete_aext(table, epos, eloc, (etype << 30) | elen);
        }
        else
                alloc_count = 0;
 
-       udf_release_data(bh);
+       brelse(epos.bh);
 
        if (alloc_count && UDF_SB_LVIDBH(sb))
        {
@@ -747,9 +743,9 @@ static int udf_table_new_block(struct super_block * sb,
        struct udf_sb_info *sbi = UDF_SB(sb);
        uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
        uint32_t newblock = 0, adsize;
-       uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
-       kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
-       struct buffer_head *bh, *goal_bh;
+       uint32_t elen, goal_elen = 0;
+       kernel_lb_addr eloc, goal_eloc;
+       struct extent_position epos, goal_epos;
        int8_t etype;
 
        *err = -ENOSPC;
@@ -770,14 +766,12 @@ static int udf_table_new_block(struct super_block * sb,
           We store the buffer_head, bloc, and extoffset of the current closest
           match and use that when we are done.
        */
-
-       extoffset = sizeof(struct unallocSpaceEntry);
-       bloc = UDF_I_LOCATION(table);
-
-       goal_bh = bh = NULL;
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.bh = goal_epos.bh = NULL;
 
        while (spread && (etype =
-               udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                if (goal >= eloc.logicalBlockNum)
                {
@@ -793,24 +787,24 @@ static int udf_table_new_block(struct super_block * sb,
                if (nspread < spread)
                {
                        spread = nspread;
-                       if (goal_bh != bh)
+                       if (goal_epos.bh != epos.bh)
                        {
-                               udf_release_data(goal_bh);
-                               goal_bh = bh;
-                               atomic_inc(&goal_bh->b_count);
+                               brelse(goal_epos.bh);
+                               goal_epos.bh = epos.bh;
+                               get_bh(goal_epos.bh);
                        }
-                       goal_bloc = bloc;
-                       goal_extoffset = extoffset - adsize;
+                       goal_epos.block = epos.block;
+                       goal_epos.offset = epos.offset - adsize;
                        goal_eloc = eloc;
                        goal_elen = (etype << 30) | elen;
                }
        }
 
-       udf_release_data(bh);
+       brelse(epos.bh);
 
        if (spread == 0xFFFFFFFF)
        {
-               udf_release_data(goal_bh);
+               brelse(goal_epos.bh);
                mutex_unlock(&sbi->s_alloc_mutex);
                return 0;
        }
@@ -826,17 +820,17 @@ static int udf_table_new_block(struct super_block * sb,
 
        if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
        {
-               udf_release_data(goal_bh);
+               brelse(goal_epos.bh);
                mutex_unlock(&sbi->s_alloc_mutex);
                *err = -EDQUOT;
                return 0;
        }
 
        if (goal_elen)
-               udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
+               udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1);
        else
-               udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);
-       udf_release_data(goal_bh);
+               udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
+       brelse(goal_epos.bh);
 
        if (UDF_SB_LVIDBH(sb))
        {
@@ -921,11 +915,14 @@ inline int udf_new_block(struct super_block * sb,
        struct inode * inode,
        uint16_t partition, uint32_t goal, int *err)
 {
+       int ret;
+
        if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
        {
-               return udf_bitmap_new_block(sb, inode,
+               ret = udf_bitmap_new_block(sb, inode,
                        UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,
                        partition, goal, err);
+               return ret;
        }
        else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
        {
index 2391c9150c497dbd27f3b6bf0bf25808a1672889..e45f86b5e7b07aef5c945400b9fdf4030c25b545 100644 (file)
@@ -111,11 +111,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        uint16_t liu;
        uint8_t lfi;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
-       struct buffer_head * bh = NULL, * tmp, * bha[16];
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen, offset;
+       struct buffer_head *tmp, *bha[16];
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
        int i, num;
        unsigned int dt_type;
+       struct extent_position epos = { NULL, 0, {0, 0}};
 
        if (nf_pos >= size)
                return 0;
@@ -127,23 +129,22 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                fibh.sbh = fibh.ebh = NULL;
        else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
-               &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
-               offset >>= dir->i_sb->s_blocksize_bits;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       brelse(epos.bh);
                        return -EIO;
                }
        
@@ -171,7 +172,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        }
        else
        {
-               udf_release_data(bh);
+               brelse(epos.bh);
                return -ENOENT;
        }
 
@@ -179,14 +180,14 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        {
                filp->f_pos = nf_pos + 1;
 
-               fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh.sbh != fibh.ebh)
-                               udf_release_data(fibh.ebh);
-                       udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                               brelse(fibh.ebh);
+                       brelse(fibh.sbh);
+                       brelse(epos.bh);
                        return 0;
                }
 
@@ -244,9 +245,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
                        if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0)
                        {
                                if (fibh.sbh != fibh.ebh)
-                                       udf_release_data(fibh.ebh);
-                               udf_release_data(fibh.sbh);
-                               udf_release_data(bh);
+                                       brelse(fibh.ebh);
+                               brelse(fibh.sbh);
+                               brelse(epos.bh);
                                return 0;
                        }
                }
@@ -255,9 +256,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        filp->f_pos = nf_pos + 1;
 
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
-       udf_release_data(bh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
+       brelse(epos.bh);
 
        return 0;
 }
index fe751a2a0e478d5debb692a7ae23d0c1dc750b6a..198caa33027a99f5a6371f8077cac32ba3b6f53f 100644 (file)
@@ -36,14 +36,14 @@ udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
 
        if (!ad)
        {
-               udf_release_data(*bh);
+               brelse(*bh);
                *error = 1;
                return NULL;
        }
 
        if (*offset == dir->i_sb->s_blocksize)
        {
-               udf_release_data(*bh);
+               brelse(*bh);
                block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
                if (!block)
                        return NULL;
@@ -57,7 +57,7 @@ udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
                remainder = dir->i_sb->s_blocksize - loffset;
                memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder);
 
-               udf_release_data(*bh);
+               brelse(*bh);
                block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
                if (!block)
                        return NULL;
@@ -75,9 +75,9 @@ struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        struct udf_fileident_bh *fibh,
        struct fileIdentDesc *cfi,
-       kernel_lb_addr *bloc, uint32_t *extoffset, 
+       struct extent_position *epos,
        kernel_lb_addr *eloc, uint32_t *elen,
-       uint32_t *offset, struct buffer_head **bh)
+       sector_t *offset)
 {
        struct fileIdentDesc *fi;
        int i, num, block;
@@ -105,13 +105,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 
        if (fibh->eoffset == dir->i_sb->s_blocksize)
        {
-               int lextoffset = *extoffset;
+               int lextoffset = epos->offset;
 
-               if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
+               if (udf_next_aext(dir, epos, eloc, elen, 1) !=
                        (EXT_RECORDED_ALLOCATED >> 30))
-               {
                        return NULL;
-               }
 
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
@@ -120,9 +118,9 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
                        *offset = 0;
                else
-                       *extoffset = lextoffset;
+                       epos->offset = lextoffset;
 
-               udf_release_data(fibh->sbh);
+               brelse(fibh->sbh);
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
                        return NULL;
                fibh->soffset = fibh->eoffset = 0;
@@ -151,7 +149,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        }
        else if (fibh->sbh != fibh->ebh)
        {
-               udf_release_data(fibh->sbh);
+               brelse(fibh->sbh);
                fibh->sbh = fibh->ebh;
        }
 
@@ -169,13 +167,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        }
        else if (fibh->eoffset > dir->i_sb->s_blocksize)
        {
-               int lextoffset = *extoffset;
+               int lextoffset = epos->offset;
 
-               if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
+               if (udf_next_aext(dir, epos, eloc, elen, 1) !=
                        (EXT_RECORDED_ALLOCATED >> 30))
-               {
                        return NULL;
-               }
 
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
@@ -184,7 +180,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
                        *offset = 0;
                else
-                       *extoffset = lextoffset;
+                       epos->offset = lextoffset;
 
                fibh->soffset -= dir->i_sb->s_blocksize;
                fibh->eoffset -= dir->i_sb->s_blocksize;
index 5887d78cde431cb05bfb3289b547195ae52421b1..6ded93e7c44fc79587bce58b0241facb627a9634 100644 (file)
@@ -21,7 +21,6 @@
 #include "udfdecl.h"
 
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 
 static int udf_fsync_inode(struct inode *, int);
 
index ae21a0e59e9569b09234f57fd1a910baf9928059..c8461551e108bda5a48448ae5b0945286842a1ab 100644 (file)
@@ -49,10 +49,10 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
-static struct buffer_head *inode_getblk(struct inode *, long, int *,
+static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
        long *, int *);
-static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
-       kernel_lb_addr, uint32_t, struct buffer_head *);
+static int8_t udf_insert_aext(struct inode *, struct extent_position,
+       kernel_lb_addr, uint32_t);
 static void udf_split_extents(struct inode *, int *, int, int,
        kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
@@ -61,7 +61,7 @@ static void udf_merge_extents(struct inode *,
         kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
        kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
-       kernel_lb_addr, uint32_t, struct buffer_head **);
+       struct extent_position *);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
@@ -194,10 +194,11 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
 {
        int newblock;
-       struct buffer_head *sbh = NULL, *dbh = NULL;
-       kernel_lb_addr bloc, eloc;
-       uint32_t elen, extoffset;
+       struct buffer_head *dbh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        uint8_t alloctype;
+       struct extent_position epos;
 
        struct udf_fileident_bh sfibh, dfibh;
        loff_t f_pos = udf_ext0_offset(inode) >> 2;
@@ -237,16 +238,16 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
        mark_buffer_dirty_inode(dbh, inode);
 
        sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
-       sbh = sfibh.sbh = sfibh.ebh = NULL;
+       sfibh.sbh = sfibh.ebh = NULL;
        dfibh.soffset = dfibh.eoffset = 0;
        dfibh.sbh = dfibh.ebh = dbh;
        while ( (f_pos < size) )
        {
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
-               sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
+               sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
                if (!sfi)
                {
-                       udf_release_data(dbh);
+                       brelse(dbh);
                        return NULL;
                }
                UDF_I_ALLOCTYPE(inode) = alloctype;
@@ -258,7 +259,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
                        sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
                {
                        UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
-                       udf_release_data(dbh);
+                       brelse(dbh);
                        return NULL;
                }
        }
@@ -266,16 +267,17 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 
        memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
        UDF_I_LENALLOC(inode) = 0;
-       bloc = UDF_I_LOCATION(inode);
        eloc.logicalBlockNum = *block;
        eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
        elen = inode->i_size;
        UDF_I_LENEXTENTS(inode) = elen;
-       extoffset = udf_file_entry_alloc_offset(inode);
-       udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
+       epos.bh = NULL;
+       epos.block = UDF_I_LOCATION(inode);
+       epos.offset = udf_file_entry_alloc_offset(inode);
+       udf_add_aext(inode, &epos, eloc, elen, 0);
        /* UniqueID stuff */
 
-       udf_release_data(sbh);
+       brelse(epos.bh);
        mark_inode_dirty(inode);
        return dbh;
 }
@@ -354,53 +356,153 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
        return NULL;
 }
 
-static struct buffer_head * inode_getblk(struct inode * inode, long block,
+/* Extend the file by 'blocks' blocks, return the number of extents added */
+int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
+       kernel_long_ad *last_ext, sector_t blocks)
+{
+       sector_t add;
+       int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+       struct super_block *sb = inode->i_sb;
+       kernel_lb_addr prealloc_loc = {0, 0};
+       int prealloc_len = 0;
+
+       /* The previous extent is fake and we should not extend by anything
+        * - there's nothing to do... */
+       if (!blocks && fake)
+               return 0;
+       /* Round the last extent up to a multiple of block size */
+       if (last_ext->extLength & (sb->s_blocksize - 1)) {
+               last_ext->extLength =
+                       (last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
+                       (((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
+                               sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
+               UDF_I_LENEXTENTS(inode) =
+                       (UDF_I_LENEXTENTS(inode) + sb->s_blocksize - 1) &
+                               ~(sb->s_blocksize - 1);
+       }
+       /* Last extent are just preallocated blocks? */
+       if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_ALLOCATED) {
+               /* Save the extent so that we can reattach it to the end */
+               prealloc_loc = last_ext->extLocation;
+               prealloc_len = last_ext->extLength;
+               /* Mark the extent as a hole */
+               last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                       (last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+               last_ext->extLocation.logicalBlockNum = 0;
+                       last_ext->extLocation.partitionReferenceNum = 0;
+       }
+       /* Can we merge with the previous extent? */
+       if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) {
+               add = ((1<<30) - sb->s_blocksize - (last_ext->extLength &
+                       UDF_EXTENT_LENGTH_MASK)) >> sb->s_blocksize_bits;
+               if (add > blocks)
+                       add = blocks;
+               blocks -= add;
+               last_ext->extLength += add << sb->s_blocksize_bits;
+       }
+
+       if (fake) {
+               udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1);
+               count++;
+       }
+       else
+               udf_write_aext(inode, last_pos, last_ext->extLocation, last_ext->extLength, 1);
+       /* Managed to do everything necessary? */
+       if (!blocks)
+               goto out;
+
+       /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
+       last_ext->extLocation.logicalBlockNum = 0;
+               last_ext->extLocation.partitionReferenceNum = 0;
+       add = (1 << (30-sb->s_blocksize_bits)) - 1;
+       last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | (add << sb->s_blocksize_bits);
+       /* Create enough extents to cover the whole hole */
+       while (blocks > add) {
+               blocks -= add;
+               if (udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1) == -1)
+                       return -1;
+               count++;
+       }
+       if (blocks) {
+               last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                       (blocks << sb->s_blocksize_bits);
+               if (udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1) == -1)
+                       return -1;
+               count++;
+       }
+out:
+       /* Do we have some preallocated blocks saved? */
+       if (prealloc_len) {
+               if (udf_add_aext(inode, last_pos, prealloc_loc, prealloc_len, 1) == -1)
+                       return -1;
+               last_ext->extLocation = prealloc_loc;
+               last_ext->extLength = prealloc_len;
+               count++;
+       }
+       /* last_pos should point to the last written extent... */
+       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
+               last_pos->offset -= sizeof(short_ad);
+       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
+               last_pos->offset -= sizeof(long_ad);
+       else
+               return -1;
+       return count;
+}
+
+static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
        int *err, long *phys, int *new)
 {
-       struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
+       static sector_t last_block;
+       struct buffer_head *result = NULL;
        kernel_long_ad laarr[EXTENT_MERGE_SIZE];
-       uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
+       struct extent_position prev_epos, cur_epos, next_epos;
        int count = 0, startnum = 0, endnum = 0;
        uint32_t elen = 0;
-       kernel_lb_addr eloc, pbloc, cbloc, nbloc;
+       kernel_lb_addr eloc;
        int c = 1;
-       uint64_t lbcount = 0, b_off = 0;
-       uint32_t newblocknum, newblock, offset = 0;
+       loff_t lbcount = 0, b_off = 0;
+       uint32_t newblocknum, newblock;
+       sector_t offset = 0;
        int8_t etype;
        int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
-       char lastblock = 0;
+       int lastblock = 0;
 
-       pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
-       b_off = (uint64_t)block << inode->i_sb->s_blocksize_bits;
-       pbloc = cbloc = nbloc = UDF_I_LOCATION(inode);
+       prev_epos.offset = udf_file_entry_alloc_offset(inode);
+       prev_epos.block = UDF_I_LOCATION(inode);
+       prev_epos.bh = NULL;
+       cur_epos = next_epos = prev_epos;
+       b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
 
        /* find the extent which contains the block we are looking for.
        alternate between laarr[0] and laarr[1] for locations of the
        current extent, and the previous extent */
        do
        {
-               if (pbh != cbh)
+               if (prev_epos.bh != cur_epos.bh)
                {
-                       udf_release_data(pbh);
-                       atomic_inc(&cbh->b_count);
-                       pbh = cbh;
+                       brelse(prev_epos.bh);
+                       get_bh(cur_epos.bh);
+                       prev_epos.bh = cur_epos.bh;
                }
-               if (cbh != nbh)
+               if (cur_epos.bh != next_epos.bh)
                {
-                       udf_release_data(cbh);
-                       atomic_inc(&nbh->b_count);
-                       cbh = nbh;
+                       brelse(cur_epos.bh);
+                       get_bh(next_epos.bh);
+                       cur_epos.bh = next_epos.bh;
                }
 
                lbcount += elen;
 
-               pbloc = cbloc;
-               cbloc = nbloc;
+               prev_epos.block = cur_epos.block;
+               cur_epos.block = next_epos.block;
 
-               pextoffset = cextoffset;
-               cextoffset = nextoffset;
+               prev_epos.offset = cur_epos.offset;
+               cur_epos.offset = next_epos.offset;
 
-               if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1)
+               if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1)) == -1)
                        break;
 
                c = !c;
@@ -418,6 +520,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 
        b_off -= lbcount;
        offset = b_off >> inode->i_sb->s_blocksize_bits;
+       /* Move into indirect extent if we are at a pointer to it */
+       udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
 
        /* if the extent is allocated and recorded, return the block
        if the extent is not a multiple of the blocksize, round up */
@@ -429,54 +533,77 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                        elen = EXT_RECORDED_ALLOCATED |
                                ((elen + inode->i_sb->s_blocksize - 1) &
                                ~(inode->i_sb->s_blocksize - 1));
-                       etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1);
+                       etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
                }
-               udf_release_data(pbh);
-               udf_release_data(cbh);
-               udf_release_data(nbh);
+               brelse(prev_epos.bh);
+               brelse(cur_epos.bh);
+               brelse(next_epos.bh);
                newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
                *phys = newblock;
                return NULL;
        }
 
+       last_block = block;
+       /* Are we beyond EOF? */
        if (etype == -1)
        {
-               endnum = startnum = ((count > 1) ? 1 : count);
-               if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
-               {
-                       laarr[c].extLength =
-                               (laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
-                               (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
-                                       inode->i_sb->s_blocksize - 1) &
-                               ~(inode->i_sb->s_blocksize - 1));
-                       UDF_I_LENEXTENTS(inode) =
-                               (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) &
-                                       ~(inode->i_sb->s_blocksize - 1);
+               int ret;
+
+               if (count) {
+                       if (c)
+                               laarr[0] = laarr[1];
+                       startnum = 1;
+               }
+               else {
+                       /* Create a fake extent when there's not one */
+                       memset(&laarr[0].extLocation, 0x00, sizeof(kernel_lb_addr));
+                       laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
+                       /* Will udf_extend_file() create real extent from a fake one? */
+                       startnum = (offset > 0);
+               }
+               /* Create extents for the hole between EOF and offset */
+               ret = udf_extend_file(inode, &prev_epos, laarr, offset);
+               if (ret == -1) {
+                       brelse(prev_epos.bh);
+                       brelse(cur_epos.bh);
+                       brelse(next_epos.bh);
+                       /* We don't really know the error here so we just make
+                        * something up */
+                       *err = -ENOSPC;
+                       return NULL;
                }
-               c = !c;
-               laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
-                       ((offset + 1) << inode->i_sb->s_blocksize_bits);
-               memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
-               count ++;
-               endnum ++;
+               c = 0;
+               offset = 0;
+               count += ret;
+               /* We are not covered by a preallocated extent? */
+               if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != EXT_NOT_RECORDED_ALLOCATED) {
+                       /* Is there any real extent? - otherwise we overwrite
+                        * the fake one... */
+                       if (count)
+                               c = !c;
+                       laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                               inode->i_sb->s_blocksize;
+                       memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
+                       count ++;
+                       endnum ++;
+               }
+               endnum = c+1;
                lastblock = 1;
        }
-       else
+       else {
                endnum = startnum = ((count > 2) ? 2 : count);
 
-       /* if the current extent is in position 0, swap it with the previous */
-       if (!c && count != 1)
-       {
-               laarr[2] = laarr[0];
-               laarr[0] = laarr[1];
-               laarr[1] = laarr[2];
-               c = 1;
-       }
+               /* if the current extent is in position 0, swap it with the previous */
+               if (!c && count != 1)
+               {
+                       laarr[2] = laarr[0];
+                       laarr[0] = laarr[1];
+                       laarr[1] = laarr[2];
+                       c = 1;
+               }
 
-       /* if the current block is located in a extent, read the next extent */
-       if (etype != -1)
-       {
-               if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1)
+               /* if the current block is located in an extent, read the next extent */
+               if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
                {
                        laarr[c+1].extLength = (etype << 30) | elen;
                        laarr[c+1].extLocation = eloc;
@@ -484,11 +611,10 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                        startnum ++;
                        endnum ++;
                }
-               else
+               else {
                        lastblock = 1;
+               }
        }
-       udf_release_data(cbh);
-       udf_release_data(nbh);
 
        /* if the current extent is not recorded but allocated, get the
                block in the extent corresponding to the requested block */
@@ -508,7 +634,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                if (!(newblocknum = udf_new_block(inode->i_sb, inode,
                        UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
                {
-                       udf_release_data(pbh);
+                       brelse(prev_epos.bh);
                        *err = -ENOSPC;
                        return NULL;
                }
@@ -529,11 +655,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
        udf_merge_extents(inode, laarr, &endnum);
 
        /* write back the new extents, inserting new extents if the new number
-       of extents is greater than the old number, and deleting extents if
-       the new number of extents is less than the old number */
-       udf_update_extents(inode, laarr, startnum, endnum, pbloc, pextoffset, &pbh);
+       of extents is greater than the old number, and deleting extents if
+       the new number of extents is less than the old number */
+       udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
 
-       udf_release_data(pbh);
+       brelse(prev_epos.bh);
 
        if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
                UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@@ -795,7 +921,7 @@ static void udf_merge_extents(struct inode *inode,
 
 static void udf_update_extents(struct inode *inode,
        kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
-       kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
+       struct extent_position *epos)
 {
        int start = 0, i;
        kernel_lb_addr tmploc;
@@ -804,28 +930,26 @@ static void udf_update_extents(struct inode *inode,
        if (startnum > endnum)
        {
                for (i=0; i<(startnum-endnum); i++)
-               {
-                       udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
-                               laarr[i].extLength, *pbh);
-               }
+                       udf_delete_aext(inode, *epos, laarr[i].extLocation,
+                               laarr[i].extLength);
        }
        else if (startnum < endnum)
        {
                for (i=0; i<(endnum-startnum); i++)
                {
-                       udf_insert_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
-                               laarr[i].extLength, *pbh);
-                       udf_next_aext(inode, &pbloc, &pextoffset, &laarr[i].extLocation,
-                               &laarr[i].extLength, pbh, 1);
+                       udf_insert_aext(inode, *epos, laarr[i].extLocation,
+                               laarr[i].extLength);
+                       udf_next_aext(inode, epos, &laarr[i].extLocation,
+                               &laarr[i].extLength, 1);
                        start ++;
                }
        }
 
        for (i=start; i<endnum; i++)
        {
-               udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
-               udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
-                       laarr[i].extLength, *pbh, 1);
+               udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
+               udf_write_aext(inode, epos, laarr[i].extLocation,
+                       laarr[i].extLength, 1);
        }
 }
 
@@ -931,7 +1055,7 @@ __udf_read_inode(struct inode *inode)
        {
                printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
                        inode->i_ino, ident);
-               udf_release_data(bh);
+               brelse(bh);
                make_bad_inode(inode);
                return;
        }
@@ -960,35 +1084,36 @@ __udf_read_inode(struct inode *inode)
                                                ident == TAG_IDENT_EFE)
                                        {
                                                memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
-                                               udf_release_data(bh);
-                                               udf_release_data(ibh);
-                                               udf_release_data(nbh);
+                                               brelse(bh);
+                                               brelse(ibh);
+                                               brelse(nbh);
                                                __udf_read_inode(inode);
                                                return;
                                        }
                                        else
                                        {
-                                               udf_release_data(nbh);
-                                               udf_release_data(ibh);
+                                               brelse(nbh);
+                                               brelse(ibh);
                                        }
                                }
                                else
-                                       udf_release_data(ibh);
+                                       brelse(ibh);
                        }
                }
                else
-                       udf_release_data(ibh);
+                       brelse(ibh);
        }
        else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
        {
                printk(KERN_ERR "udf: unsupported strategy type: %d\n",
                        le16_to_cpu(fe->icbTag.strategyType));
-               udf_release_data(bh);
+               brelse(bh);
                make_bad_inode(inode);
                return;
        }
        udf_fill_inode(inode, bh);
-       udf_release_data(bh);
+
+       brelse(bh);
 }
 
 static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
@@ -1331,7 +1456,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                                use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i];
 
                mark_buffer_dirty(bh);
-               udf_release_data(bh);
+               brelse(bh);
                return err;
        }
 
@@ -1520,7 +1645,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                        err = -EIO;
                }
        }
-       udf_release_data(bh);
+       brelse(bh);
        return err;
 }
 
@@ -1556,8 +1681,8 @@ udf_iget(struct super_block *sb, kernel_lb_addr ino)
        return NULL;
 }
 
-int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
+int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr eloc, uint32_t elen, int inc)
 {
        int adsize;
        short_ad *sad = NULL;
@@ -1566,10 +1691,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        int8_t etype;
        uint8_t *ptr;
 
-       if (!*bh)
-               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+       if (!epos->bh)
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
        else
-               ptr = (*bh)->b_data + *extoffset;
+               ptr = epos->bh->b_data + epos->offset;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -1578,20 +1703,20 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        else
                return -1;
 
-       if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
+       if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize)
        {
                char *sptr, *dptr;
                struct buffer_head *nbh;
                int err, loffset;
-               kernel_lb_addr obloc = *bloc;
+               kernel_lb_addr obloc = epos->block;
 
-               if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
+               if (!(epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
                        obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
                {
                        return -1;
                }
                if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
-                       *bloc, 0))))
+                       epos->block, 0))))
                {
                        return -1;
                }
@@ -1604,25 +1729,25 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                aed = (struct allocExtDesc *)(nbh->b_data);
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
                        aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
-               if (*extoffset + adsize > inode->i_sb->s_blocksize)
+               if (epos->offset + adsize > inode->i_sb->s_blocksize)
                {
-                       loffset = *extoffset;
+                       loffset = epos->offset;
                        aed->lengthAllocDescs = cpu_to_le32(adsize);
                        sptr = ptr - adsize;
                        dptr = nbh->b_data + sizeof(struct allocExtDesc);
                        memcpy(dptr, sptr, adsize);
-                       *extoffset = sizeof(struct allocExtDesc) + adsize;
+                       epos->offset = sizeof(struct allocExtDesc) + adsize;
                }
                else
                {
-                       loffset = *extoffset + adsize;
+                       loffset = epos->offset + adsize;
                        aed->lengthAllocDescs = cpu_to_le32(0);
                        sptr = ptr;
-                       *extoffset = sizeof(struct allocExtDesc);
+                       epos->offset = sizeof(struct allocExtDesc);
 
-                       if (*bh)
+                       if (epos->bh)
                        {
-                               aed = (struct allocExtDesc *)(*bh)->b_data;
+                               aed = (struct allocExtDesc *)epos->bh->b_data;
                                aed->lengthAllocDescs =
                                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                        }
@@ -1634,10 +1759,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                }
                if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
                        udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
-                               bloc->logicalBlockNum, sizeof(tag));
+                               epos->block.logicalBlockNum, sizeof(tag));
                else
                        udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
-                               bloc->logicalBlockNum, sizeof(tag));
+                               epos->block.logicalBlockNum, sizeof(tag));
                switch (UDF_I_ALLOCTYPE(inode))
                {
                        case ICBTAG_FLAG_AD_SHORT:
@@ -1646,7 +1771,7 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                                sad->extLength = cpu_to_le32(
                                        EXT_NEXT_EXTENT_ALLOCDECS |
                                        inode->i_sb->s_blocksize);
-                               sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);
+                               sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum);
                                break;
                        }
                        case ICBTAG_FLAG_AD_LONG:
@@ -1655,60 +1780,57 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                                lad->extLength = cpu_to_le32(
                                        EXT_NEXT_EXTENT_ALLOCDECS |
                                        inode->i_sb->s_blocksize);
-                               lad->extLocation = cpu_to_lelb(*bloc);
+                               lad->extLocation = cpu_to_lelb(epos->block);
                                memset(lad->impUse, 0x00, sizeof(lad->impUse));
                                break;
                        }
                }
-               if (*bh)
+               if (epos->bh)
                {
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag((*bh)->b_data, loffset);
+                               udf_update_tag(epos->bh->b_data, loffset);
                        else
-                               udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(*bh, inode);
-                       udf_release_data(*bh);
+                               udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(epos->bh, inode);
+                       brelse(epos->bh);
                }
                else
                        mark_inode_dirty(inode);
-               *bh = nbh;
+               epos->bh = nbh;
        }
 
-       etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
+       etype = udf_write_aext(inode, epos, eloc, elen, inc);
 
-       if (!*bh)
+       if (!epos->bh)
        {
                UDF_I_LENALLOC(inode) += adsize;
                mark_inode_dirty(inode);
        }
        else
        {
-               aed = (struct allocExtDesc *)(*bh)->b_data;
+               aed = (struct allocExtDesc *)epos->bh->b_data;
                aed->lengthAllocDescs =
                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                       udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));
+                       udf_update_tag(epos->bh->b_data, epos->offset + (inc ? 0 : adsize));
                else
-                       udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-               mark_buffer_dirty_inode(*bh, inode);
+                       udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
+               mark_buffer_dirty_inode(epos->bh, inode);
        }
 
        return etype;
 }
 
-int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
-    kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
+int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
+    kernel_lb_addr eloc, uint32_t elen, int inc)
 {
        int adsize;
        uint8_t *ptr;
 
-       if (!bh)
-               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+       if (!epos->bh)
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
        else
-       {
-               ptr = bh->b_data + *extoffset;
-               atomic_inc(&bh->b_count);
-       }
+               ptr = epos->bh->b_data + epos->offset;
 
        switch (UDF_I_ALLOCTYPE(inode))
        {
@@ -1733,40 +1855,39 @@ int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
                        return -1;
        }
 
-       if (bh)
+       if (epos->bh)
        {
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
                {
-                       struct allocExtDesc *aed = (struct allocExtDesc *)(bh)->b_data;
-                       udf_update_tag((bh)->b_data,
+                       struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data;
+                       udf_update_tag(epos->bh->b_data,
                                le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
                }
-               mark_buffer_dirty_inode(bh, inode);
-               udf_release_data(bh);
+               mark_buffer_dirty_inode(epos->bh, inode);
        }
        else
                mark_inode_dirty(inode);
 
        if (inc)
-               *extoffset += adsize;
+               epos->offset += adsize;
        return (elen >> 30);
 }
 
-int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
        int8_t etype;
 
-       while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
+       while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
                (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
        {
-               *bloc = *eloc;
-               *extoffset = sizeof(struct allocExtDesc);
-               udf_release_data(*bh);
-               if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
+               epos->block = *eloc;
+               epos->offset = sizeof(struct allocExtDesc);
+               brelse(epos->bh);
+               if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0))))
                {
                        udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, *bloc, 0));
+                               udf_get_lb_pblock(inode->i_sb, epos->block, 0));
                        return -1;
                }
        }
@@ -1774,26 +1895,26 @@ int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        return etype;
 }
 
-int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
        int alen;
        int8_t etype;
        uint8_t *ptr;
 
-       if (!*bh)
+       if (!epos->bh)
        {
-               if (!(*extoffset))
-                       *extoffset = udf_file_entry_alloc_offset(inode);
-               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+               if (!epos->offset)
+                       epos->offset = udf_file_entry_alloc_offset(inode);
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
                alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
        }
        else
        {
-               if (!(*extoffset))
-                       *extoffset = sizeof(struct allocExtDesc);
-               ptr = (*bh)->b_data + *extoffset;
-               alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
+               if (!epos->offset)
+                       epos->offset = sizeof(struct allocExtDesc);
+               ptr = epos->bh->b_data + epos->offset;
+               alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs);
        }
 
        switch (UDF_I_ALLOCTYPE(inode))
@@ -1802,7 +1923,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
                {
                        short_ad *sad;
 
-                       if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
+                       if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(sad->extLength) >> 30;
@@ -1815,7 +1936,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
                {
                        long_ad *lad;
 
-                       if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
+                       if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(lad->extLength) >> 30;
@@ -1834,41 +1955,40 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
 }
 
 static int8_t
-udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
-               kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
+udf_insert_aext(struct inode *inode, struct extent_position epos,
+               kernel_lb_addr neloc, uint32_t nelen)
 {
        kernel_lb_addr oeloc;
        uint32_t oelen;
        int8_t etype;
 
-       if (bh)
-               atomic_inc(&bh->b_count);
+       if (epos.bh)
+               get_bh(epos.bh);
 
-       while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
+       while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1)
        {
-               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
+               udf_write_aext(inode, &epos, neloc, nelen, 1);
 
                neloc = oeloc;
                nelen = (etype << 30) | oelen;
        }
-       udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
-       udf_release_data(bh);
+       udf_add_aext(inode, &epos, neloc, nelen, 1);
+       brelse(epos.bh);
        return (nelen >> 30);
 }
 
-int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
-       kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
+int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+       kernel_lb_addr eloc, uint32_t elen)
 {
-       struct buffer_head *obh;
-       kernel_lb_addr obloc;
-       int oextoffset, adsize;
+       struct extent_position oepos;
+       int adsize;
        int8_t etype;
        struct allocExtDesc *aed;
 
-       if (nbh)
+       if (epos.bh)
        {
-               atomic_inc(&nbh->b_count);
-               atomic_inc(&nbh->b_count);
+               get_bh(epos.bh);
+               get_bh(epos.bh);
        }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -1878,80 +1998,77 @@ int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset
        else
                adsize = 0;
 
-       obh = nbh;
-       obloc = nbloc;
-       oextoffset = nextoffset;
-
-       if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
+       oepos = epos;
+       if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
                return -1;
 
-       while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
+       while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
        {
-               udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
-               if (obh != nbh)
+               udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);
+               if (oepos.bh != epos.bh)
                {
-                       obloc = nbloc;
-                       udf_release_data(obh);
-                       atomic_inc(&nbh->b_count);
-                       obh = nbh;
-                       oextoffset = nextoffset - adsize;
+                       oepos.block = epos.block;
+                       brelse(oepos.bh);
+                       get_bh(epos.bh);
+                       oepos.bh = epos.bh;
+                       oepos.offset = epos.offset - adsize;
                }
        }
        memset(&eloc, 0x00, sizeof(kernel_lb_addr));
        elen = 0;
 
-       if (nbh != obh)
+       if (epos.bh != oepos.bh)
        {
-               udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
-               udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               if (!obh)
+               udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               if (!oepos.bh)
                {
                        UDF_I_LENALLOC(inode) -= (adsize * 2);
                        mark_inode_dirty(inode);
                }
                else
                {
-                       aed = (struct allocExtDesc *)(obh)->b_data;
+                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                        aed->lengthAllocDescs =
                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag((obh)->b_data, oextoffset - (2*adsize));
+                               udf_update_tag(oepos.bh->b_data, oepos.offset - (2*adsize));
                        else
-                               udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(obh, inode);
+                               udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(oepos.bh, inode);
                }
        }
        else
        {
-               udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               if (!obh)
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               if (!oepos.bh)
                {
                        UDF_I_LENALLOC(inode) -= adsize;
                        mark_inode_dirty(inode);
                }
                else
                {
-                       aed = (struct allocExtDesc *)(obh)->b_data;
+                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                        aed->lengthAllocDescs =
                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag((obh)->b_data, oextoffset - adsize);
+                               udf_update_tag(oepos.bh->b_data, epos.offset - adsize);
                        else
-                               udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(obh, inode);
+                               udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(oepos.bh, inode);
                }
        }
        
-       udf_release_data(nbh);
-       udf_release_data(obh);
+       brelse(epos.bh);
+       brelse(oepos.bh);
        return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
+int8_t inode_bmap(struct inode *inode, sector_t block, struct extent_position *pos,
+       kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset)
 {
-       uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;
+       loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
        int8_t etype;
 
        if (block < 0)
@@ -1960,42 +2077,44 @@ int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t
                return -1;
        }
 
-       *extoffset = 0;
+       pos->offset = 0;
+       pos->block = UDF_I_LOCATION(inode);
+       pos->bh = NULL;
        *elen = 0;
-       *bloc = UDF_I_LOCATION(inode);
 
        do
        {
-               if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
+               if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1)
                {
-                       *offset = bcount - lbcount;
+                       *offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
                        UDF_I_LENEXTENTS(inode) = lbcount;
                        return -1;
                }
                lbcount += *elen;
        } while (lbcount <= bcount);
 
-       *offset = bcount + *elen - lbcount;
+       *offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits;
 
        return etype;
 }
 
-long udf_block_map(struct inode *inode, long block)
+long udf_block_map(struct inode *inode, sector_t block)
 {
-       kernel_lb_addr eloc, bloc;
-       uint32_t offset, extoffset, elen;
-       struct buffer_head *bh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
        int ret;
 
        lock_kernel();
 
-       if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
-               ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits);
+       if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
+               ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
        else
                ret = 0;
 
        unlock_kernel();
-       udf_release_data(bh);
+       brelse(epos.bh);
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
                return udf_fixed_to_variable(ret);
index cc8ca3254db11f95d669f8b93321f6ee2c61517d..a2b2a98ce78a66b8425fcb241c2ed04d56087742 100644 (file)
@@ -274,12 +274,6 @@ udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, uint32_t offset, ui
                loc.logicalBlockNum + offset, ident);
 }
 
-void udf_release_data(struct buffer_head *bh)
-{
-       if (bh)
-               brelse(bh);
-}
-
 void udf_update_tag(char *data, int length)
 {
        tag *tptr = (tag *)data;
index fe361cd19a98912ce1fec1f280d06d758ddec298..91df4928651cdbaa95f70cfa385baa8eee3819ee 100644 (file)
@@ -155,9 +155,10 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        uint8_t lfi;
        uint16_t liu;
        loff_t size;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen, offset;
-       struct buffer_head *bh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
 
        size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        f_pos = (udf_ext0_offset(dir) >> 2);
@@ -166,42 +167,41 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                fibh->sbh = fibh->ebh = NULL;
        else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-               &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
-               offset >>= dir->i_sb->s_blocksize_bits;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       brelse(epos.bh);
                        return NULL;
                }
        }
        else
        {
-               udf_release_data(bh);
+               brelse(epos.bh);
                return NULL;
        }
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh->sbh != fibh->ebh)
-                               udf_release_data(fibh->ebh);
-                       udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                               brelse(fibh->ebh);
+                       brelse(fibh->sbh);
+                       brelse(epos.bh);
                        return NULL;
                }
 
@@ -247,15 +247,15 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
                {
                        if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
                        {
-                               udf_release_data(bh);
+                               brelse(epos.bh);
                                return fi;
                        }
                }
        }
        if (fibh->sbh != fibh->ebh)
-               udf_release_data(fibh->ebh);
-       udf_release_data(fibh->sbh);
-       udf_release_data(bh);
+               brelse(fibh->ebh);
+       brelse(fibh->sbh);
+       brelse(epos.bh);
        return NULL;
 }
 
@@ -321,8 +321,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        if (udf_find_entry(dir, dentry, &fibh, &cfi))
        {
                if (fibh.sbh != fibh.ebh)
-                       udf_release_data(fibh.ebh);
-               udf_release_data(fibh.sbh);
+                       brelse(fibh.ebh);
+               brelse(fibh.sbh);
 
                inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
                if ( !inode )
@@ -353,9 +353,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        uint8_t lfi;
        uint16_t liu;
        int block;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen, offset;
-       struct buffer_head *bh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
+       struct extent_position epos = { NULL, 0, { 0, 0 }};
 
        sb = dir->i_sb;
 
@@ -384,23 +385,22 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                fibh->sbh = fibh->ebh = NULL;
        else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-               &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
-               offset >>= dir->i_sb->s_blocksize_bits;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       brelse(epos.bh);
                        *err = -EIO;
                        return NULL;
                }
@@ -418,14 +418,14 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh->sbh != fibh->ebh)
-                               udf_release_data(fibh->ebh);
-                       udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                               brelse(fibh->ebh);
+                       brelse(fibh->sbh);
+                       brelse(epos.bh);
                        *err = -EIO;
                        return NULL;
                }
@@ -455,7 +455,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                {
                        if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
                        {
-                               udf_release_data(bh);
+                               brelse(epos.bh);
                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
                                cfi->fileVersionNum = cpu_to_le16(1);
                                cfi->fileCharacteristics = 0;
@@ -478,9 +478,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                        udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
                {
                        if (fibh->sbh != fibh->ebh)
-                               udf_release_data(fibh->ebh);
-                       udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                               brelse(fibh->ebh);
+                       brelse(fibh->sbh);
+                       brelse(epos.bh);
                        *err = -EEXIST;
                        return NULL;
                }
@@ -492,25 +492,25 @@ add:
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
                sb->s_blocksize - fibh->eoffset < nfidlen)
        {
-               udf_release_data(bh);
-               bh = NULL;
+               brelse(epos.bh);
+               epos.bh = NULL;
                fibh->soffset -= udf_ext0_offset(dir);
                fibh->eoffset -= udf_ext0_offset(dir);
                f_pos -= (udf_ext0_offset(dir) >> 2);
                if (fibh->sbh != fibh->ebh)
-                       udf_release_data(fibh->ebh);
-               udf_release_data(fibh->sbh);
+                       brelse(fibh->ebh);
+               brelse(fibh->sbh);
                if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
                        return NULL;
-               bloc = UDF_I_LOCATION(dir);
+               epos.block = UDF_I_LOCATION(dir);
                eloc.logicalBlockNum = block;
                eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
                elen = dir->i_sb->s_blocksize;
-               extoffset = udf_file_entry_alloc_offset(dir);
+               epos.offset = udf_file_entry_alloc_offset(dir);
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                       extoffset += sizeof(short_ad);
+                       epos.offset += sizeof(short_ad);
                else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                       extoffset += sizeof(long_ad);
+                       epos.offset += sizeof(long_ad);
        }
 
        if (sb->s_blocksize - fibh->eoffset >= nfidlen)
@@ -519,7 +519,7 @@ add:
                fibh->eoffset += nfidlen;
                if (fibh->sbh != fibh->ebh)
                {
-                       udf_release_data(fibh->sbh);
+                       brelse(fibh->sbh);
                        fibh->sbh = fibh->ebh;
                }
 
@@ -541,7 +541,7 @@ add:
                fibh->eoffset += nfidlen - sb->s_blocksize;
                if (fibh->sbh != fibh->ebh)
                {
-                       udf_release_data(fibh->sbh);
+                       brelse(fibh->sbh);
                        fibh->sbh = fibh->ebh;
                }
 
@@ -550,14 +550,14 @@ add:
 
                if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
                {
-                       udf_release_data(bh);
-                       udf_release_data(fibh->sbh);
+                       brelse(epos.bh);
+                       brelse(fibh->sbh);
                        return NULL;
                }
 
                if (!(fibh->soffset))
                {
-                       if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
+                       if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
                                (EXT_RECORDED_ALLOCATED >> 30))
                        {
                                block = eloc.logicalBlockNum + ((elen - 1) >>
@@ -566,7 +566,7 @@ add:
                        else
                                block ++;
 
-                       udf_release_data(fibh->sbh);
+                       brelse(fibh->sbh);
                        fibh->sbh = fibh->ebh;
                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
                }
@@ -587,7 +587,7 @@ add:
        cfi->lengthOfImpUse = cpu_to_le16(0);
        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
        {
-               udf_release_data(bh);
+               brelse(epos.bh);
                dir->i_size += nfidlen;
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                        UDF_I_LENALLOC(dir) += nfidlen;
@@ -596,10 +596,10 @@ add:
        }
        else
        {
-               udf_release_data(bh);
+               brelse(epos.bh);
                if (fibh->sbh != fibh->ebh)
-                       udf_release_data(fibh->ebh);
-               udf_release_data(fibh->sbh);
+                       brelse(fibh->ebh);
+               brelse(fibh->sbh);
                *err = -EIO;
                return NULL;
        }
@@ -656,8 +656,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode, struct
                mark_inode_dirty(dir);
        }
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
        unlock_kernel();
        d_instantiate(dentry, inode);
        return 0;
@@ -701,8 +701,8 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t
        mark_inode_dirty(inode);
 
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
        d_instantiate(dentry, inode);
        err = 0;
 out:
@@ -743,7 +743,7 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
        cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
        udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
-       udf_release_data(fibh.sbh);
+       brelse(fibh.sbh);
        inode->i_mode = S_IFDIR | mode;
        if (dir->i_mode & S_ISGID)
                inode->i_mode |= S_ISGID;
@@ -766,8 +766,8 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        mark_inode_dirty(dir);
        d_instantiate(dentry, inode);
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
        err = 0;
 out:
        unlock_kernel();
@@ -781,9 +781,10 @@ static int empty_dir(struct inode *dir)
        loff_t f_pos;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        int block;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen, offset;
-       struct buffer_head *bh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
 
        f_pos = (udf_ext0_offset(dir) >> 2);
 
@@ -792,59 +793,58 @@ static int empty_dir(struct inode *dir)
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                fibh.sbh = fibh.ebh = NULL;
        else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-               &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
-               offset >>= dir->i_sb->s_blocksize_bits;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       brelse(epos.bh);
                        return 0;
                }
        }
        else
        {
-               udf_release_data(bh);
+               brelse(epos.bh);
                return 0;
        }
 
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh.sbh != fibh.ebh)
-                               udf_release_data(fibh.ebh);
-                       udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                               brelse(fibh.ebh);
+                       brelse(fibh.sbh);
+                       brelse(epos.bh);
                        return 0;
                }
 
                if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
                {
                        if (fibh.sbh != fibh.ebh)
-                               udf_release_data(fibh.ebh);
-                       udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                               brelse(fibh.ebh);
+                       brelse(fibh.sbh);
+                       brelse(epos.bh);
                        return 0;
                }
        }
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
-       udf_release_data(bh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
+       brelse(epos.bh);
        return 1;
 }
 
@@ -878,14 +878,14 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
                        inode->i_nlink);
        clear_nlink(inode);
        inode->i_size = 0;
-       inode_dec_link_count(inode);
+       inode_dec_link_count(dir);
        inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
        mark_inode_dirty(dir);
 
 end_rmdir:
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
 out:
        unlock_kernel();
        return retval;
@@ -928,8 +928,8 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
 
 end_unlink:
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
 out:
        unlock_kernel();
        return retval;
@@ -941,7 +941,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
        struct pathComponent *pc;
        char *compstart;
        struct udf_fileident_bh fibh;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL,  0, {0, 0}};
        int eoffset, elen = 0;
        struct fileIdentDesc *fi;
        struct fileIdentDesc cfi;
@@ -961,33 +961,33 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 
        if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
        {
-               struct buffer_head *bh = NULL;
-               kernel_lb_addr bloc, eloc;
-               uint32_t elen, extoffset;
+               kernel_lb_addr eloc;
+               uint32_t elen;
 
                block = udf_new_block(inode->i_sb, inode,
                        UDF_I_LOCATION(inode).partitionReferenceNum,
                        UDF_I_LOCATION(inode).logicalBlockNum, &err);
                if (!block)
                        goto out_no_entry;
-               bloc = UDF_I_LOCATION(inode);
+               epos.block = UDF_I_LOCATION(inode);
+               epos.offset = udf_file_entry_alloc_offset(inode);
+               epos.bh = NULL;
                eloc.logicalBlockNum = block;
                eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
                elen = inode->i_sb->s_blocksize;
                UDF_I_LENEXTENTS(inode) = elen;
-               extoffset = udf_file_entry_alloc_offset(inode);
-               udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
-               udf_release_data(bh);
+               udf_add_aext(inode, &epos, eloc, elen, 0);
+               brelse(epos.bh);
 
                block = udf_get_pblock(inode->i_sb, block,
                        UDF_I_LOCATION(inode).partitionReferenceNum, 0);
-               bh = udf_tread(inode->i_sb, block);
-               lock_buffer(bh);
-               memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
-               set_buffer_uptodate(bh);
-               unlock_buffer(bh);
-               mark_buffer_dirty_inode(bh, inode);
-               ea = bh->b_data + udf_ext0_offset(inode);
+               epos.bh = udf_tread(inode->i_sb, block);
+               lock_buffer(epos.bh);
+               memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
+               set_buffer_uptodate(epos.bh);
+               unlock_buffer(epos.bh);
+               mark_buffer_dirty_inode(epos.bh, inode);
+               ea = epos.bh->b_data + udf_ext0_offset(inode);
        }
        else
                ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
@@ -1060,7 +1060,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
                }
        }
 
-       udf_release_data(bh);
+       brelse(epos.bh);
        inode->i_size = elen;
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
                UDF_I_LENALLOC(inode) = inode->i_size;
@@ -1089,8 +1089,8 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
                mark_inode_dirty(dir);
        }
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
        d_instantiate(dentry, inode);
        err = 0;
 
@@ -1145,8 +1145,8 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
                mark_inode_dirty(dir);
        }
        if (fibh.sbh != fibh.ebh)
-               udf_release_data(fibh.ebh);
-       udf_release_data(fibh.sbh);
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
        inc_nlink(inode);
        inode->i_ctime = current_fs_time(inode->i_sb);
        mark_inode_dirty(inode);
@@ -1174,8 +1174,8 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
        if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))
        {
                if (ofibh.sbh != ofibh.ebh)
-                       udf_release_data(ofibh.ebh);
-               udf_release_data(ofibh.sbh);
+                       brelse(ofibh.ebh);
+               brelse(ofibh.sbh);
        }
        tloc = lelb_to_cpu(ocfi.icb.extLocation);
        if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0)
@@ -1188,8 +1188,8 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
                if (!new_inode)
                {
                        if (nfibh.sbh != nfibh.ebh)
-                               udf_release_data(nfibh.ebh);
-                       udf_release_data(nfibh.sbh);
+                               brelse(nfibh.ebh);
+                       brelse(nfibh.sbh);
                        nfi = NULL;
                }
        }
@@ -1290,19 +1290,19 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
        if (ofi)
        {
                if (ofibh.sbh != ofibh.ebh)
-                       udf_release_data(ofibh.ebh);
-               udf_release_data(ofibh.sbh);
+                       brelse(ofibh.ebh);
+               brelse(ofibh.sbh);
        }
 
        retval = 0;
 
 end_rename:
-       udf_release_data(dir_bh);
+       brelse(dir_bh);
        if (nfi)
        {
                if (nfibh.sbh != nfibh.ebh)
-                       udf_release_data(nfibh.ebh);
-               udf_release_data(nfibh.sbh);
+                       brelse(nfibh.ebh);
+               brelse(nfibh.sbh);
        }
        unlock_kernel();
        return retval;
index dabf2b841db83c1ad00139e7c94054a858caa263..467a26171cd96e547d8f50c464727ff9e5afade5 100644 (file)
@@ -81,7 +81,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, uint16_t
 
        loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
 
-       udf_release_data(bh);
+       brelse(bh);
 
        if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
        {
index 023b304fdd996a85415f79226dd362d993145d7c..9b8644a06e53b98f257a54198abb8894abbab85d 100644 (file)
@@ -563,7 +563,7 @@ udf_vrs(struct super_block *sb, int silent)
 
                if (vsd->stdIdent[0] == 0)
                {
-                       udf_release_data(bh);
+                       brelse(bh);
                        break;
                }
                else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN))
@@ -596,7 +596,7 @@ udf_vrs(struct super_block *sb, int silent)
                }
                else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01, VSD_STD_ID_LEN))
                {
-                       udf_release_data(bh);
+                       brelse(bh);
                        break;
                }
                else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN))
@@ -607,7 +607,7 @@ udf_vrs(struct super_block *sb, int silent)
                {
                        nsr03 = sector;
                }
-               udf_release_data(bh);
+               brelse(bh);
        }
 
        if (nsr03)
@@ -673,7 +673,7 @@ udf_find_anchor(struct super_block *sb)
                        {
                                ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
                                location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
-                               udf_release_data(bh);
+                               brelse(bh);
                        }
 
                        if (ident == TAG_IDENT_AVDP)
@@ -708,7 +708,7 @@ udf_find_anchor(struct super_block *sb)
                                {
                                        ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
                                        location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
-                                       udf_release_data(bh);
+                                       brelse(bh);
                                }
        
                                if (ident == TAG_IDENT_AVDP &&
@@ -727,7 +727,7 @@ udf_find_anchor(struct super_block *sb)
                                        {
                                                ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
                                                location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
-                                               udf_release_data(bh);
+                                               brelse(bh);
                                        }
        
                                        if (ident == TAG_IDENT_AVDP &&
@@ -749,7 +749,7 @@ udf_find_anchor(struct super_block *sb)
                {
                        ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
                        location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
-                       udf_release_data(bh);
+                       brelse(bh);
 
                        if (ident == TAG_IDENT_AVDP && location == 256)
                                UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
@@ -766,7 +766,7 @@ udf_find_anchor(struct super_block *sb)
                        }
                        else
                        {
-                               udf_release_data(bh);
+                               brelse(bh);
                                if ((ident != TAG_IDENT_AVDP) && (i ||
                                        (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE)))
                                {
@@ -795,7 +795,7 @@ udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr
                        return 1;
                else if (ident != TAG_IDENT_FSD)
                {
-                       udf_release_data(bh);
+                       brelse(bh);
                        return 1;
                }
                        
@@ -834,7 +834,7 @@ udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr
                                                newfileset.logicalBlockNum += 1 +
                                                        ((le32_to_cpu(sp->numOfBytes) + sizeof(struct spaceBitmapDesc) - 1)
                                                                >> sb->s_blocksize_bits);
-                                               udf_release_data(bh);
+                                               brelse(bh);
                                                break;
                                        }
                                        case TAG_IDENT_FSD:
@@ -845,7 +845,7 @@ udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr
                                        default:
                                        {
                                                newfileset.logicalBlockNum ++;
-                                               udf_release_data(bh);
+                                               brelse(bh);
                                                bh = NULL;
                                                break;
                                        }
@@ -865,7 +865,7 @@ udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr
 
                UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum;
                udf_load_fileset(sb, bh, root);
-               udf_release_data(bh);
+               brelse(bh);
                return 0;
        }
        return 1;
@@ -1083,7 +1083,7 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, kernel_lb_a
                                                if (ident != 0 ||
                                                        strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
                                                {
-                                                       udf_release_data(UDF_SB_TYPESPAR(sb,i).s_spar_map[j]);
+                                                       brelse(UDF_SB_TYPESPAR(sb,i).s_spar_map[j]);
                                                        UDF_SB_TYPESPAR(sb,i).s_spar_map[j] = NULL;
                                                }
                                        }
@@ -1137,12 +1137,12 @@ udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
                        udf_load_logicalvolint(sb, leea_to_cpu(UDF_SB_LVID(sb)->nextIntegrityExt));
                
                if (UDF_SB_LVIDBH(sb) != bh)
-                       udf_release_data(bh);
+                       brelse(bh);
                loc.extLength -= sb->s_blocksize;
                loc.extLocation ++;
        }
        if (UDF_SB_LVIDBH(sb) != bh)
-               udf_release_data(bh);
+               brelse(bh);
 }
 
 /*
@@ -1245,7 +1245,7 @@ udf_process_sequence(struct super_block *sb, long block, long lastblock, kernel_
                                        done = 1;
                                break;
                }
-               udf_release_data(bh);
+               brelse(bh);
        }
        for (i=0; i<VDS_POS_LENGTH; i++)
        {
@@ -1267,10 +1267,10 @@ udf_process_sequence(struct super_block *sb, long block, long lastblock, kernel_
                                        gd = (struct generic_desc *)bh2->b_data;
                                        if (ident == TAG_IDENT_PD)
                                                udf_load_partdesc(sb, bh2);
-                                       udf_release_data(bh2);
+                                       brelse(bh2);
                                }
                        }
-                       udf_release_data(bh);
+                       brelse(bh);
                }
        }
 
@@ -1333,7 +1333,7 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
                        reserve_e = reserve_e >> sb->s_blocksize_bits;
                        reserve_e += reserve_s;
 
-                       udf_release_data(bh);
+                       brelse(bh);
 
                        /* Process the main & reserve sequences */
                        /* responsible for finding the PartitionDesc(s) */
@@ -1403,12 +1403,14 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
 
                                        pos = udf_block_map(UDF_SB_VAT(sb), 0);
                                        bh = sb_bread(sb, pos);
+                                       if (!bh)
+                                               return 1;
                                        UDF_SB_TYPEVIRT(sb,i).s_start_offset =
                                                le16_to_cpu(((struct virtualAllocationTable20 *)bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb)))->lengthHeader) +
                                                        udf_ext0_offset(UDF_SB_VAT(sb));
                                        UDF_SB_TYPEVIRT(sb,i).s_num_entries = (UDF_SB_VAT(sb)->i_size -
                                                UDF_SB_TYPEVIRT(sb,i).s_start_offset) >> 2;
-                                       udf_release_data(bh);
+                                       brelse(bh);
                                }
                                UDF_SB_PARTROOT(sb,i) = udf_get_pblock(sb, 0, i, 0);
                                UDF_SB_PARTLEN(sb,i) = UDF_SB_PARTLEN(sb,ino.partitionReferenceNum);
@@ -1661,7 +1663,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                iput(inode);
                goto error_out;
        }
-       sb->s_maxbytes = 1<<30;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
        return 0;
 
 error_out:
@@ -1680,7 +1682,7 @@ error_out:
                if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
                {
                        for (i=0; i<4; i++)
-                               udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
+                               brelse(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
                }
        }
 #ifdef CONFIG_UDF_NLS
@@ -1689,7 +1691,7 @@ error_out:
 #endif
        if (!(sb->s_flags & MS_RDONLY))
                udf_close_lvid(sb);
-       udf_release_data(UDF_SB_LVIDBH(sb));
+       brelse(UDF_SB_LVIDBH(sb));
        UDF_SB_FREE(sb);
        kfree(sbi);
        sb->s_fs_info = NULL;
@@ -1758,7 +1760,7 @@ udf_put_super(struct super_block *sb)
                if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
                {
                        for (i=0; i<4; i++)
-                               udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
+                               brelse(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
                }
        }
 #ifdef CONFIG_UDF_NLS
@@ -1767,7 +1769,7 @@ udf_put_super(struct super_block *sb)
 #endif
        if (!(sb->s_flags & MS_RDONLY))
                udf_close_lvid(sb);
-       udf_release_data(UDF_SB_LVIDBH(sb));
+       brelse(UDF_SB_LVIDBH(sb));
        UDF_SB_FREE(sb);
        kfree(sb->s_fs_info);
        sb->s_fs_info = NULL;
@@ -1837,7 +1839,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
        }
        else if (ident != TAG_IDENT_SBD)
        {
-               udf_release_data(bh);
+               brelse(bh);
                printk(KERN_ERR "udf: udf_count_free failed\n");
                goto out;
        }
@@ -1859,7 +1861,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
                }
                if ( bytes )
                {
-                       udf_release_data(bh);
+                       brelse(bh);
                        newblock = udf_get_lb_pblock(sb, loc, ++block);
                        bh = udf_tread(sb, newblock);
                        if (!bh)
@@ -1871,7 +1873,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
                        ptr = (uint8_t *)bh->b_data;
                }
        }
-       udf_release_data(bh);
+       brelse(bh);
 
 out:
        unlock_kernel();
@@ -1883,21 +1885,20 @@ static unsigned int
 udf_count_free_table(struct super_block *sb, struct inode * table)
 {
        unsigned int accum = 0;
-       uint32_t extoffset, elen;
-       kernel_lb_addr bloc, eloc;
+       uint32_t elen;
+       kernel_lb_addr eloc;
        int8_t etype;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos;
 
        lock_kernel();
 
-       bloc = UDF_I_LOCATION(table);
-       extoffset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.bh = NULL;
 
-       while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
-       {
+       while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
                accum += (elen >> table->i_sb->s_blocksize_bits);
-       }
-       udf_release_data(bh);
+       brelse(epos.bh);
 
        unlock_kernel();
 
index ba068a7865630bb07a8f968a91d20c13245c143f..12613b680cc4aa2e93db48c27d5f0b2ec16b82a9 100644 (file)
@@ -95,7 +95,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        }
 
        udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
-       udf_release_data(bh);
+       brelse(bh);
 
        unlock_kernel();
        SetPageUptodate(page);
index 0abd66ce36ea042091bd6564ff17b003257a2d24..77975ae291a55410c72db68025add299aa0c06f5 100644 (file)
@@ -28,8 +28,8 @@
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
-       kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
+static void extent_trunc(struct inode * inode, struct extent_position *epos,
+       kernel_lb_addr eloc, int8_t etype, uint32_t elen, uint32_t nelen)
 {
        kernel_lb_addr neloc = { 0, 0 };
        int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
@@ -49,7 +49,7 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
        if (elen != nelen)
        {
-               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
+               udf_write_aext(inode, epos, neloc, nelen, 0);
                if (last_block - first_block > 0)
                {
                        if (etype == (EXT_RECORDED_ALLOCATED >> 30))
@@ -63,18 +63,16 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
 void udf_discard_prealloc(struct inode * inode)
 {
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset = 0, elen, nelen;
+       struct extent_position epos = { NULL, 0, {0, 0}};
+       kernel_lb_addr eloc;
+       uint32_t elen, nelen;
        uint64_t lbcount = 0;
        int8_t etype = -1, netype;
-       struct buffer_head *bh = NULL;
        int adsize;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
                inode->i_size == UDF_I_LENEXTENTS(inode))
-       {
                return;
-       }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -83,52 +81,58 @@ void udf_discard_prealloc(struct inode * inode)
        else
                adsize = 0;
 
-       bloc = UDF_I_LOCATION(inode);
+       epos.block = UDF_I_LOCATION(inode);
 
-       while ((netype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+       /* Find the last extent in the file */
+       while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
        {
                etype = netype;
                lbcount += elen;
-               if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
+               if (lbcount > inode->i_size && lbcount - elen < inode->i_size)
                {
+                       WARN_ON(lbcount - inode->i_size >= inode->i_sb->s_blocksize);
                        nelen = elen - (lbcount - inode->i_size);
-                       extent_trunc(inode, bloc, extoffset-adsize, eloc, etype, elen, bh, nelen);
+                       epos.offset -= adsize;
+                       extent_trunc(inode, &epos, eloc, etype, elen, nelen);
+                       epos.offset += adsize;
                        lbcount = inode->i_size;
                }
        }
-       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
-       {
-               extoffset -= adsize;
+       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
+               epos.offset -= adsize;
                lbcount -= elen;
-               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
-               if (!bh)
+               extent_trunc(inode, &epos, eloc, etype, elen, 0);
+               if (!epos.bh)
                {
-                       UDF_I_LENALLOC(inode) = extoffset - udf_file_entry_alloc_offset(inode);
+                       UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode);
                        mark_inode_dirty(inode);
                }
                else
                {
-                       struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
-                       aed->lengthAllocDescs = cpu_to_le32(extoffset - sizeof(struct allocExtDesc));
+                       struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
+                       aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc));
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag(bh->b_data, extoffset);
+                               udf_update_tag(epos.bh->b_data, epos.offset);
                        else
-                               udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(bh, inode);
+                               udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(epos.bh, inode);
                }
        }
        UDF_I_LENEXTENTS(inode) = lbcount;
 
-       udf_release_data(bh);
+       WARN_ON(lbcount != inode->i_size);
+       brelse(epos.bh);
 }
 
 void udf_truncate_extents(struct inode * inode)
 {
-       kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
-       uint32_t extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
+       struct extent_position epos;
+       kernel_lb_addr eloc, neloc = { 0, 0 };
+       uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
        int8_t etype;
-       int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-       struct buffer_head *bh = NULL;
+       struct super_block *sb = inode->i_sb;
+       sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
+       loff_t byte_offset;
        int adsize;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -136,158 +140,130 @@ void udf_truncate_extents(struct inode * inode)
        else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
                adsize = sizeof(long_ad);
        else
-               adsize = 0;
+               BUG();
 
-       etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-       offset += (inode->i_size & (inode->i_sb->s_blocksize - 1));
+       etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
+       byte_offset = (offset << sb->s_blocksize_bits) + (inode->i_size & (sb->s_blocksize-1));
        if (etype != -1)
        {
-               extoffset -= adsize;
-               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset);
-               extoffset += adsize;
-
-               if (offset)
-                       lenalloc = extoffset;
+               epos.offset -= adsize;
+               extent_trunc(inode, &epos, eloc, etype, elen, byte_offset);
+               epos.offset += adsize;
+               if (byte_offset)
+                       lenalloc = epos.offset;
                else
-                       lenalloc = extoffset - adsize;
+                       lenalloc = epos.offset - adsize;
 
-               if (!bh)
+               if (!epos.bh)
                        lenalloc -= udf_file_entry_alloc_offset(inode);
                else
                        lenalloc -= sizeof(struct allocExtDesc);
 
-               while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
+               while ((etype = udf_current_aext(inode, &epos, &eloc, &elen, 0)) != -1)
                {
                        if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
                        {
-                               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
-                               extoffset = 0;
-                               if (lelen)
+                               udf_write_aext(inode, &epos, neloc, nelen, 0);
+                               if (indirect_ext_len)
                                {
-                                       if (!bh)
+                                       /* We managed to free all extents in the
+                                        * indirect extent - free it too */
+                                       if (!epos.bh)
                                                BUG();
-                                       else
-                                               memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
-                                       udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
+                                       udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len);
                                }
                                else
                                {
-                                       if (!bh)
+                                       if (!epos.bh)
                                        {
                                                UDF_I_LENALLOC(inode) = lenalloc;
                                                mark_inode_dirty(inode);
                                        }
                                        else
                                        {
-                                               struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+                                               struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
                                                aed->lengthAllocDescs = cpu_to_le32(lenalloc);
-                                               if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                                                       udf_update_tag(bh->b_data, lenalloc +
+                                               if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201)
+                                                       udf_update_tag(epos.bh->b_data, lenalloc +
                                                                sizeof(struct allocExtDesc));
                                                else
-                                                       udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                                               mark_buffer_dirty_inode(bh, inode);
+                                                       udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                                               mark_buffer_dirty_inode(epos.bh, inode);
                                        }
                                }
-
-                               udf_release_data(bh);
-                               extoffset = sizeof(struct allocExtDesc);
-                               bloc = eloc;
-                               bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
+                               brelse(epos.bh);
+                               epos.offset = sizeof(struct allocExtDesc);
+                               epos.block = eloc;
+                               epos.bh = udf_tread(sb, udf_get_lb_pblock(sb, eloc, 0));
                                if (elen)
-                                       lelen = (elen + inode->i_sb->s_blocksize - 1) >>
-                                               inode->i_sb->s_blocksize_bits;
+                                       indirect_ext_len = (elen +
+                                               sb->s_blocksize - 1) >>
+                                               sb->s_blocksize_bits;
                                else
-                                       lelen = 1;
+                                       indirect_ext_len = 1;
                        }
                        else
                        {
-                               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
-                               extoffset += adsize;
+                               extent_trunc(inode, &epos, eloc, etype, elen, 0);
+                               epos.offset += adsize;
                        }
                }
 
-               if (lelen)
+               if (indirect_ext_len)
                {
-                       if (!bh)
+                       if (!epos.bh)
                                BUG();
-                       else
-                               memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
-                       udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
+                       udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len);
                }
                else
                {
-                       if (!bh)
+                       if (!epos.bh)
                        {
                                UDF_I_LENALLOC(inode) = lenalloc;
                                mark_inode_dirty(inode);
                        }
                        else
                        {
-                               struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+                               struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
                                aed->lengthAllocDescs = cpu_to_le32(lenalloc);
-                               if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                                       udf_update_tag(bh->b_data, lenalloc +
+                               if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201)
+                                       udf_update_tag(epos.bh->b_data, lenalloc +
                                                sizeof(struct allocExtDesc));
                                else
-                                       udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                               mark_buffer_dirty_inode(bh, inode);
+                                       udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                               mark_buffer_dirty_inode(epos.bh, inode);
                        }
                }
        }
        else if (inode->i_size)
        {
-               if (offset)
+               if (byte_offset)
                {
+                       kernel_long_ad extent;
+
                        /*
                         *  OK, there is not extent covering inode->i_size and
                         *  no extent above inode->i_size => truncate is
-                        *  extending the file by 'offset'.
+                        *  extending the file by 'offset' blocks.
                         */
-                       if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
-                           (bh && extoffset == sizeof(struct allocExtDesc))) {
-                               /* File has no extents at all! */
-                               memset(&eloc, 0x00, sizeof(kernel_lb_addr));
-                               elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
-                               udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
+                       if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
+                           (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
+                               /* File has no extents at all or has empty last
+                                * indirect extent! Create a fake extent... */
+                               extent.extLocation.logicalBlockNum = 0;
+                               extent.extLocation.partitionReferenceNum = 0;
+                               extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
                        }
                        else {
-                               extoffset -= adsize;
-                               etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
-                               if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
-                               {
-                                       extoffset -= adsize;
-                                       elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
-                                       udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
-                               }
-                               else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
-                               {
-                                       kernel_lb_addr neloc = { 0, 0 };
-                                       extoffset -= adsize;
-                                       nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
-                                               ((elen + offset + inode->i_sb->s_blocksize - 1) &
-                                               ~(inode->i_sb->s_blocksize - 1));
-                                       udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
-                                       udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
-                               }
-                               else
-                               {
-                                       if (elen & (inode->i_sb->s_blocksize - 1))
-                                       {
-                                               extoffset -= adsize;
-                                               elen = EXT_RECORDED_ALLOCATED |
-                                                       ((elen + inode->i_sb->s_blocksize - 1) &
-                                                       ~(inode->i_sb->s_blocksize - 1));
-                                               udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
-                                       }
-                                       memset(&eloc, 0x00, sizeof(kernel_lb_addr));
-                                       elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
-                                       udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
-                               }
+                               epos.offset -= adsize;
+                               etype = udf_next_aext(inode, &epos,
+                                       &extent.extLocation, &extent.extLength, 0);
+                               extent.extLength |= etype << 30;
                        }
+                       udf_extend_file(inode, &epos, &extent, offset+((inode->i_size & (sb->s_blocksize-1)) != 0));
                }
        }
        UDF_I_LENEXTENTS(inode) = inode->i_size;
 
-       udf_release_data(bh);
+       brelse(epos.bh);
 }
index 110f8d62616f4fa513c0fbd123e7292e92793faf..3b2e6c8cb15151389b7e4e2edc6cbc87e592952d 100644 (file)
@@ -93,7 +93,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
        for (i=0; i<nr_groups; i++)\
        {\
                if (UDF_SB_BITMAP(X,Y,Z,i))\
-                       udf_release_data(UDF_SB_BITMAP(X,Y,Z,i));\
+                       brelse(UDF_SB_BITMAP(X,Y,Z,i));\
        }\
        if (size <= PAGE_SIZE)\
                kfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
index ee1dece1f6f513d9411e9a573a151dc65469f10a..67ded289497cfc3ba1e88a6f67d86f0fa6685c5d 100644 (file)
@@ -77,6 +77,13 @@ struct ustr
        uint8_t u_len;
 };
 
+struct extent_position {
+       struct buffer_head *bh;
+       uint32_t offset;
+       kernel_lb_addr block;
+};
+
+
 /* super.c */
 extern void udf_error(struct super_block *, const char *, const char *, ...);
 extern void udf_warning(struct super_block *, const char *, const char *, ...);
@@ -98,13 +105,14 @@ extern void udf_read_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
 extern int udf_write_inode(struct inode *, int);
-extern long udf_block_map(struct inode *, long);
-extern int8_t inode_bmap(struct inode *, int, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
-extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
-extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
-extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
+extern long udf_block_map(struct inode *, sector_t);
+extern int udf_extend_file(struct inode *, struct extent_position *, kernel_long_ad *, sector_t);
+extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
+extern int8_t udf_add_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
+extern int8_t udf_write_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
+extern int8_t udf_delete_aext(struct inode *, struct extent_position, kernel_lb_addr, uint32_t);
+extern int8_t udf_next_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
+extern int8_t udf_current_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
 
 /* misc.c */
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
@@ -113,7 +121,6 @@ extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint
 extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
 extern struct buffer_head *udf_read_ptagged(struct super_block *, kernel_lb_addr, uint32_t, uint16_t *);
-extern void udf_release_data(struct buffer_head *);
 extern void udf_update_tag(char *, int);
 extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
 
@@ -151,7 +158,7 @@ extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_
 extern int udf_fsync_file(struct file *, struct dentry *, int);
 
 /* directory.c */
-extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
 extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
index 4fb8b2e077eeeb0ae44a41771c168450437a4479..154452172f433f8a44c4965065b900ba6f2f699b 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/smp_lock.h>
 
 #include "swab.h"
 #include "util.h"
index 99cf2cb11fec4ad0090c9d2f12d966a7dadb1ef1..480f7c8c29da13ee10941f5cf5e560faffbde0a6 100644 (file)
@@ -1,8 +1,10 @@
 #include <linux/compiler.h>
+#include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/linkage.h>
 #include <linux/namei.h>
 #include <linux/sched.h>
+#include <linux/stat.h>
 #include <linux/utime.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
  * must be owner or have write permission.
  * Else, update from *times, must be owner or super user.
  */
-asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
+asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
 {
-       int error;
-       struct nameidata nd;
-       struct inode * inode;
-       struct iattr newattrs;
+       struct timespec tv[2];
 
-       error = user_path_walk(filename, &nd);
-       if (error)
-               goto out;
-       inode = nd.dentry->d_inode;
-
-       error = -EROFS;
-       if (IS_RDONLY(inode))
-               goto dput_and_out;
-
-       /* Don't worry, the checks are done in inode_change_ok() */
-       newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
-               error = -EPERM;
-               if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-                       goto dput_and_out;
-
-               error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
-               newattrs.ia_atime.tv_nsec = 0;
-               if (!error)
-                       error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
-               newattrs.ia_mtime.tv_nsec = 0;
-               if (error)
-                       goto dput_and_out;
-
-               newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-       } else {
-                error = -EACCES;
-                if (IS_IMMUTABLE(inode))
-                        goto dput_and_out;
-
-               if (current->fsuid != inode->i_uid &&
-                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
-                       goto dput_and_out;
+               if (get_user(tv[0].tv_sec, &times->actime) ||
+                   get_user(tv[1].tv_sec, &times->modtime))
+                       return -EFAULT;
+               tv[0].tv_nsec = 0;
+               tv[1].tv_nsec = 0;
        }
-       mutex_lock(&inode->i_mutex);
-       error = notify_change(nd.dentry, &newattrs);
-       mutex_unlock(&inode->i_mutex);
-dput_and_out:
-       path_release(&nd);
-out:
-       return error;
+       return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0);
 }
 
 #endif
@@ -76,18 +42,38 @@ out:
  * must be owner or have write permission.
  * Else, update from *times, must be owner or super user.
  */
-long do_utimes(int dfd, char __user *filename, struct timeval *times)
+long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags)
 {
        int error;
        struct nameidata nd;
-       struct inode * inode;
+       struct dentry *dentry;
+       struct inode *inode;
        struct iattr newattrs;
+       struct file *f = NULL;
 
-       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
-
-       if (error)
+       error = -EINVAL;
+       if (flags & ~AT_SYMLINK_NOFOLLOW)
                goto out;
-       inode = nd.dentry->d_inode;
+
+       if (filename == NULL && dfd != AT_FDCWD) {
+               error = -EINVAL;
+               if (flags & AT_SYMLINK_NOFOLLOW)
+                       goto out;
+
+               error = -EBADF;
+               f = fget(dfd);
+               if (!f)
+                       goto out;
+               dentry = f->f_path.dentry;
+       } else {
+               error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
+               if (error)
+                       goto out;
+
+               dentry = nd.dentry;
+       }
+
+       inode = dentry->d_inode;
 
        error = -EROFS;
        if (IS_RDONLY(inode))
@@ -100,11 +86,21 @@ long do_utimes(int dfd, char __user *filename, struct timeval *times)
                 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                         goto dput_and_out;
 
-               newattrs.ia_atime.tv_sec = times[0].tv_sec;
-               newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000;
-               newattrs.ia_mtime.tv_sec = times[1].tv_sec;
-               newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000;
-               newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
+               if (times[0].tv_nsec == UTIME_OMIT)
+                       newattrs.ia_valid &= ~ATTR_ATIME;
+               else if (times[0].tv_nsec != UTIME_NOW) {
+                       newattrs.ia_atime.tv_sec = times[0].tv_sec;
+                       newattrs.ia_atime.tv_nsec = times[0].tv_nsec;
+                       newattrs.ia_valid |= ATTR_ATIME_SET;
+               }
+
+               if (times[1].tv_nsec == UTIME_OMIT)
+                       newattrs.ia_valid &= ~ATTR_MTIME;
+               else if (times[1].tv_nsec != UTIME_NOW) {
+                       newattrs.ia_mtime.tv_sec = times[1].tv_sec;
+                       newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
+                       newattrs.ia_valid |= ATTR_MTIME_SET;
+               }
        } else {
                error = -EACCES;
                 if (IS_IMMUTABLE(inode))
@@ -115,21 +111,67 @@ long do_utimes(int dfd, char __user *filename, struct timeval *times)
                        goto dput_and_out;
        }
        mutex_lock(&inode->i_mutex);
-       error = notify_change(nd.dentry, &newattrs);
+       error = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
 dput_and_out:
-       path_release(&nd);
+       if (f)
+               fput(f);
+       else
+               path_release(&nd);
 out:
        return error;
 }
 
+asmlinkage long sys_utimensat(int dfd, char __user *filename, struct timespec __user *utimes, int flags)
+{
+       struct timespec tstimes[2];
+
+       if (utimes) {
+               if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
+                       return -EFAULT;
+               if ((tstimes[0].tv_nsec == UTIME_OMIT ||
+                    tstimes[0].tv_nsec == UTIME_NOW) &&
+                   tstimes[0].tv_sec != 0)
+                       return -EINVAL;
+               if ((tstimes[1].tv_nsec == UTIME_OMIT ||
+                    tstimes[1].tv_nsec == UTIME_NOW) &&
+                   tstimes[1].tv_sec != 0)
+                       return -EINVAL;
+
+               /* Nothing to do, we must not even check the path.  */
+               if (tstimes[0].tv_nsec == UTIME_OMIT &&
+                   tstimes[1].tv_nsec == UTIME_OMIT)
+                       return 0;
+       }
+
+       return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags);
+}
+
 asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
 {
        struct timeval times[2];
+       struct timespec tstimes[2];
+
+       if (utimes) {
+               if (copy_from_user(&times, utimes, sizeof(times)))
+                       return -EFAULT;
+
+               /* This test is needed to catch all invalid values.  If we
+                  would test only in do_utimes we would miss those invalid
+                  values truncated by the multiplication with 1000.  Note
+                  that we also catch UTIME_{NOW,OMIT} here which are only
+                  valid for utimensat.  */
+               if (times[0].tv_usec >= 1000000 || times[0].tv_usec < 0 ||
+                   times[1].tv_usec >= 1000000 || times[1].tv_usec < 0)
+                       return -EINVAL;
+
+               tstimes[0].tv_sec = times[0].tv_sec;
+               tstimes[0].tv_nsec = 1000 * times[0].tv_usec;
+               tstimes[1].tv_sec = times[1].tv_sec;
+               tstimes[1].tv_nsec = 1000 * times[1].tv_usec;
+       }
 
-       if (utimes && copy_from_user(&times, utimes, sizeof(times)))
-               return -EFAULT;
-       return do_utimes(dfd, filename, utimes ? times : NULL);
+       return do_utimes(dfd, filename, utimes ? tstimes : NULL, 0);
 }
 
 asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
index 38646132ab0e29ec4c8ab8a4d3c7bbb491eaeaeb..9f4568b55b0f1b1232c6b1c4ec1592c0486a53e4 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/xattr.h>
 #include <linux/namei.h>
index af168a1a98c1bf5ad6a56e1f2f513bca584f632d..c110bb002665af5dce7d73d17cbb47943826d71d 100644 (file)
@@ -43,6 +43,18 @@ static inline void mrupdate(mrlock_t *mrp)
        mrp->mr_writer = 1;
 }
 
+static inline void mraccess_nested(mrlock_t *mrp, int subclass)
+{
+       down_read_nested(&mrp->mr_lock, subclass);
+}
+
+static inline void mrupdate_nested(mrlock_t *mrp, int subclass)
+{
+       down_write_nested(&mrp->mr_lock, subclass);
+       mrp->mr_writer = 1;
+}
+
+
 static inline int mrtryaccess(mrlock_t *mrp)
 {
        return down_read_trylock(&mrp->mr_lock);
index 143ffc851c9d21376b1c928394544d59443b87e9..4475588e973a4aa922144c80b39df5948b5199ef 100644 (file)
@@ -140,10 +140,47 @@ xfs_destroy_ioend(
        mempool_free(ioend, xfs_ioend_pool);
 }
 
+/*
+ * Update on-disk file size now that data has been written to disk.
+ * The current in-memory file size is i_size.  If a write is beyond
+ * eof io_new_size will be the intended file size until i_size is
+ * updated.  If this write does not extend all the way to the valid
+ * file size then restrict this update to the end of the write.
+ */
+STATIC void
+xfs_setfilesize(
+       xfs_ioend_t             *ioend)
+{
+       xfs_inode_t             *ip;
+       xfs_fsize_t             isize;
+       xfs_fsize_t             bsize;
+
+       ip = xfs_vtoi(ioend->io_vnode);
+
+       ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
+       ASSERT(ioend->io_type != IOMAP_READ);
+
+       if (unlikely(ioend->io_error))
+               return;
+
+       bsize = ioend->io_offset + ioend->io_size;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+       isize = MAX(ip->i_size, ip->i_iocore.io_new_size);
+       isize = MIN(isize, bsize);
+
+       if (ip->i_d.di_size < isize) {
+               ip->i_d.di_size = isize;
+               ip->i_update_core = 1;
+               ip->i_update_size = 1;
+       }
+
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+}
+
 /*
  * Buffered IO write completion for delayed allocate extents.
- * TODO: Update ondisk isize now that we know the file data
- * has been flushed (i.e. the notorious "NULL file" problem).
  */
 STATIC void
 xfs_end_bio_delalloc(
@@ -152,6 +189,7 @@ xfs_end_bio_delalloc(
        xfs_ioend_t             *ioend =
                container_of(work, xfs_ioend_t, io_work);
 
+       xfs_setfilesize(ioend);
        xfs_destroy_ioend(ioend);
 }
 
@@ -165,6 +203,7 @@ xfs_end_bio_written(
        xfs_ioend_t             *ioend =
                container_of(work, xfs_ioend_t, io_work);
 
+       xfs_setfilesize(ioend);
        xfs_destroy_ioend(ioend);
 }
 
@@ -184,8 +223,23 @@ xfs_end_bio_unwritten(
        xfs_off_t               offset = ioend->io_offset;
        size_t                  size = ioend->io_size;
 
-       if (likely(!ioend->io_error))
+       if (likely(!ioend->io_error)) {
                bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
+               xfs_setfilesize(ioend);
+       }
+       xfs_destroy_ioend(ioend);
+}
+
+/*
+ * IO read completion for regular, written extents.
+ */
+STATIC void
+xfs_end_bio_read(
+       struct work_struct      *work)
+{
+       xfs_ioend_t             *ioend =
+               container_of(work, xfs_ioend_t, io_work);
+
        xfs_destroy_ioend(ioend);
 }
 
@@ -224,6 +278,8 @@ xfs_alloc_ioend(
                INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten);
        else if (type == IOMAP_DELAY)
                INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc);
+       else if (type == IOMAP_READ)
+               INIT_WORK(&ioend->io_work, xfs_end_bio_read);
        else
                INIT_WORK(&ioend->io_work, xfs_end_bio_written);
 
@@ -913,7 +969,7 @@ xfs_page_state_convert(
        bh = head = page_buffers(page);
        offset = page_offset(page);
        flags = -1;
-       type = 0;
+       type = IOMAP_READ;
 
        /* TODO: cleanup count and page_dirty */
 
@@ -999,7 +1055,7 @@ xfs_page_state_convert(
                         * That means it must already have extents allocated
                         * underneath it. Map the extent by reading it.
                         */
-                       if (!iomap_valid || type != 0) {
+                       if (!iomap_valid || type != IOMAP_READ) {
                                flags = BMAPI_READ;
                                size = xfs_probe_cluster(inode, page, bh,
                                                                head, 1);
@@ -1010,7 +1066,7 @@ xfs_page_state_convert(
                                iomap_valid = xfs_iomap_valid(&iomap, offset);
                        }
 
-                       type = 0;
+                       type = IOMAP_READ;
                        if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
                                ASSERT(buffer_mapped(bh));
                                if (iomap_valid)
@@ -1356,12 +1412,21 @@ xfs_end_io_direct(
         * completion handler in the future, in which case all this can
         * go away.
         */
-       if (private && size > 0) {
-               ioend->io_offset = offset;
-               ioend->io_size = size;
+       ioend->io_offset = offset;
+       ioend->io_size = size;
+       if (ioend->io_type == IOMAP_READ) {
+               xfs_finish_ioend(ioend);
+       } else if (private && size > 0) {
                xfs_finish_ioend(ioend);
        } else {
-               xfs_destroy_ioend(ioend);
+               /*
+                * A direct I/O write ioend starts it's life in unwritten
+                * state in case they map an unwritten extent.  This write
+                * didn't map an unwritten extent so switch it's completion
+                * handler.
+                */
+               INIT_WORK(&ioend->io_work, xfs_end_bio_written);
+               xfs_finish_ioend(ioend);
        }
 
        /*
@@ -1392,15 +1457,15 @@ xfs_vm_direct_IO(
        if (error)
                return -error;
 
-       iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
-
        if (rw == WRITE) {
+               iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
                ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
                        iomap.iomap_target->bt_bdev,
                        iov, offset, nr_segs,
                        xfs_get_blocks_direct,
                        xfs_end_io_direct);
        } else {
+               iocb->private = xfs_alloc_ioend(inode, IOMAP_READ);
                ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
                        iomap.iomap_target->bt_bdev,
                        iov, offset, nr_segs,
index 69e9e80735d2c5e4861dfe0545e657b9376bee46..fe4f66a5af145a31a61afac29b440c4ce1f2d5d6 100644 (file)
@@ -1426,7 +1426,7 @@ xfs_free_bufhash(
 /*
  *     buftarg list for delwrite queue processing
  */
-LIST_HEAD(xfs_buftarg_list);
+static LIST_HEAD(xfs_buftarg_list);
 static DEFINE_SPINLOCK(xfs_buftarg_lock);
 
 STATIC void
@@ -1867,3 +1867,11 @@ xfs_buf_terminate(void)
        ktrace_free(xfs_buf_trace_buf);
 #endif
 }
+
+#ifdef CONFIG_KDB_MODULES
+struct list_head *
+xfs_get_buftarg_list(void)
+{
+       return &xfs_buftarg_list;
+}
+#endif
index 9e8ef8fef39fff7f5c58d00209b42bdd0d60569e..b6241f6201a5e89803bc5e63dad2e336850765a2 100644 (file)
@@ -411,6 +411,9 @@ extern void xfs_free_buftarg(xfs_buftarg_t *, int);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
+#ifdef CONFIG_KDB_MODULES
+extern struct list_head *xfs_get_buftarg_list(void);
+#endif
 
 #define xfs_getsize_buftarg(buftarg)   block_size((buftarg)->bt_bdev)
 #define xfs_readonly_buftarg(buftarg)  bdev_read_only((buftarg)->bt_bdev)
index dc0562828e760958b22242153111e928f317dbd5..2eb87cd082af5592bc354b8d1698a7f3f7b60910 100644 (file)
@@ -35,7 +35,7 @@ fs_tosspages(
                truncate_inode_pages(ip->i_mapping, first);
 }
 
-void
+int
 fs_flushinval_pages(
        bhv_desc_t      *bdp,
        xfs_off_t       first,
@@ -44,13 +44,16 @@ fs_flushinval_pages(
 {
        bhv_vnode_t     *vp = BHV_TO_VNODE(bdp);
        struct inode    *ip = vn_to_inode(vp);
+       int             ret = 0;
 
        if (VN_CACHED(vp)) {
                if (VN_TRUNC(vp))
                        VUNTRUNCATE(vp);
-               filemap_write_and_wait(ip->i_mapping);
-               truncate_inode_pages(ip->i_mapping, first);
+               ret = filemap_write_and_wait(ip->i_mapping);
+               if (!ret)
+                       truncate_inode_pages(ip->i_mapping, first);
        }
+       return ret;
 }
 
 int
@@ -63,14 +66,18 @@ fs_flush_pages(
 {
        bhv_vnode_t     *vp = BHV_TO_VNODE(bdp);
        struct inode    *ip = vn_to_inode(vp);
+       int             ret = 0;
+       int             ret2;
 
        if (VN_DIRTY(vp)) {
                if (VN_TRUNC(vp))
                        VUNTRUNCATE(vp);
-               filemap_fdatawrite(ip->i_mapping);
+               ret = filemap_fdatawrite(ip->i_mapping);
                if (flags & XFS_B_ASYNC)
-                       return 0;
-               filemap_fdatawait(ip->i_mapping);
+                       return ret;
+               ret2 = filemap_fdatawait(ip->i_mapping);
+               if (!ret)
+                       ret = ret2;
        }
-       return 0;
+       return ret;
 }
index aee9ccdd18f76facd65e8a0b6d92033f5b91c5d0..c1b53118a3030d0343cc3408aae53ddb267ef922 100644 (file)
@@ -23,7 +23,7 @@ extern int  fs_noerr(void);
 extern int  fs_nosys(void);
 extern void fs_noval(void);
 extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-extern void fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
+extern int  fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 extern int  fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
 
 #endif /* __XFS_FS_SUBR_H__ */
index ff8d64eba9f8d4e20ba3457276b22ab655ab9993..86fb671a8bccf80ba0eba43d98e3fb4bee4ad41b 100644 (file)
@@ -191,7 +191,7 @@ xfs_read(
        struct file             *file = iocb->ki_filp;
        struct inode            *inode = file->f_mapping->host;
        size_t                  size = 0;
-       ssize_t                 ret;
+       ssize_t                 ret = 0;
        xfs_fsize_t             n;
        xfs_inode_t             *ip;
        xfs_mount_t             *mp;
@@ -224,7 +224,7 @@ xfs_read(
                                mp->m_rtdev_targp : mp->m_ddev_targp;
                if ((*offset & target->bt_smask) ||
                    (size & target->bt_smask)) {
-                       if (*offset == ip->i_d.di_size) {
+                       if (*offset == ip->i_size) {
                                return (0);
                        }
                        return -XFS_ERROR(EINVAL);
@@ -263,9 +263,13 @@ xfs_read(
 
        if (unlikely(ioflags & IO_ISDIRECT)) {
                if (VN_CACHED(vp))
-                       bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
+                       ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
                                                 -1, FI_REMAPF_LOCKED);
                mutex_unlock(&inode->i_mutex);
+               if (ret) {
+                       xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+                       return ret;
+               }
        }
 
        xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
@@ -383,9 +387,10 @@ xfs_splice_write(
 {
        xfs_inode_t             *ip = XFS_BHVTOI(bdp);
        xfs_mount_t             *mp = ip->i_mount;
+       xfs_iocore_t            *io = &ip->i_iocore;
        ssize_t                 ret;
        struct inode            *inode = outfilp->f_mapping->host;
-       xfs_fsize_t             isize;
+       xfs_fsize_t             isize, new_size;
 
        XFS_STATS_INC(xs_write_calls);
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -406,6 +411,14 @@ xfs_splice_write(
                        return -error;
                }
        }
+
+       new_size = *ppos + count;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       if (new_size > ip->i_size)
+               io->io_new_size = new_size;
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
        xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
                           pipe, count, *ppos, ioflags);
        ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
@@ -416,14 +429,18 @@ xfs_splice_write(
        if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
                *ppos = isize;
 
-       if (*ppos > ip->i_d.di_size) {
+       if (*ppos > ip->i_size) {
                xfs_ilock(ip, XFS_ILOCK_EXCL);
-               if (*ppos > ip->i_d.di_size) {
-                       ip->i_d.di_size = *ppos;
-                       i_size_write(inode, *ppos);
-                       ip->i_update_core = 1;
-                       ip->i_update_size = 1;
-               }
+               if (*ppos > ip->i_size)
+                       ip->i_size = *ppos;
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       }
+
+       if (io->io_new_size) {
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               io->io_new_size = 0;
+               if (ip->i_d.di_size > ip->i_size)
+                       ip->i_d.di_size = ip->i_size;
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@ -639,37 +656,21 @@ xfs_write(
        xfs_fsize_t             isize, new_size;
        xfs_iocore_t            *io;
        bhv_vnode_t             *vp;
-       unsigned long           seg;
        int                     iolock;
        int                     eventsent = 0;
        bhv_vrwlock_t           locktype;
        size_t                  ocount = 0, count;
        loff_t                  pos;
-       int                     need_i_mutex = 1, need_flush = 0;
+       int                     need_i_mutex;
 
        XFS_STATS_INC(xs_write_calls);
 
        vp = BHV_TO_VNODE(bdp);
        xip = XFS_BHVTOI(bdp);
 
-       for (seg = 0; seg < segs; seg++) {
-               const struct iovec *iv = &iovp[seg];
-
-               /*
-                * If any segment has a negative length, or the cumulative
-                * length ever wraps negative then return -EINVAL.
-                */
-               ocount += iv->iov_len;
-               if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
-                       return -EINVAL;
-               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-                       continue;
-               if (seg == 0)
-                       return -EFAULT;
-               segs = seg;
-               ocount -= iv->iov_len;  /* This segment is no good */
-               break;
-       }
+       error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
+       if (error)
+               return error;
 
        count = ocount;
        pos = *offset;
@@ -685,39 +686,20 @@ xfs_write(
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       if (ioflags & IO_ISDIRECT) {
-               xfs_buftarg_t   *target =
-                       (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
-                               mp->m_rtdev_targp : mp->m_ddev_targp;
-
-               if ((pos & target->bt_smask) || (count & target->bt_smask))
-                       return XFS_ERROR(-EINVAL);
-
-               if (!VN_CACHED(vp) && pos < i_size_read(inode))
-                       need_i_mutex = 0;
-
-               if (VN_CACHED(vp))
-                       need_flush = 1;
-       }
-
 relock:
-       if (need_i_mutex) {
+       if (ioflags & IO_ISDIRECT) {
+               iolock = XFS_IOLOCK_SHARED;
+               locktype = VRWLOCK_WRITE_DIRECT;
+               need_i_mutex = 0;
+       } else {
                iolock = XFS_IOLOCK_EXCL;
                locktype = VRWLOCK_WRITE;
-
+               need_i_mutex = 1;
                mutex_lock(&inode->i_mutex);
-       } else {
-               iolock = XFS_IOLOCK_SHARED;
-               locktype = VRWLOCK_WRITE_DIRECT;
        }
 
        xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
 
-       isize = i_size_read(inode);
-
-       if (file->f_flags & O_APPEND)
-               *offset = isize;
-
 start:
        error = -generic_write_checks(file, &pos, &count,
                                        S_ISBLK(inode->i_mode));
@@ -726,13 +708,8 @@ start:
                goto out_unlock_mutex;
        }
 
-       new_size = pos + count;
-       if (new_size > isize)
-               io->io_new_size = new_size;
-
        if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
            !(ioflags & IO_INVIS) && !eventsent)) {
-               loff_t          savedsize = pos;
                int             dmflags = FILP_DELAY_FLAG(file);
 
                if (need_i_mutex)
@@ -743,8 +720,7 @@ start:
                                      pos, count,
                                      dmflags, &locktype);
                if (error) {
-                       xfs_iunlock(xip, iolock);
-                       goto out_unlock_mutex;
+                       goto out_unlock_internal;
                }
                xfs_ilock(xip, XFS_ILOCK_EXCL);
                eventsent = 1;
@@ -756,12 +732,35 @@ start:
                 * event prevents another call to XFS_SEND_DATA, which is
                 * what allows the size to change in the first place.
                 */
-               if ((file->f_flags & O_APPEND) && savedsize != isize) {
-                       pos = isize = xip->i_d.di_size;
+               if ((file->f_flags & O_APPEND) && pos != xip->i_size)
+                       goto start;
+       }
+
+       if (ioflags & IO_ISDIRECT) {
+               xfs_buftarg_t   *target =
+                       (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+                               mp->m_rtdev_targp : mp->m_ddev_targp;
+
+               if ((pos & target->bt_smask) || (count & target->bt_smask)) {
+                       xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
+                       return XFS_ERROR(-EINVAL);
+               }
+
+               if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
+                       xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
+                       iolock = XFS_IOLOCK_EXCL;
+                       locktype = VRWLOCK_WRITE;
+                       need_i_mutex = 1;
+                       mutex_lock(&inode->i_mutex);
+                       xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
                        goto start;
                }
        }
 
+       new_size = pos + count;
+       if (new_size > xip->i_size)
+               io->io_new_size = new_size;
+
        if (likely(!(ioflags & IO_INVIS))) {
                file_update_time(file);
                xfs_ichgtime_fast(xip, inode,
@@ -777,11 +776,11 @@ start:
         * to zero it out up to the new size.
         */
 
-       if (pos > isize) {
-               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
+       if (pos > xip->i_size) {
+               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
                if (error) {
-                       xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-                       goto out_unlock_mutex;
+                       xfs_iunlock(xip, XFS_ILOCK_EXCL);
+                       goto out_unlock_internal;
                }
        }
        xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -801,8 +800,7 @@ start:
                if (likely(!error))
                        error = -remove_suid(file->f_path.dentry);
                if (unlikely(error)) {
-                       xfs_iunlock(xip, iolock);
-                       goto out_unlock_mutex;
+                       goto out_unlock_internal;
                }
        }
 
@@ -811,11 +809,14 @@ retry:
        current->backing_dev_info = mapping->backing_dev_info;
 
        if ((ioflags & IO_ISDIRECT)) {
-               if (need_flush) {
+               if (VN_CACHED(vp)) {
+                       WARN_ON(need_i_mutex == 0);
                        xfs_inval_cached_trace(io, pos, -1,
                                        ctooff(offtoct(pos)), -1);
-                       bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
+                       error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
                                        -1, FI_REMAPF_LOCKED);
+                       if (error)
+                               goto out_unlock_internal;
                }
 
                if (need_i_mutex) {
@@ -843,7 +844,6 @@ retry:
                        pos += ret;
                        count -= ret;
 
-                       need_i_mutex = 1;
                        ioflags &= ~IO_ISDIRECT;
                        xfs_iunlock(xip, iolock);
                        goto relock;
@@ -870,12 +870,12 @@ retry:
                error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
                                DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
                                0, 0, 0); /* Delay flag intentionally  unused */
-               if (error)
-                       goto out_nounlocks;
                if (need_i_mutex)
                        mutex_lock(&inode->i_mutex);
                xfs_rwlock(bdp, locktype);
-               pos = xip->i_d.di_size;
+               if (error)
+                       goto out_unlock_internal;
+               pos = xip->i_size;
                ret = 0;
                goto retry;
        }
@@ -884,14 +884,10 @@ retry:
        if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
                *offset = isize;
 
-       if (*offset > xip->i_d.di_size) {
+       if (*offset > xip->i_size) {
                xfs_ilock(xip, XFS_ILOCK_EXCL);
-               if (*offset > xip->i_d.di_size) {
-                       xip->i_d.di_size = *offset;
-                       i_size_write(inode, *offset);
-                       xip->i_update_core = 1;
-                       xip->i_update_size = 1;
-               }
+               if (*offset > xip->i_size)
+                       xip->i_size = *offset;
                xfs_iunlock(xip, XFS_ILOCK_EXCL);
        }
 
@@ -913,16 +909,31 @@ retry:
 
                error = sync_page_range(inode, mapping, pos, ret);
                if (!error)
-                       error = ret;
-               return error;
+                       error = -ret;
+               if (need_i_mutex)
+                       mutex_lock(&inode->i_mutex);
+               xfs_rwlock(bdp, locktype);
        }
 
  out_unlock_internal:
+       if (io->io_new_size) {
+               xfs_ilock(xip, XFS_ILOCK_EXCL);
+               io->io_new_size = 0;
+               /*
+                * If this was a direct or synchronous I/O that failed (such
+                * as ENOSPC) then part of the I/O may have been written to
+                * disk before the error occured.  In this case the on-disk
+                * file size may have been adjusted beyond the in-memory file
+                * size and now needs to be truncated back.
+                */
+               if (xip->i_d.di_size > xip->i_size)
+                       xip->i_d.di_size = xip->i_size;
+               xfs_iunlock(xip, XFS_ILOCK_EXCL);
+       }
        xfs_rwunlock(bdp, locktype);
  out_unlock_mutex:
        if (need_i_mutex)
                mutex_unlock(&inode->i_mutex);
- out_nounlocks:
        return -error;
 }
 
index b76118cf48978b72f28368f54f080da6623b8e45..d1b2d01843d177d2f75b8bed5f0c07d3061ba519 100644 (file)
@@ -194,7 +194,7 @@ typedef     int     (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
 typedef void   (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
 typedef void   (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
 typedef void   (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-typedef void   (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
+typedef int    (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 typedef int    (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
                                uint64_t, int);
 typedef int    (*vop_iflush_t)(bhv_desc_t *, int);
index 4adaf13aac6f783fa67aa8071e2cf934473d7bd4..cfdd35ee9f7a1e192aa797abe8659c870e789967 100644 (file)
@@ -753,8 +753,7 @@ xfs_qm_idtodq(
                goto error0;
        }
        if (tp) {
-               if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
-                                            NULL)))
+               if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES)))
                        goto error1;
        }
 
index 1de2acdc7f70eab902b24c403b54962bb6b95d74..3e4a8ad8a34c3180eff417f732f11d5df320b722 100644 (file)
@@ -388,6 +388,17 @@ xfs_qm_mount_quotas(
                        return XFS_ERROR(error);
                }
        }
+       /* 
+        * If one type of quotas is off, then it will lose its
+        * quotachecked status, since we won't be doing accounting for
+        * that type anymore.
+        */
+       if (!XFS_IS_UQUOTA_ON(mp)) {
+               mp->m_qflags &= ~XFS_UQUOTA_CHKD;
+       }
+       if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp))) {
+               mp->m_qflags &= ~XFS_OQUOTA_CHKD;
+       }
 
  write_changes:
        /*
@@ -1453,8 +1464,7 @@ xfs_qm_qino_alloc(
        XFS_SB_UNLOCK(mp, s);
        xfs_mod_sb(tp, sbfields);
 
-       if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
-                                    NULL))) {
+       if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
                xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!");
                return error;
        }
@@ -2405,7 +2415,7 @@ xfs_qm_write_sb_changes(
        }
 
        xfs_mod_sb(tp, flags);
-       (void) xfs_trans_commit(tp, 0, NULL);
+       (void) xfs_trans_commit(tp, 0);
 
        return 0;
 }
index 716f562aa8b2f036c46c7dd1951b0185ae04d5d0..2df67fd913e5f9c3f5efa5ad64c436cf5b920cb8 100644 (file)
@@ -456,9 +456,7 @@ xfs_qm_scall_quotaon(
            ||
            ((flags & XFS_PQUOTA_ACCT) == 0 &&
            (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
-           (flags & XFS_OQUOTA_ENFD))
-           ||
-           ((flags & XFS_GQUOTA_ACCT) == 0 &&
+           (flags & XFS_GQUOTA_ACCT) == 0 &&
            (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
            (flags & XFS_OQUOTA_ENFD))) {
                qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
@@ -735,7 +733,7 @@ xfs_qm_scall_setqlim(
        xfs_trans_log_dquot(tp, dqp);
 
        xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
-       xfs_trans_commit(tp, 0, NULL);
+       xfs_trans_commit(tp, 0);
        xfs_qm_dqprint(dqp);
        xfs_qm_dqrele(dqp);
        mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
@@ -809,7 +807,7 @@ xfs_qm_log_quotaoff_end(
         * We don't care about quotoff's performance.
         */
        xfs_trans_set_sync(tp);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        return (error);
 }
 
@@ -852,7 +850,7 @@ xfs_qm_log_quotaoff(
         * We don't care about quotoff's performance.
         */
        xfs_trans_set_sync(tp);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
 error0:
        if (error) {
@@ -911,14 +909,19 @@ xfs_qm_export_dquot(
         * gets turned off. No need to confuse the user level code,
         * so return zeroes in that case.
         */
-       if (! XFS_IS_QUOTA_ENFORCED(mp)) {
+       if ((!XFS_IS_UQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_USER) ||
+           (!XFS_IS_OQUOTA_ENFORCED(mp) &&
+                       (src->d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
                dst->d_btimer = 0;
                dst->d_itimer = 0;
                dst->d_rtbtimer = 0;
        }
 
 #ifdef DEBUG
-       if (XFS_IS_QUOTA_ENFORCED(mp) && dst->d_id != 0) {
+       if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == XFS_USER_QUOTA) ||
+            (XFS_IS_OQUOTA_ENFORCED(mp) &&
+                       (dst->d_flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)))) &&
+           dst->d_id != 0) {
                if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
                    (dst->d_blk_softlimit > 0)) {
                        ASSERT(dst->d_btimer != 0);
index d7491e7b1f3bca3c1a29d13585b9f914f9cf761f..7de6874bf1b8871c7823354494b6e8adb3c00580 100644 (file)
@@ -656,7 +656,9 @@ xfs_trans_dqresv(
 
        if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
            dqp->q_core.d_id &&
-           XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {
+           ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
+            (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
+             (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
 #ifdef QUOTADEBUG
                cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
                          " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);
index 08bbd3cb87aefb055088902550405c49a92be228..f45a49ffd3a34907f6b1ca2aceaea7dce40e2133 100644 (file)
@@ -81,20 +81,3 @@ assfail(char *expr, char *file, int line)
        printk("Assertion failed: %s, file: %s, line: %d\n", expr, file, line);
        BUG();
 }
-
-#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM))
-unsigned long random(void)
-{
-       static unsigned long    RandomValue = 1;
-       /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
-       register long   rv = RandomValue;
-       register long   lo;
-       register long   hi;
-
-       hi = rv / 127773;
-       lo = rv % 127773;
-       rv = 16807 * lo - 2836 * hi;
-       if (rv <= 0) rv += 2147483647;
-       return RandomValue = rv;
-}
-#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */
index 2a70cc605ae34b5298ed8e4ebd0a912d9153fd37..a27a7c8c05264c1e651e0c0651d9caa4eec64c7f 100644 (file)
@@ -50,7 +50,7 @@ extern void assfail(char *expr, char *f, int l);
 #else /* DEBUG */
 
 # define ASSERT(expr)  ASSERT_ALWAYS(expr)
-extern unsigned long random(void);
+# include <linux/random.h>
 
 #ifndef STATIC
 # define STATIC noinline
index e80dda3437d196345b0d19cded4cac518b4e0eda..8e9a40aa0cd3fec9c14ffa158730ef801d6f598a 100644 (file)
@@ -764,7 +764,7 @@ xfs_alloc_ag_vextent_near(
         */
        int             dofirst;        /* set to do first algorithm */
 
-       dofirst = random() & 1;
+       dofirst = random32() & 1;
 #endif
        /*
         * Get a cursor for the by-size btree.
index 9d358ffce4e5101d999570b3af021be3705d797b..7ce44a7b88a246de3effe15bd9ab8f0aa680b095 100644 (file)
@@ -328,8 +328,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
                                xfs_trans_set_sync(args.trans);
                        }
                        err2 = xfs_trans_commit(args.trans,
-                                                XFS_TRANS_RELEASE_LOG_RES,
-                                                NULL);
+                                                XFS_TRANS_RELEASE_LOG_RES);
                        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
                        /*
@@ -397,8 +396,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
         * Commit the last in the sequence of transactions.
         */
        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
-       error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
-                                NULL);
+       error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
        /*
@@ -544,8 +542,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
         * Commit the last in the sequence of transactions.
         */
        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
-       error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
-                                NULL);
+       error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
        /*
@@ -859,8 +856,7 @@ xfs_attr_inactive(xfs_inode_t *dp)
         * Commit the last in the sequence of transactions.
         */
        xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
-       error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES,
-                                NULL);
+       error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
        return(error);
index 8eab73e8340ac223c00d617750845d1cee7c8fbd..81f45dae1c57f668c09786b405b2b805862bb556 100644 (file)
@@ -3053,7 +3053,7 @@ xfs_attr_rolltrans(xfs_trans_t **transp, xfs_inode_t *dp)
         * is in progress. The caller takes the responsibility to cancel
         * the duplicate transaction that gets returned.
         */
-       if ((error = xfs_trans_commit(trans, 0, NULL)))
+       if ((error = xfs_trans_commit(trans, 0)))
                return (error);
 
        trans = *transp;
index 87795188cedf31dd4d7edaa3a27848b5bf1330df..b1ea26e40aaf217815cca6a6a8f3ef9340750bab 100644 (file)
@@ -130,7 +130,6 @@ STATIC int                          /* error */
 xfs_bmap_add_extent_hole_delay(
        xfs_inode_t             *ip,    /* incore inode pointer */
        xfs_extnum_t            idx,    /* extent number to update/insert */
-       xfs_btree_cur_t         *cur,   /* if null, not a btree */
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
        int                     *logflagsp,/* inode logging flags */
        xfs_extdelta_t          *delta, /* Change made to incore extents */
@@ -399,7 +398,6 @@ xfs_bmap_count_leaves(
 
 STATIC int
 xfs_bmap_disk_count_leaves(
-       xfs_ifork_t             *ifp,
        xfs_extnum_t            idx,
        xfs_bmbt_block_t        *block,
        int                     numrecs,
@@ -580,7 +578,7 @@ xfs_bmap_add_extent(
                if (cur)
                        ASSERT((cur->bc_private.b.flags &
                                XFS_BTCUR_BPRV_WASDEL) == 0);
-               if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new,
+               if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new,
                                &logflags, delta, rsvd)))
                        goto done;
        }
@@ -1841,7 +1839,6 @@ STATIC int                                /* error */
 xfs_bmap_add_extent_hole_delay(
        xfs_inode_t             *ip,    /* incore inode pointer */
        xfs_extnum_t            idx,    /* extent number to update/insert */
-       xfs_btree_cur_t         *cur,   /* if null, not a btree */
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
        int                     *logflagsp, /* inode logging flags */
        xfs_extdelta_t          *delta, /* Change made to incore extents */
@@ -4071,7 +4068,7 @@ xfs_bmap_add_attrfork(
        }
        if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
                goto error2;
-       error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES);
        ASSERT(ip->i_df.if_ext_max ==
               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
        return error;
@@ -4227,7 +4224,7 @@ xfs_bmap_finish(
        logres = ntp->t_log_res;
        logcount = ntp->t_log_count;
        ntp = xfs_trans_dup(*tp);
-       error = xfs_trans_commit(*tp, 0, NULL);
+       error = xfs_trans_commit(*tp, 0);
        *tp = ntp;
        *committed = 1;
        /*
@@ -4447,8 +4444,11 @@ xfs_bmap_one_block(
        xfs_bmbt_irec_t s;              /* internal version of extent */
 
 #ifndef DEBUG
-       if (whichfork == XFS_DATA_FORK)
-               return ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize;
+       if (whichfork == XFS_DATA_FORK) {
+               return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
+                       (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
+                       (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
+       }
 #endif /* !DEBUG */
        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
                return 0;
@@ -4460,7 +4460,7 @@ xfs_bmap_one_block(
        xfs_bmbt_get_all(ep, &s);
        rval = s.br_startoff == 0 && s.br_blockcount == 1;
        if (rval && whichfork == XFS_DATA_FORK)
-               ASSERT(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
+               ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
        return rval;
 }
 
@@ -5820,7 +5820,7 @@ xfs_getbmap(
                        fixlen = XFS_MAXIOFFSET(mp);
                } else {
                        prealloced = 0;
-                       fixlen = ip->i_d.di_size;
+                       fixlen = ip->i_size;
                }
        } else {
                prealloced = 0;
@@ -5844,7 +5844,8 @@ xfs_getbmap(
 
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
-       if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {
+       if (whichfork == XFS_DATA_FORK &&
+               (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
                /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
                error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
        }
@@ -6425,8 +6426,8 @@ xfs_bmap_count_tree(
                for (;;) {
                        nextbno = be64_to_cpu(block->bb_rightsib);
                        numrecs = be16_to_cpu(block->bb_numrecs);
-                       if (unlikely(xfs_bmap_disk_count_leaves(ifp,
-                                       0, block, numrecs, count) < 0)) {
+                       if (unlikely(xfs_bmap_disk_count_leaves(0,
+                                       block, numrecs, count) < 0)) {
                                xfs_trans_brelse(tp, bp);
                                XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
                                                 XFS_ERRLEVEL_LOW, mp);
@@ -6472,7 +6473,6 @@ xfs_bmap_count_leaves(
  */
 int
 xfs_bmap_disk_count_leaves(
-       xfs_ifork_t             *ifp,
        xfs_extnum_t            idx,
        xfs_bmbt_block_t        *block,
        int                     numrecs,
index b847e6a7a3f03ba3a5e0f8e200414e97347e0609..de35d18cc002c5eefcf7c631143bdfacef753bf9 100644 (file)
@@ -199,7 +199,9 @@ xfs_swap_extents(
 
        if (VN_CACHED(tvp) != 0) {
                xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
-               bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
+               error = bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
+               if (error)
+                       goto error0;
        }
 
        /* Verify O_DIRECT for ftmp */
@@ -382,7 +384,7 @@ xfs_swap_extents(
                xfs_trans_set_sync(tp);
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT);
        locked = 0;
 
  error0:
index 9d7438bba30d73b0c16ddb8686db9fd0fd6d5f70..3accc1dcd6c9919658545237699ace1d0302a028 100644 (file)
@@ -282,8 +282,7 @@ xfs_dir2_block_addname(
                 * This needs to happen before the next call to use_free.
                 */
                if (needscan) {
-                       xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block,
-                               &needlog, NULL);
+                       xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
                        needscan = 0;
                }
        }
@@ -333,7 +332,7 @@ xfs_dir2_block_addname(
                 */
                if (needscan) {
                        xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block,
-                               &needlog, NULL);
+                               &needlog);
                        needscan = 0;
                }
                /*
@@ -418,8 +417,7 @@ xfs_dir2_block_addname(
         * Clean up the bestfree array and log the header, tail, and entry.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
-                       NULL);
+               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, bp);
        xfs_dir2_block_log_tail(tp, bp);
@@ -798,8 +796,7 @@ xfs_dir2_block_removename(
         * Fix up bestfree, log the header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
-                       NULL);
+               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, bp);
        xfs_dir2_data_check(dp, bp);
@@ -996,8 +993,7 @@ xfs_dir2_leaf_to_block(
         * Scan the bestfree if we need it and log the data block header.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
-                       NULL);
+               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, dbp);
        /*
index f7c799217072066518a560965c907cc8f428ef35..c211c37ef67cb307fa70a1a60b66635c8c39947a 100644 (file)
@@ -324,8 +324,7 @@ void
 xfs_dir2_data_freescan(
        xfs_mount_t             *mp,            /* filesystem mount point */
        xfs_dir2_data_t         *d,             /* data block pointer */
-       int                     *loghead,       /* out: log data header */
-       char                    *aendp)         /* in: caller's endp */
+       int                     *loghead)       /* out: log data header */
 {
        xfs_dir2_block_tail_t   *btp;           /* block tail */
        xfs_dir2_data_entry_t   *dep;           /* active data entry */
@@ -346,9 +345,7 @@ xfs_dir2_data_freescan(
         * Set up pointers.
         */
        p = (char *)d->u;
-       if (aendp)
-               endp = aendp;
-       else if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
+       if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
                btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
                endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
        } else
index a6ae2d21c40abf9d3ca6f7fa0402b084a114898a..c94c9099cfb13c7c271857f2c518e39aaf9ebc52 100644 (file)
@@ -166,7 +166,7 @@ extern xfs_dir2_data_free_t *xfs_dir2_data_freefind(xfs_dir2_data_t *d,
 extern xfs_dir2_data_free_t *xfs_dir2_data_freeinsert(xfs_dir2_data_t *d,
                                xfs_dir2_data_unused_t *dup, int *loghead);
 extern void xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
-                               int *loghead, char *aendp);
+                               int *loghead);
 extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
                                struct xfs_dabuf **bpp);
 extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
index b1cf1fbf423d346aa1064d412337b1c05d4dd962..db14ea71459f0c8086e00e0d26c40498cf845da8 100644 (file)
@@ -133,8 +133,7 @@ xfs_dir2_block_to_leaf(
         */
        block->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
        if (needscan)
-               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
-                       NULL);
+               xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
        /*
         * Set up leaf tail and bests table.
         */
@@ -414,7 +413,7 @@ xfs_dir2_leaf_addname(
         * Need to scan fix up the bestfree table.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, data, &needlog, NULL);
+               xfs_dir2_data_freescan(mp, data, &needlog);
        /*
         * Need to log the data block's header.
         */
@@ -1496,7 +1495,7 @@ xfs_dir2_leaf_removename(
         * log the data block header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, data, &needlog, NULL);
+               xfs_dir2_data_freescan(mp, data, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, dbp);
        /*
index 9ca71719b683b041ff67795d316f55c2b96008d7..d083c38199343e0eacf91007c8e41180e79fcb54 100644 (file)
@@ -904,7 +904,7 @@ xfs_dir2_leafn_remove(
         * Log the data block header if needed.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, data, &needlog, NULL);
+               xfs_dir2_data_freescan(mp, data, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, dbp);
        xfs_dir2_data_check(dp, dbp);
@@ -1705,7 +1705,7 @@ xfs_dir2_node_addname_int(
         * Rescan the block for bestfree if needed.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, data, &needlog, NULL);
+               xfs_dir2_data_freescan(mp, data, &needlog);
        /*
         * Log the data block header if needed.
         */
index b1af54464f0078006146cc790d664a6989f68350..8c433163133734d5905741bf1226c128319e82ab 100644 (file)
@@ -80,7 +80,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression,
        int i;
        int64_t fsid;
 
-       if (random() % randfactor)
+       if (random32() % randfactor)
                return 0;
 
        memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
index 32c37c1c47ab341fed758b6e5fb8bea04742906d..b599e6be9ec18f146f8527c7e361c5dc94f45c30 100644 (file)
@@ -346,7 +346,7 @@ xfs_growfs_data_private(
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, nfree);
        if (dpct)
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        if (error) {
                return error;
        }
@@ -605,7 +605,7 @@ xfs_fs_log_dummy(
        xfs_trans_ihold(tp, ip);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        xfs_trans_set_sync(tp);
-       xfs_trans_commit(tp, 0, NULL);
+       xfs_trans_commit(tp, 0);
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 }
index c1c89dac19cceceed3aff020651b9eac349cf98e..114433a22baafcfba0f51c73d15eeab21f7afe29 100644 (file)
@@ -879,17 +879,17 @@ xfs_ilock(xfs_inode_t     *ip,
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0);
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
 
        if (lock_flags & XFS_IOLOCK_EXCL) {
-               mrupdate(&ip->i_iolock);
+               mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
        } else if (lock_flags & XFS_IOLOCK_SHARED) {
-               mraccess(&ip->i_iolock);
+               mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
        }
        if (lock_flags & XFS_ILOCK_EXCL) {
-               mrupdate(&ip->i_lock);
+               mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
        } else if (lock_flags & XFS_ILOCK_SHARED) {
-               mraccess(&ip->i_lock);
+               mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
        }
        xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address);
 }
@@ -923,7 +923,7 @@ xfs_ilock_nowait(xfs_inode_t        *ip,
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0);
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
 
        iolocked = 0;
        if (lock_flags & XFS_IOLOCK_EXCL) {
@@ -983,7 +983,8 @@ xfs_iunlock(xfs_inode_t     *ip,
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY)) == 0);
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY |
+                       XFS_LOCK_DEP_MASK)) == 0);
        ASSERT(lock_flags != 0);
 
        if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
index 3da9829c19d5e80af53be627dc8b5b1a0b594ee0..3ca5d43b83456ccdf8ca4c61f13b363d13c9e76c 100644 (file)
@@ -442,6 +442,7 @@ xfs_iformat(
                        return XFS_ERROR(EFSCORRUPTED);
                }
                ip->i_d.di_size = 0;
+               ip->i_size = 0;
                ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
                break;
 
@@ -980,6 +981,7 @@ xfs_iread(
        }
 
        ip->i_delayed_blks = 0;
+       ip->i_size = ip->i_d.di_size;
 
        /*
         * Mark the buffer containing the inode as something to keep
@@ -1170,6 +1172,7 @@ xfs_ialloc(
        }
 
        ip->i_d.di_size = 0;
+       ip->i_size = 0;
        ip->i_d.di_nextents = 0;
        ASSERT(ip->i_d.di_nblocks == 0);
        xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD);
@@ -1340,7 +1343,7 @@ xfs_file_last_byte(
        } else {
                last_block = 0;
        }
-       size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_d.di_size);
+       size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_size);
        last_block = XFS_FILEOFF_MAX(last_block, size_last_block);
 
        last_byte = XFS_FSB_TO_B(mp, last_block);
@@ -1421,7 +1424,7 @@ xfs_itrunc_trace(
  * must be called again with all the same restrictions as the initial
  * call.
  */
-void
+int
 xfs_itruncate_start(
        xfs_inode_t     *ip,
        uint            flags,
@@ -1431,9 +1434,10 @@ xfs_itruncate_start(
        xfs_off_t       toss_start;
        xfs_mount_t     *mp;
        bhv_vnode_t     *vp;
+       int             error = 0;
 
        ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
-       ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
+       ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
               (flags == XFS_ITRUNC_MAYBE));
 
@@ -1468,7 +1472,7 @@ xfs_itruncate_start(
                 * file size, so there is no way that the data extended
                 * out there.
                 */
-               return;
+               return 0;
        }
        last_byte = xfs_file_last_byte(ip);
        xfs_itrunc_trace(XFS_ITRUNC_START, ip, flags, new_size, toss_start,
@@ -1477,7 +1481,7 @@ xfs_itruncate_start(
                if (flags & XFS_ITRUNC_DEFINITE) {
                        bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
                } else {
-                       bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
+                       error = bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
                }
        }
 
@@ -1486,6 +1490,7 @@ xfs_itruncate_start(
                ASSERT(VN_CACHED(vp) == 0);
        }
 #endif
+       return error;
 }
 
 /*
@@ -1556,7 +1561,7 @@ xfs_itruncate_finish(
 
        ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
        ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
-       ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
+       ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT(*tp != NULL);
        ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
        ASSERT(ip->i_transp == *tp);
@@ -1630,8 +1635,20 @@ xfs_itruncate_finish(
         */
        if (fork == XFS_DATA_FORK) {
                if (ip->i_d.di_nextents > 0) {
-                       ip->i_d.di_size = new_size;
-                       xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+                       /*
+                        * If we are not changing the file size then do
+                        * not update the on-disk file size - we may be
+                        * called from xfs_inactive_free_eofblocks().  If we
+                        * update the on-disk file size and then the system
+                        * crashes before the contents of the file are
+                        * flushed to disk then the files may be full of
+                        * holes (ie NULL files bug).
+                        */
+                       if (ip->i_size != new_size) {
+                               ip->i_d.di_size = new_size;
+                               ip->i_size = new_size;
+                               xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+                       }
                }
        } else if (sync) {
                ASSERT(!(mp->m_flags & XFS_MOUNT_WSYNC));
@@ -1746,7 +1763,7 @@ xfs_itruncate_finish(
                        xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
                }
                ntp = xfs_trans_dup(ntp);
-               (void) xfs_trans_commit(*tp, 0, NULL);
+               (void) xfs_trans_commit(*tp, 0);
                *tp = ntp;
                error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
                                          XFS_TRANS_PERM_LOG_RES,
@@ -1767,7 +1784,19 @@ xfs_itruncate_finish(
         */
        if (fork == XFS_DATA_FORK) {
                xfs_isize_check(mp, ip, new_size);
-               ip->i_d.di_size = new_size;
+               /*
+                * If we are not changing the file size then do
+                * not update the on-disk file size - we may be
+                * called from xfs_inactive_free_eofblocks().  If we
+                * update the on-disk file size and then the system
+                * crashes before the contents of the file are
+                * flushed to disk then the files may be full of
+                * holes (ie NULL files bug).
+                */
+               if (ip->i_size != new_size) {
+                       ip->i_d.di_size = new_size;
+                       ip->i_size = new_size;
+               }
        }
        xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
        ASSERT((new_size != 0) ||
@@ -1800,7 +1829,7 @@ xfs_igrow_start(
 
        ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
        ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
-       ASSERT(new_size > ip->i_d.di_size);
+       ASSERT(new_size > ip->i_size);
 
        /*
         * Zero any pages that may have been created by
@@ -1808,7 +1837,7 @@ xfs_igrow_start(
         * and any blocks between the old and new file sizes.
         */
        error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
-                            ip->i_d.di_size);
+                            ip->i_size);
        return error;
 }
 
@@ -1832,13 +1861,14 @@ xfs_igrow_finish(
        ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
        ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
        ASSERT(ip->i_transp == tp);
-       ASSERT(new_size > ip->i_d.di_size);
+       ASSERT(new_size > ip->i_size);
 
        /*
         * Update the file size.  Update the inode change timestamp
         * if change_flag set.
         */
        ip->i_d.di_size = new_size;
+       ip->i_size = new_size;
        if (change_flag)
                xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -2321,7 +2351,7 @@ xfs_ifree(
        ASSERT(ip->i_d.di_nlink == 0);
        ASSERT(ip->i_d.di_nextents == 0);
        ASSERT(ip->i_d.di_anextents == 0);
-       ASSERT((ip->i_d.di_size == 0) ||
+       ASSERT((ip->i_d.di_size == 0 && ip->i_size == 0) ||
               ((ip->i_d.di_mode & S_IFMT) != S_IFREG));
        ASSERT(ip->i_d.di_nblocks == 0);
 
index bc823720d88f4116bff4eccc42fb07b6d1ab971d..f75afecef8e7b02d78ebb2c4d45a1e381af2ac8c 100644 (file)
@@ -287,6 +287,7 @@ typedef struct xfs_inode {
        struct xfs_inode        *i_cnext;       /* cluster hash link forward */
        struct xfs_inode        *i_cprev;       /* cluster hash link backward */
 
+       xfs_fsize_t             i_size;         /* in-memory size */
        /* Trace buffers per inode. */
 #ifdef XFS_BMAP_TRACE
        struct ktrace           *i_xtrace;      /* inode extent list trace */
@@ -305,6 +306,8 @@ typedef struct xfs_inode {
 #endif
 } xfs_inode_t;
 
+#define XFS_ISIZE(ip)  (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
+                               (ip)->i_size : (ip)->i_d.di_size;
 
 /*
  * i_flags helper functions
@@ -379,26 +382,58 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
 
 /*
  * Flags for inode locking.
+ * Bit ranges: 1<<1  - 1<<16-1 -- iolock/ilock modes (bitfield)
+ *             1<<16 - 1<<32-1 -- lockdep annotation (integers)
  */
-#define        XFS_IOLOCK_EXCL         0x001
-#define        XFS_IOLOCK_SHARED       0x002
-#define        XFS_ILOCK_EXCL          0x004
-#define        XFS_ILOCK_SHARED        0x008
-#define        XFS_IUNLOCK_NONOTIFY    0x010
-/*     XFS_IOLOCK_NESTED       0x020 */
-#define XFS_EXTENT_TOKEN_RD    0x040
-#define XFS_SIZE_TOKEN_RD      0x080
+#define        XFS_IOLOCK_EXCL         (1<<0)
+#define        XFS_IOLOCK_SHARED       (1<<1)
+#define        XFS_ILOCK_EXCL          (1<<2)
+#define        XFS_ILOCK_SHARED        (1<<3)
+#define        XFS_IUNLOCK_NONOTIFY    (1<<4)
+/*     #define XFS_IOLOCK_NESTED       (1<<5)  */
+#define XFS_EXTENT_TOKEN_RD    (1<<6)
+#define XFS_SIZE_TOKEN_RD      (1<<7)
 #define XFS_EXTSIZE_RD         (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD)
-#define XFS_WILLLEND           0x100   /* Always acquire tokens for lending */
+#define XFS_WILLLEND           (1<<8)  /* Always acquire tokens for lending */
 #define XFS_EXTENT_TOKEN_WR    (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND)
 #define XFS_SIZE_TOKEN_WR       (XFS_SIZE_TOKEN_RD | XFS_WILLLEND)
 #define XFS_EXTSIZE_WR         (XFS_EXTSIZE_RD | XFS_WILLLEND)
-/*     XFS_SIZE_TOKEN_WANT     0x200 */
+/* TODO:XFS_SIZE_TOKEN_WANT    (1<<9) */
 
-#define XFS_LOCK_MASK  \
-       (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL | \
-        XFS_ILOCK_SHARED | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD | \
-        XFS_WILLLEND)
+#define XFS_LOCK_MASK          (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \
+                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \
+                               | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD \
+                               | XFS_WILLLEND)
+
+/*
+ * Flags for lockdep annotations.
+ *
+ * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes
+ * (ie directory operations that require locking a directory inode and
+ * an entry inode).  The first inode gets locked with this flag so it
+ * gets a lockdep subclass of 1 and the second lock will have a lockdep
+ * subclass of 0.
+ *
+ * XFS_I[O]LOCK_INUMORDER - for locking several inodes at the some time
+ * with xfs_lock_inodes().  This flag is used as the starting subclass
+ * and each subsequent lock acquired will increment the subclass by one.
+ * So the first lock acquired will have a lockdep subclass of 2, the
+ * second lock will have a lockdep subclass of 3, and so on.
+ */
+#define XFS_IOLOCK_SHIFT       16
+#define        XFS_IOLOCK_PARENT       (1 << XFS_IOLOCK_SHIFT)
+#define        XFS_IOLOCK_INUMORDER    (2 << XFS_IOLOCK_SHIFT)
+
+#define XFS_ILOCK_SHIFT                24
+#define        XFS_ILOCK_PARENT        (1 << XFS_ILOCK_SHIFT)
+#define        XFS_ILOCK_INUMORDER     (2 << XFS_ILOCK_SHIFT)
+
+#define XFS_IOLOCK_DEP_MASK    0x00ff0000
+#define XFS_ILOCK_DEP_MASK     0xff000000
+#define XFS_LOCK_DEP_MASK      (XFS_IOLOCK_DEP_MASK | XFS_ILOCK_DEP_MASK)
+
+#define XFS_IOLOCK_DEP(flags)  (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT)
+#define XFS_ILOCK_DEP(flags)   (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT)
 
 /*
  * Flags for xfs_iflush()
@@ -481,7 +516,7 @@ uint                xfs_ip2xflags(struct xfs_inode *);
 uint           xfs_dic2xflags(struct xfs_dinode_core *);
 int            xfs_ifree(struct xfs_trans *, xfs_inode_t *,
                           struct xfs_bmap_free *);
-void           xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
+int            xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
 int            xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
                                     xfs_fsize_t, int, int);
 int            xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
index 06d710c9ce4b5dec4c9f4b72cadde1d5aa39c07a..81548ec72ba6073b2b910b79d74e8d763ce06fae 100644 (file)
@@ -52,7 +52,7 @@ STATIC xfs_fsize_t
 xfs_size_fn(
        xfs_inode_t             *ip)
 {
-       return (ip->i_d.di_size);
+       return XFS_ISIZE(ip);
 }
 
 STATIC int
index cc6a7b5a99129226e91c123429f83e78bd42ab66..3f2b9f2a7b949d01e0f01f74b21e9b42fd76ae35 100644 (file)
@@ -458,7 +458,7 @@ xfs_iomap_write_direct(
                extsz = ip->i_d.di_extsize;
        }
 
-       isize = ip->i_d.di_size;
+       isize = ip->i_size;
        if (io->io_new_size > isize)
                isize = io->io_new_size;
 
@@ -524,7 +524,7 @@ xfs_iomap_write_direct(
        xfs_trans_ihold(tp, ip);
 
        bmapi_flag = XFS_BMAPI_WRITE;
-       if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz))
+       if ((flags & BMAPI_DIRECT) && (offset < ip->i_size || extsz))
                bmapi_flag |= XFS_BMAPI_PREALLOC;
 
        /*
@@ -543,7 +543,7 @@ xfs_iomap_write_direct(
        error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error)
                goto error0;
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error)
                goto error_out;
 
@@ -676,7 +676,7 @@ xfs_iomap_write_delay(
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
 retry:
-       isize = ip->i_d.di_size;
+       isize = ip->i_size;
        if (io->io_new_size > isize)
                isize = io->io_new_size;
 
@@ -817,7 +817,7 @@ xfs_iomap_write_allocate(
                         * we dropped the ilock in the interim.
                         */
 
-                       end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
+                       end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
                        xfs_bmap_last_offset(NULL, ip, &last_block,
                                XFS_DATA_FORK);
                        last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
@@ -840,8 +840,7 @@ xfs_iomap_write_allocate(
                        if (error)
                                goto trans_cancel;
 
-                       error = xfs_trans_commit(tp,
-                                       XFS_TRANS_RELEASE_LOG_RES, NULL);
+                       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                        if (error)
                                goto error0;
 
@@ -948,7 +947,7 @@ xfs_iomap_write_unwritten(
                if (error)
                        goto error_on_bmapi_transaction;
 
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                if (error)
                        return XFS_ERROR(error);
index 3ce204a524b0665df59272cdc4425d0772f95619..df441ee936b2f183a8706877245fd802f50178dc 100644 (file)
@@ -22,6 +22,7 @@
 
 
 typedef enum {                         /* iomap_flags values */
+       IOMAP_READ =            0,      /* mapping for a read */
        IOMAP_EOF =             0x01,   /* mapping contains EOF   */
        IOMAP_HOLE =            0x02,   /* mapping covers a hole  */
        IOMAP_DELAY =           0x04,   /* mapping covers delalloc region  */
index 7775ddc0b3c6b105449bef21a3954741533129f4..e725ddd3de5f1d23bf7b1f8d0e81057ede6ac956 100644 (file)
@@ -809,7 +809,7 @@ xfs_inumbers(
                                xfs_buf_relse(agbp);
                                agbp = NULL;
                                /*
-                                * Move up the the last inode in the current
+                                * Move up the last inode in the current
                                 * chunk.  The lookup_ge will always get
                                 * us the first inode in the next chunk.
                                 */
index ca74d3f5910e75cd4810a083651c7073b71ddb3b..080fabf61c92d0e23ffe07dd0069a12eee5f8a88 100644 (file)
@@ -1509,7 +1509,6 @@ xlog_recover_insert_item_frontq(
 
 STATIC int
 xlog_recover_reorder_trans(
-       xlog_t                  *log,
        xlog_recover_t          *trans)
 {
        xlog_recover_item_t     *first_item, *itemq, *itemq_next;
@@ -1867,7 +1866,6 @@ xlog_recover_do_inode_buffer(
 /*ARGSUSED*/
 STATIC void
 xlog_recover_do_reg_buffer(
-       xfs_mount_t             *mp,
        xlog_recover_item_t     *item,
        xfs_buf_t               *bp,
        xfs_buf_log_format_t    *buf_f)
@@ -2083,7 +2081,7 @@ xlog_recover_do_dquot_buffer(
        if (log->l_quotaoffs_flag & type)
                return;
 
-       xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
+       xlog_recover_do_reg_buffer(item, bp, buf_f);
 }
 
 /*
@@ -2184,7 +2182,7 @@ xlog_recover_do_buffer_trans(
                  (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
                xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
        } else {
-               xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
+               xlog_recover_do_reg_buffer(item, bp, buf_f);
        }
        if (error)
                return XFS_ERROR(error);
@@ -2765,7 +2763,7 @@ xlog_recover_do_trans(
        int                     error = 0;
        xlog_recover_item_t     *item, *first_item;
 
-       if ((error = xlog_recover_reorder_trans(log, trans)))
+       if ((error = xlog_recover_reorder_trans(trans)))
                return error;
        first_item = item = trans->r_itemq;
        do {
@@ -3016,7 +3014,7 @@ xlog_recover_process_efi(
        }
 
        efip->efi_flags |= XFS_EFI_RECOVERED;
-       xfs_trans_commit(tp, 0, NULL);
+       xfs_trans_commit(tp, 0);
 }
 
 /*
@@ -3143,7 +3141,7 @@ xlog_recover_clear_agi_bucket(
        xfs_trans_log_buf(tp, agibp, offset,
                          (offset + sizeof(xfs_agino_t) - 1));
 
-       (void) xfs_trans_commit(tp, 0, NULL);
+       (void) xfs_trans_commit(tp, 0);
 }
 
 /*
@@ -3886,8 +3884,7 @@ xlog_recover(
                 * under the vfs layer, so we can get away with it unless
                 * the device itself is read-only, in which case we fail.
                 */
-               if ((error = xfs_dev_is_read_only(log->l_mp,
-                                               "recovery required"))) {
+               if ((error = xfs_dev_is_read_only(log->l_mp, "recovery"))) {
                        return error;
                }
 
index 3bed0cf0d8afa2eaa87a98b00be0a10034c701b7..a96bde6df96d13cb61a92708aff156ad6b282e97 100644 (file)
@@ -1653,7 +1653,7 @@ xfs_mount_log_sbunit(
                return;
        }
        xfs_mod_sb(tp, fields);
-       xfs_trans_commit(tp, 0, NULL);
+       xfs_trans_commit(tp, 0);
 }
 
 
@@ -1734,11 +1734,13 @@ xfs_icsb_cpu_notify(
                        per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                /* Easy Case - initialize the area and locks, and
                 * then rebalance when online does everything else for us. */
                memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                xfs_icsb_lock(mp);
                xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
                xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
@@ -1746,6 +1748,7 @@ xfs_icsb_cpu_notify(
                xfs_icsb_unlock(mp);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                /* Disable all the counters, then fold the dead cpu's
                 * count into the total on the global superblock and
                 * re-enable the counters. */
index 320d63ff9ca2ed97ca60cf0b93caad1d989faae6..0d594ed7efef1d61a3ac4d8e7ac5ddc59b671fe7 100644 (file)
@@ -78,7 +78,7 @@ xfs_mount_reset_sbqflags(xfs_mount_t *mp)
                return error;
        }
        xfs_mod_sb(tp, XFS_SB_QFLAGS);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        return error;
 }
 
index 9dcb32aa4e2ea2a25eac703996bedfc8bb219421..6f14df976f73c71e274a537406b4d1234cfbdc30 100644 (file)
@@ -154,10 +154,11 @@ typedef struct xfs_qoff_logformat {
 #define XFS_ALL_QUOTA_CHKD     (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
 
 #define XFS_IS_QUOTA_RUNNING(mp)       ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_QUOTA_ENFORCED(mp)      ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
 #define XFS_IS_UQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_UQUOTA_ACCT)
 #define XFS_IS_PQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_PQUOTA_ACCT)
 #define XFS_IS_GQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_GQUOTA_ACCT)
+#define XFS_IS_UQUOTA_ENFORCED(mp)     ((mp)->m_qflags & XFS_UQUOTA_ENFD)
+#define XFS_IS_OQUOTA_ENFORCED(mp)     ((mp)->m_qflags & XFS_OQUOTA_ENFD)
 
 /*
  * Incore only flags for quotaoff - these bits get cleared when quota(s)
index 4c6573d784cd4bfd48cb0887c0ae664fcb11b965..7679d7a7022d36ea491616d4aa6cca83bc0e3165 100644 (file)
@@ -584,7 +584,7 @@ xfs_rename(
         * trans_commit will unlock src_ip, target_ip & decrement
         * the vnode references.
         */
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (target_ip != NULL) {
                xfs_refcache_purge_ip(target_ip);
                IRELE(target_ip);
index 6fff19dc3cf96e8cb6d00fabe3dd88d176847f46..b3a5f07bd0734cf189ccf00e076931906dae771d 100644 (file)
@@ -150,7 +150,7 @@ xfs_growfs_rt_alloc(
                error = xfs_bmap_finish(&tp, &flist, &committed);
                if (error)
                        goto error_exit;
-               xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                /*
                 * Now we need to clear the allocated blocks.
                 * Do this one block per transaction, to keep it simple.
@@ -187,7 +187,7 @@ xfs_growfs_rt_alloc(
                        /*
                         * Commit the transaction.
                         */
-                       xfs_trans_commit(tp, 0, NULL);
+                       xfs_trans_commit(tp, 0);
                }
                /*
                 * Go on to the next extent, if any.
@@ -2042,7 +2042,7 @@ xfs_growfs_rt(
                /*
                 * Commit the transaction.
                 */
-               xfs_trans_commit(tp, 0, NULL);
+               xfs_trans_commit(tp, 0);
        }
 
        if (error)
index 1ea7c0ca6ae0f8d5ec63d8ab6aca7706b13e1626..905d1c008be73056458534b58636de0c1247946a 100644 (file)
@@ -83,7 +83,7 @@ xfs_write_clear_setuid(
        }
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        xfs_trans_set_sync(tp);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        return 0;
 }
@@ -164,7 +164,7 @@ xfs_write_sync_logforce(
                        xfs_trans_ihold(tp, ip);
                        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
                        xfs_trans_set_sync(tp);
-                       error = xfs_trans_commit(tp, 0, NULL);
+                       error = xfs_trans_commit(tp, 0);
                        xfs_iunlock(ip, XFS_ILOCK_EXCL);
                }
        }
index 301ff9445b6f84cb570833ec1990df768fbed779..cc2d60951e21e0a3b5655db08c03e1eb83e0d305 100644 (file)
@@ -753,7 +753,6 @@ int
 _xfs_trans_commit(
        xfs_trans_t     *tp,
        uint            flags,
-       xfs_lsn_t       *commit_lsn_p,
        int             *log_flushed)
 {
        xfs_log_iovec_t         *log_vector;
@@ -812,8 +811,6 @@ shut_us_down:
                xfs_trans_free_busy(tp);
                xfs_trans_free(tp);
                XFS_STATS_INC(xs_trans_empty);
-               if (commit_lsn_p)
-                       *commit_lsn_p = commit_lsn;
                return (shutdown);
        }
        ASSERT(tp->t_ticket != NULL);
@@ -864,9 +861,6 @@ shut_us_down:
                kmem_free(log_vector, nvec * sizeof(xfs_log_iovec_t));
        }
 
-       if (commit_lsn_p)
-               *commit_lsn_p = commit_lsn;
-
        /*
         * If we got a log write error. Unpin the logitems that we
         * had pinned, clean up, free trans structure, and return error.
index f1d7ab236726ce20ec98160cdb3541d6f5da50ed..7dfcc450366f79338c3cc796268d8de26ef6af16 100644 (file)
@@ -988,10 +988,8 @@ void               xfs_trans_log_efd_extent(xfs_trans_t *,
                                         xfs_extlen_t);
 int            _xfs_trans_commit(xfs_trans_t *,
                                  uint flags,
-                                 xfs_lsn_t *,
                                  int *);
-#define xfs_trans_commit(tp, flags, lsn) \
-       _xfs_trans_commit(tp, flags, lsn, NULL)
+#define xfs_trans_commit(tp, flags)    _xfs_trans_commit(tp, flags, NULL)
 void           xfs_trans_cancel(xfs_trans_t *, int);
 void           xfs_trans_ail_init(struct xfs_mount *);
 xfs_lsn_t      xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t);
index 9014d7e444885faa447c2a7a987c1f4bdcd1bf8e..20ffec308e1e906cd09d661c3a9d409f97b5a8c3 100644 (file)
@@ -222,7 +222,7 @@ xfs_dir_ialloc(
                }
 
                ntp = xfs_trans_dup(tp);
-               code = xfs_trans_commit(tp, 0, NULL);
+               code = xfs_trans_commit(tp, 0);
                tp = ntp;
                if (committed != NULL) {
                        *committed = 1;
@@ -420,7 +420,11 @@ xfs_truncate_file(
         * in a transaction.
         */
        xfs_ilock(ip, XFS_IOLOCK_EXCL);
-       xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, (xfs_fsize_t)0);
+       error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, (xfs_fsize_t)0);
+       if (error) {
+               xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+               return error;
+       }
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
        if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
@@ -460,8 +464,7 @@ xfs_truncate_file(
                                 XFS_TRANS_ABORT);
        } else {
                xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
-                                        NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        }
        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 
index 29f72f613782a6a1a2d09bc6570e880d65af313a..65c561201cb879da8a83d1df3c40fe2af7927d96 100644 (file)
@@ -696,7 +696,7 @@ xfs_unmount_flush(
        bhv_vnode_t     *rvp = XFS_ITOV(rip);
        int             error;
 
-       xfs_ilock(rip, XFS_ILOCK_EXCL);
+       xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
        xfs_iflock(rip);
 
        /*
@@ -1147,7 +1147,7 @@ xfs_sync_inodes(
                        if (XFS_FORCED_SHUTDOWN(mp)) {
                                bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
                        } else {
-                               bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
+                               error = bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
                        }
 
                        xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -1539,7 +1539,7 @@ xfs_syncsub(
                xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
                xfs_trans_ihold(tp, ip);
                xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-               error = xfs_trans_commit(tp, 0, NULL);
+               error = xfs_trans_commit(tp, 0);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
        }
index 52c41714ec54c5a76cb5dbfe16a51233e44bf85f..de17aed578f04878d7942cd113103fc19ef5619f 100644 (file)
@@ -133,7 +133,7 @@ xfs_getattr(
        if (!(flags & ATTR_LAZY))
                xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-       vap->va_size = ip->i_d.di_size;
+       vap->va_size = XFS_ISIZE(ip);
        if (vap->va_mask == XFS_AT_SIZE)
                goto all_done;
 
@@ -496,7 +496,7 @@ xfs_setattr(
        if (mask & XFS_AT_SIZE) {
                /* Short circuit the truncate case for zero length files */
                if ((vap->va_size == 0) &&
-                  (ip->i_d.di_size == 0) && (ip->i_d.di_nextents == 0)) {
+                  (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
                        xfs_iunlock(ip, XFS_ILOCK_EXCL);
                        lock_flags &= ~XFS_ILOCK_EXCL;
                        if (mask & XFS_AT_CTIME)
@@ -614,7 +614,7 @@ xfs_setattr(
         */
        if (mask & XFS_AT_SIZE) {
                code = 0;
-               if ((vap->va_size > ip->i_d.di_size) && 
+               if ((vap->va_size > ip->i_size) &&
                    (flags & ATTR_NOSIZETOK) == 0) {
                        code = xfs_igrow_start(ip, vap->va_size, credp);
                }
@@ -654,10 +654,10 @@ xfs_setattr(
         * Truncate file.  Must have write permission and not be a directory.
         */
        if (mask & XFS_AT_SIZE) {
-               if (vap->va_size > ip->i_d.di_size) {
+               if (vap->va_size > ip->i_size) {
                        xfs_igrow_finish(tp, ip, vap->va_size,
                            !(flags & ATTR_DMI));
-               } else if ((vap->va_size <= ip->i_d.di_size) ||
+               } else if ((vap->va_size <= ip->i_size) ||
                           ((vap->va_size == 0) && ip->i_d.di_nextents)) {
                        /*
                         * signal a sync transaction unless
@@ -873,7 +873,7 @@ xfs_setattr(
                if (mp->m_flags & XFS_MOUNT_WSYNC)
                        xfs_trans_set_sync(tp);
 
-               code = xfs_trans_commit(tp, commit_flags, NULL);
+               code = xfs_trans_commit(tp, commit_flags);
        }
 
        /*
@@ -1176,7 +1176,7 @@ xfs_fsync(
                xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
                if (flag & FSYNC_WAIT)
                        xfs_trans_set_sync(tp);
-               error = _xfs_trans_commit(tp, 0, NULL, &log_flushed);
+               error = _xfs_trans_commit(tp, 0, &log_flushed);
 
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
@@ -1221,7 +1221,7 @@ xfs_inactive_free_eofblocks(
         * Figure out if there are any blocks beyond the end
         * of the file.  If not, then there is nothing to do.
         */
-       end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_d.di_size));
+       end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size));
        last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
        map_len = last_fsb - end_fsb;
        if (map_len <= 0)
@@ -1257,8 +1257,12 @@ xfs_inactive_free_eofblocks(
                 * do that within a transaction.
                 */
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
-               xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
-                                   ip->i_d.di_size);
+               error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
+                                   ip->i_size);
+               if (error) {
+                       xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+                       return error;
+               }
 
                error = xfs_trans_reserve(tp, 0,
                                          XFS_ITRUNCATE_LOG_RES(mp),
@@ -1278,7 +1282,7 @@ xfs_inactive_free_eofblocks(
                xfs_trans_ihold(tp, ip);
 
                error = xfs_itruncate_finish(&tp, ip,
-                                            ip->i_d.di_size,
+                                            ip->i_size,
                                             XFS_DATA_FORK,
                                             0);
                /*
@@ -1291,8 +1295,7 @@ xfs_inactive_free_eofblocks(
                                          XFS_TRANS_ABORT));
                } else {
                        error = xfs_trans_commit(tp,
-                                               XFS_TRANS_RELEASE_LOG_RES,
-                                               NULL);
+                                               XFS_TRANS_RELEASE_LOG_RES);
                }
                xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        }
@@ -1406,7 +1409,7 @@ xfs_inactive_symlink_rmt(
         * we need to unlock the inode since the new transaction doesn't
         * have the inode attached.
         */
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
        tp = ntp;
        if (error) {
                ASSERT(XFS_FORCED_SHUTDOWN(mp));
@@ -1503,7 +1506,7 @@ xfs_inactive_attrs(
        tp = *tpp;
        mp = ip->i_mount;
        ASSERT(ip->i_d.di_forkoff != 0);
-       xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        error = xfs_attr_inactive(ip);
@@ -1565,7 +1568,7 @@ xfs_release(
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                    ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+                    ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
                       ip->i_delayed_blks > 0)) &&
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
                    (!(ip->i_d.di_flags &
@@ -1626,8 +1629,8 @@ xfs_inactive(
         * only one with a reference to the inode.
         */
        truncate = ((ip->i_d.di_nlink == 0) &&
-            ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
-             (ip->i_delayed_blks > 0)) &&
+           ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
+            (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
            ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
 
        mp = ip->i_mount;
@@ -1645,7 +1648,7 @@ xfs_inactive(
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+                     ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
                        ip->i_delayed_blks > 0)) &&
                      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
                     (!(ip->i_d.di_flags &
@@ -1675,7 +1678,11 @@ xfs_inactive(
                 */
                xfs_ilock(ip, XFS_IOLOCK_EXCL);
 
-               xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
+               error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
+               if (error) {
+                       xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+                       return VN_INACTIVE_CACHE;
+               }
 
                error = xfs_trans_reserve(tp, 0,
                                          XFS_ITRUNCATE_LOG_RES(mp),
@@ -1790,7 +1797,7 @@ xfs_inactive(
                 * nothing we can do except to try to keep going.
                 */
                (void) xfs_bmap_finish(&tp,  &free_list, &committed);
-               (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        }
        /*
         * Release the dquots held by inode, if any.
@@ -1940,7 +1947,7 @@ xfs_create(
                goto error_return;
        }
 
-       xfs_ilock(dp, XFS_ILOCK_EXCL);
+       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 
        XFS_BMAP_INIT(&free_list, &first_block);
 
@@ -2026,7 +2033,7 @@ xfs_create(
                goto abort_rele;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(ip);
                tp = NULL;
@@ -2121,7 +2128,6 @@ int xfs_rm_attempts;
 STATIC int
 xfs_lock_dir_and_entry(
        xfs_inode_t     *dp,
-       bhv_vname_t     *dentry,
        xfs_inode_t     *ip)    /* inode of entry 'name' */
 {
        int             attempts;
@@ -2135,7 +2141,7 @@ xfs_lock_dir_and_entry(
        attempts = 0;
 
 again:
-       xfs_ilock(dp, XFS_ILOCK_EXCL);
+       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 
        e_inum = ip->i_ino;
 
@@ -2203,6 +2209,21 @@ int xfs_lots_retries;
 int xfs_lock_delays;
 #endif
 
+/*
+ * Bump the subclass so xfs_lock_inodes() acquires each lock with
+ * a different value
+ */
+static inline int
+xfs_lock_inumorder(int lock_mode, int subclass)
+{
+       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
+               lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
+       if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
+               lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT;
+
+       return lock_mode;
+}
+
 /*
  * The following routine will lock n inodes in exclusive mode.
  * We assume the caller calls us with the inodes in i_ino order.
@@ -2270,7 +2291,7 @@ again:
                         * that is in the AIL.
                         */
                        ASSERT(i != 0);
-                       if (!xfs_ilock_nowait(ips[i], lock_mode)) {
+                       if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) {
                                attempts++;
 
                                /*
@@ -2305,7 +2326,7 @@ again:
                                goto again;
                        }
                } else {
-                       xfs_ilock(ips[i], lock_mode);
+                       xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
                }
        }
 
@@ -2440,7 +2461,7 @@ xfs_remove(
                return error;
        }
 
-       error = xfs_lock_dir_and_entry(dp, dentry, ip);
+       error = xfs_lock_dir_and_entry(dp, ip);
        if (error) {
                REMOVE_DEBUG_TRACE(__LINE__);
                xfs_trans_cancel(tp, cancel_flags);
@@ -2511,7 +2532,7 @@ xfs_remove(
                goto error_rele;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(ip);
                goto std_return;
@@ -2719,7 +2740,7 @@ xfs_link(
                goto abort_return;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error)
                goto std_return;
 
@@ -2839,7 +2860,7 @@ xfs_mkdir(
                goto error_return;
        }
 
-       xfs_ilock(dp, XFS_ILOCK_EXCL);
+       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 
        /*
         * Check for directory link count overflow.
@@ -2936,7 +2957,7 @@ xfs_mkdir(
                goto error2;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        XFS_QM_DQRELE(mp, udqp);
        XFS_QM_DQRELE(mp, gdqp);
        if (error) {
@@ -3096,7 +3117,7 @@ xfs_rmdir(
         * that the directory entry for the child directory inode has
         * not changed while we were obtaining a log reservation.
         */
-       error = xfs_lock_dir_and_entry(dp, dentry, cdp);
+       error = xfs_lock_dir_and_entry(dp, cdp);
        if (error) {
                xfs_trans_cancel(tp, cancel_flags);
                IRELE(cdp);
@@ -3190,7 +3211,7 @@ xfs_rmdir(
                goto std_return;
        }
 
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
                IRELE(cdp);
                goto std_return;
@@ -3393,7 +3414,7 @@ xfs_symlink(
                goto error_return;
        }
 
-       xfs_ilock(dp, XFS_ILOCK_EXCL);
+       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 
        /*
         * Check whether the directory allows new symlinks or not.
@@ -3535,7 +3556,7 @@ xfs_symlink(
        if (error) {
                goto error2;
        }
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        XFS_QM_DQRELE(mp, udqp);
        XFS_QM_DQRELE(mp, gdqp);
 
@@ -3790,7 +3811,7 @@ xfs_set_dmattrs (
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        IHOLD(ip);
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
        return error;
 }
@@ -4049,14 +4070,14 @@ xfs_alloc_file_space(
        allocatesize_fsb = XFS_B_TO_FSB(mp, count);
 
        /*      Generate a DMAPI event if needed.       */
-       if (alloc_type != 0 && offset < ip->i_d.di_size &&
+       if (alloc_type != 0 && offset < ip->i_size &&
                        (attr_flags&ATTR_DMI) == 0  &&
                        DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
                xfs_off_t           end_dmi_offset;
 
                end_dmi_offset = offset+len;
-               if (end_dmi_offset > ip->i_d.di_size)
-                       end_dmi_offset = ip->i_d.di_size;
+               if (end_dmi_offset > ip->i_size)
+                       end_dmi_offset = ip->i_size;
                error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
                        offset, end_dmi_offset - offset,
                        0, NULL);
@@ -4148,7 +4169,7 @@ retry:
                        goto error0;
                }
 
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                if (error) {
                        break;
@@ -4283,7 +4304,6 @@ xfs_free_file_space(
        int                     error;
        xfs_fsblock_t           firstfsb;
        xfs_bmap_free_t         free_list;
-       xfs_off_t               ilen;
        xfs_bmbt_irec_t         imap;
        xfs_off_t               ioffset;
        xfs_extlen_t            mod=0;
@@ -4312,11 +4332,11 @@ xfs_free_file_space(
        end_dmi_offset = offset + len;
        endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
 
-       if (offset < ip->i_d.di_size &&
+       if (offset < ip->i_size &&
            (attr_flags & ATTR_DMI) == 0 &&
            DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
-               if (end_dmi_offset > ip->i_d.di_size)
-                       end_dmi_offset = ip->i_d.di_size;
+               if (end_dmi_offset > ip->i_size)
+                       end_dmi_offset = ip->i_size;
                error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
                                offset, end_dmi_offset - offset,
                                AT_DELAY_FLAG(attr_flags), NULL);
@@ -4332,16 +4352,15 @@ xfs_free_file_space(
        }
 
        rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
-       ilen = len + (offset & (rounding - 1));
        ioffset = offset & ~(rounding - 1);
-       if (ilen & (rounding - 1))
-               ilen = (ilen + rounding) & ~(rounding - 1);
 
        if (VN_CACHED(vp) != 0) {
                xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
                                ctooff(offtoct(ioffset)), -1);
-               bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
+               error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
                                -1, FI_REMAPF_LOCKED);
+               if (error)
+                       goto out_unlock_iolock;
        }
 
        /*
@@ -4455,7 +4474,7 @@ xfs_free_file_space(
                        goto error0;
                }
 
-               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
 
@@ -4533,7 +4552,7 @@ xfs_change_file_space(
                bf->l_start += offset;
                break;
        case 2: /*SEEK_END*/
-               bf->l_start += ip->i_d.di_size;
+               bf->l_start += ip->i_size;
                break;
        default:
                return XFS_ERROR(EINVAL);
@@ -4550,7 +4569,7 @@ xfs_change_file_space(
        bf->l_whence = 0;
 
        startoffset = bf->l_start;
-       fsize = ip->i_d.di_size;
+       fsize = ip->i_size;
 
        /*
         * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve
@@ -4649,7 +4668,7 @@ xfs_change_file_space(
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        xfs_trans_set_sync(tp);
 
-       error = xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
index 16c3c441256ebf476941bcad836b29aabbe563e6..9cfd5b1a48eb8e9a42df7bb02009d4d3abb0eca8 100644 (file)
@@ -303,6 +303,9 @@ struct acpi_device {
 #define to_acpi_device(d)      container_of(d, struct acpi_device, dev)
 #define to_acpi_driver(d)      container_of(d, struct acpi_driver, drv)
 
+/* acpi_device.dev.bus == &acpi_bus_type */
+extern struct bus_type acpi_bus_type;
+
 /*
  * Events
  * ------
index fc77f74130832a099ab91bf26449f1f3ea348690..f5cb7b878af25ba2dd69abb0343327db8c183dd4 100644 (file)
@@ -2,6 +2,7 @@
 #define _ALPHA_ATOMIC_H
 
 #include <asm/barrier.h>
+#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -175,19 +176,64 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
        return result;
 }
 
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
 #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
 
diff --git a/include/asm-alpha/kdebug.h b/include/asm-alpha/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 90a510fa358e820800b6520ed3c7172f583b497e..6ad3ea6964219509b91521f8e19c660c1e06d94f 100644 (file)
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
-typedef atomic64_t local_t;
+typedef struct
+{
+       atomic_long_t a;
+} local_t;
 
-#define LOCAL_INIT(i)  ATOMIC64_INIT(i)
-#define local_read(v)  atomic64_read(v)
-#define local_set(v,i) atomic64_set(v,i)
+#define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
+#define local_read(l)  atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set(&(l)->a, (i))
+#define local_inc(l)   atomic_long_inc(&(l)->a)
+#define local_dec(l)   atomic_long_dec(&(l)->a)
+#define local_add(i,l) atomic_long_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
 
-#define local_inc(v)   atomic64_inc(v)
-#define local_dec(v)   atomic64_dec(v)
-#define local_add(i, v)        atomic64_add(i, v)
-#define local_sub(i, v)        atomic64_sub(i, v)
+static __inline__ long local_add_return(long i, local_t * l)
+{
+       long temp, result;
+       __asm__ __volatile__(
+       "1:     ldq_l %0,%1\n"
+       "       addq %0,%3,%2\n"
+       "       addq %0,%3,%0\n"
+       "       stq_c %0,%1\n"
+       "       beq %0,2f\n"
+       ".subsection 2\n"
+       "2:     br 1b\n"
+       ".previous"
+       :"=&r" (temp), "=m" (l->a.counter), "=&r" (result)
+       :"Ir" (i), "m" (l->a.counter) : "memory");
+       return result;
+}
 
-#define __local_inc(v)         ((v)->counter++)
-#define __local_dec(v)         ((v)->counter++)
-#define __local_add(i,v)       ((v)->counter+=(i))
-#define __local_sub(i,v)       ((v)->counter-=(i))
+static __inline__ long local_sub_return(long i, local_t * l)
+{
+       long temp, result;
+       __asm__ __volatile__(
+       "1:     ldq_l %0,%1\n"
+       "       subq %0,%3,%2\n"
+       "       subq %0,%3,%0\n"
+       "       stq_c %0,%1\n"
+       "       beq %0,2f\n"
+       ".subsection 2\n"
+       "2:     br 1b\n"
+       ".previous"
+       :"=&r" (temp), "=m" (l->a.counter), "=&r" (result)
+       :"Ir" (i), "m" (l->a.counter) : "memory");
+       return result;
+}
+
+#define local_cmpxchg(l, o, n) \
+       (cmpxchg_local(&((l)->a.counter), (o), (n)))
+#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n)))
+
+/**
+ * local_add_unless - add unless the number is a given value
+ * @l: pointer of type local_t
+ * @a: the amount to add to l...
+ * @u: ...unless l is equal to u.
+ *
+ * Atomically adds @a to @l, so long as it was not @u.
+ * Returns non-zero if @l was not @u, and zero otherwise.
+ */
+#define local_add_unless(l, a, u)                              \
+({                                                             \
+       long c, old;                                            \
+       c = local_read(l);                                      \
+       for (;;) {                                              \
+               if (unlikely(c == (u)))                         \
+                       break;                                  \
+               old = local_cmpxchg((l), c, c + (a));   \
+               if (likely(old == c))                           \
+                       break;                                  \
+               c = old;                                        \
+       }                                                       \
+       c != (u);                                               \
+})
+#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+
+#define local_add_negative(a, l) (local_add_return((a), (l)) < 0)
+
+#define local_dec_return(l) local_sub_return(1,(l))
+
+#define local_inc_return(l) local_add_return(1,(l))
+
+#define local_sub_and_test(i,l) (local_sub_return((i), (l)) == 0)
+
+#define local_inc_and_test(l) (local_add_return(1, (l)) == 0)
+
+#define local_dec_and_test(l) (local_sub_return(1, (l)) == 0)
+
+/* Verify if faster than atomic ops */
+#define __local_inc(l)         ((l)->a.counter++)
+#define __local_dec(l)         ((l)->a.counter++)
+#define __local_add(i,l)       ((l)->a.counter+=(i))
+#define __local_sub(i,l)       ((l)->a.counter-=(i))
 
 /* Use these for per-cpu local_t variables: on some archs they are
  * much more efficient than these naive implementations.  Note they take
  * a variable, not an address.
  */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
-
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
-
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
+#define cpu_local_read(l)      local_read(&__get_cpu_var(l))
+#define cpu_local_set(l, i)    local_set(&__get_cpu_var(l), (i))
+
+#define cpu_local_inc(l)       local_inc(&__get_cpu_var(l))
+#define cpu_local_dec(l)       local_dec(&__get_cpu_var(l))
+#define cpu_local_add(i, l)    local_add((i), &__get_cpu_var(l))
+#define cpu_local_sub(i, l)    local_sub((i), &__get_cpu_var(l))
+
+#define __cpu_local_inc(l)     __local_inc(&__get_cpu_var(l))
+#define __cpu_local_dec(l)     __local_dec(&__get_cpu_var(l))
+#define __cpu_local_add(i, l)  __local_add((i), &__get_cpu_var(l))
+#define __cpu_local_sub(i, l)  __local_sub((i), &__get_cpu_var(l))
 
 #endif /* _ALPHA_LOCAL_H */
index 49ac9bee7ced240390a732ac159169b963772fd3..616d20662ff343cec53dbd069487cae7013f7298 100644 (file)
@@ -345,10 +345,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 #define io_remap_pfn_range(vma, start, pfn, size, prot)        \
                remap_pfn_range(vma, start, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
index a1a1eca6be45b0e3ebe72d9d236071719ba979d9..286e1d844f635e53c1903ab452ef283be423d75e 100644 (file)
@@ -51,6 +51,7 @@ int smp_call_function_on_cpu(void (*func) (void *info), void *info,int retry, in
 
 #else /* CONFIG_SMP */
 
+#define hard_smp_processor_id()                0
 #define smp_call_function_on_cpu(func,info,retry,wait,cpu)    ({ 0; })
 
 #endif /* CONFIG_SMP */
index 03e9c0e5ed7451d99161959d0d6f716e6789984c..cf1021a97b2ea947969f3f3344b0261e907e87ba 100644 (file)
@@ -443,8 +443,110 @@ extern void __xchg_called_with_bad_pointer(void);
      (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
   })
 
-#define tas(ptr) (xchg((ptr),1))
+static inline unsigned long
+__xchg_u8_local(volatile char *m, unsigned long val)
+{
+       unsigned long ret, tmp, addr64;
+
+       __asm__ __volatile__(
+       "       andnot  %4,7,%3\n"
+       "       insbl   %1,%4,%1\n"
+       "1:     ldq_l   %2,0(%3)\n"
+       "       extbl   %2,%4,%0\n"
+       "       mskbl   %2,%4,%2\n"
+       "       or      %1,%2,%2\n"
+       "       stq_c   %2,0(%3)\n"
+       "       beq     %2,2f\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
+       : "r" ((long)m), "1" (val) : "memory");
 
+       return ret;
+}
+
+static inline unsigned long
+__xchg_u16_local(volatile short *m, unsigned long val)
+{
+       unsigned long ret, tmp, addr64;
+
+       __asm__ __volatile__(
+       "       andnot  %4,7,%3\n"
+       "       inswl   %1,%4,%1\n"
+       "1:     ldq_l   %2,0(%3)\n"
+       "       extwl   %2,%4,%0\n"
+       "       mskwl   %2,%4,%2\n"
+       "       or      %1,%2,%2\n"
+       "       stq_c   %2,0(%3)\n"
+       "       beq     %2,2f\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
+       : "r" ((long)m), "1" (val) : "memory");
+
+       return ret;
+}
+
+static inline unsigned long
+__xchg_u32_local(volatile int *m, unsigned long val)
+{
+       unsigned long dummy;
+
+       __asm__ __volatile__(
+       "1:     ldl_l %0,%4\n"
+       "       bis $31,%3,%1\n"
+       "       stl_c %1,%2\n"
+       "       beq %1,2f\n"
+       ".subsection 2\n"
+       "2:     br 1b\n"
+       ".previous"
+       : "=&r" (val), "=&r" (dummy), "=m" (*m)
+       : "rI" (val), "m" (*m) : "memory");
+
+       return val;
+}
+
+static inline unsigned long
+__xchg_u64_local(volatile long *m, unsigned long val)
+{
+       unsigned long dummy;
+
+       __asm__ __volatile__(
+       "1:     ldq_l %0,%4\n"
+       "       bis $31,%3,%1\n"
+       "       stq_c %1,%2\n"
+       "       beq %1,2f\n"
+       ".subsection 2\n"
+       "2:     br 1b\n"
+       ".previous"
+       : "=&r" (val), "=&r" (dummy), "=m" (*m)
+       : "rI" (val), "m" (*m) : "memory");
+
+       return val;
+}
+
+#define __xchg_local(ptr, x, size) \
+({ \
+       unsigned long __xchg__res; \
+       volatile void *__xchg__ptr = (ptr); \
+       switch (size) { \
+               case 1: __xchg__res = __xchg_u8_local(__xchg__ptr, x); break; \
+               case 2: __xchg__res = __xchg_u16_local(__xchg__ptr, x); break; \
+               case 4: __xchg__res = __xchg_u32_local(__xchg__ptr, x); break; \
+               case 8: __xchg__res = __xchg_u64_local(__xchg__ptr, x); break; \
+               default: __xchg_called_with_bad_pointer(); __xchg__res = x; \
+       } \
+       __xchg__res; \
+})
+
+#define xchg_local(ptr,x)                                                   \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,           \
+               sizeof(*(ptr))); \
+  })
 
 /* 
  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
@@ -596,6 +698,128 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
                                    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+static inline unsigned long
+__cmpxchg_u8_local(volatile char *m, long old, long new)
+{
+       unsigned long prev, tmp, cmp, addr64;
+
+       __asm__ __volatile__(
+       "       andnot  %5,7,%4\n"
+       "       insbl   %1,%5,%1\n"
+       "1:     ldq_l   %2,0(%4)\n"
+       "       extbl   %2,%5,%0\n"
+       "       cmpeq   %0,%6,%3\n"
+       "       beq     %3,2f\n"
+       "       mskbl   %2,%5,%2\n"
+       "       or      %1,%2,%2\n"
+       "       stq_c   %2,0(%4)\n"
+       "       beq     %2,3f\n"
+       "2:\n"
+       ".subsection 2\n"
+       "3:     br      1b\n"
+       ".previous"
+       : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
+       : "r" ((long)m), "Ir" (old), "1" (new) : "memory");
+
+       return prev;
+}
+
+static inline unsigned long
+__cmpxchg_u16_local(volatile short *m, long old, long new)
+{
+       unsigned long prev, tmp, cmp, addr64;
+
+       __asm__ __volatile__(
+       "       andnot  %5,7,%4\n"
+       "       inswl   %1,%5,%1\n"
+       "1:     ldq_l   %2,0(%4)\n"
+       "       extwl   %2,%5,%0\n"
+       "       cmpeq   %0,%6,%3\n"
+       "       beq     %3,2f\n"
+       "       mskwl   %2,%5,%2\n"
+       "       or      %1,%2,%2\n"
+       "       stq_c   %2,0(%4)\n"
+       "       beq     %2,3f\n"
+       "2:\n"
+       ".subsection 2\n"
+       "3:     br      1b\n"
+       ".previous"
+       : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
+       : "r" ((long)m), "Ir" (old), "1" (new) : "memory");
+
+       return prev;
+}
+
+static inline unsigned long
+__cmpxchg_u32_local(volatile int *m, int old, int new)
+{
+       unsigned long prev, cmp;
+
+       __asm__ __volatile__(
+       "1:     ldl_l %0,%5\n"
+       "       cmpeq %0,%3,%1\n"
+       "       beq %1,2f\n"
+       "       mov %4,%1\n"
+       "       stl_c %1,%2\n"
+       "       beq %1,3f\n"
+       "2:\n"
+       ".subsection 2\n"
+       "3:     br 1b\n"
+       ".previous"
+       : "=&r"(prev), "=&r"(cmp), "=m"(*m)
+       : "r"((long) old), "r"(new), "m"(*m) : "memory");
+
+       return prev;
+}
+
+static inline unsigned long
+__cmpxchg_u64_local(volatile long *m, unsigned long old, unsigned long new)
+{
+       unsigned long prev, cmp;
+
+       __asm__ __volatile__(
+       "1:     ldq_l %0,%5\n"
+       "       cmpeq %0,%3,%1\n"
+       "       beq %1,2f\n"
+       "       mov %4,%1\n"
+       "       stq_c %1,%2\n"
+       "       beq %1,3f\n"
+       "2:\n"
+       ".subsection 2\n"
+       "3:     br 1b\n"
+       ".previous"
+       : "=&r"(prev), "=&r"(cmp), "=m"(*m)
+       : "r"((long) old), "r"(new), "m"(*m) : "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+               int size)
+{
+       switch (size) {
+               case 1:
+                       return __cmpxchg_u8_local(ptr, old, new);
+               case 2:
+                       return __cmpxchg_u16_local(ptr, old, new);
+               case 4:
+                       return __cmpxchg_u32_local(ptr, old, new);
+               case 8:
+                       return __cmpxchg_u64_local(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg_local(ptr,o,n)                                          \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
index eeb3bef91e116b7fe95c4f7b17ee02ea25538285..f4defc2bd3fb246e225717c527e7c7e5c855ee4a 100644 (file)
@@ -97,7 +97,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
                                 1 << TIF_UAC_SIGBUS)
 
 #define SET_UNALIGN_CTL(task,value)    ({                                   \
-       (task)->thread_info->flags = (((task)->thread_info->flags &          \
+       task_thread_info(task)->flags = ((task_thread_info(task)->flags &    \
                ~ALPHA_UAC_MASK)                                             \
                | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
                | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
@@ -105,11 +105,11 @@ register struct thread_info *__current_thread_info __asm__("$8");
        0; })
 
 #define GET_UNALIGN_CTL(task,value)    ({                              \
-       put_user(((task)->thread_info->flags & (1 << TIF_UAC_NOPRINT))  \
+       put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\
                  >> ALPHA_UAC_SHIFT                                    \
-                | ((task)->thread_info->flags & (1 << TIF_UAC_SIGBUS)) \
+                | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\
                 >> (ALPHA_UAC_SHIFT + 1)                               \
-                | ((task)->thread_info->flags & (1 << TIF_UAC_NOFIX))  \
+                | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\
                 >> (ALPHA_UAC_SHIFT - 1),                              \
                 (int __user *)(value));                                \
        })
index a12ac8ab2ad081992349b924169c9c5148da1238..802891a9cd81d76089c980ae1ea02df5fa969e3f 100644 (file)
 #define AT91RM9200_UHP_BASE    0x00300000      /* USB Host controller */
 
 
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-#define AT91_PA0_MISO          (1 <<  0)       /* A: SPI Master-In Slave-Out */
-#define AT91_PA0_PCK3          (1 <<  0)       /* B: PMC Programmable Clock Output 3 */
-#define AT91_PA1_MOSI          (1 <<  1)       /* A: SPI Master-Out Slave-In */
-#define AT91_PA1_PCK0          (1 <<  1)       /* B: PMC Programmable Clock Output 0 */
-#define AT91_PA2_SPCK          (1 <<  2)       /* A: SPI Serial Clock */
-#define AT91_PA2_IRQ4          (1 <<  2)       /* B: External Interrupt 4 */
-#define AT91_PA3_NPCS0         (1 <<  3)       /* A: SPI Peripheral Chip Select 0 */
-#define AT91_PA3_IRQ5          (1 <<  3)       /* B: External Interrupt 5 */
-#define AT91_PA4_NPCS1         (1 <<  4)       /* A: SPI Peripheral Chip Select 1 */
-#define AT91_PA4_PCK1          (1 <<  4)       /* B: PMC Programmable Clock Output 1 */
-#define AT91_PA5_NPCS2         (1 <<  5)       /* A: SPI Peripheral Chip Select 2 */
-#define AT91_PA5_TXD3          (1 <<  5)       /* B: USART Transmit Data 3 */
-#define AT91_PA6_NPCS3         (1 <<  6)       /* A: SPI Peripheral Chip Select 3 */
-#define AT91_PA6_RXD3          (1 <<  6)       /* B: USART Receive Data 3 */
-#define AT91_PA7_ETXCK_EREFCK  (1 <<  7)       /* A: Ethernet Reference Clock / Transmit Clock */
-#define AT91_PA7_PCK2          (1 <<  7)       /* B: PMC Programmable Clock Output 2 */
-#define AT91_PA8_ETXEN         (1 <<  8)       /* A: Ethernet Transmit Enable */
-#define AT91_PA8_MCCDB         (1 <<  8)       /* B: MMC Multimedia Card B Command */
-#define AT91_PA9_ETX0          (1 <<  9)       /* A: Ethernet Transmit Data 0 */
-#define AT91_PA9_MCDB0         (1 <<  9)       /* B: MMC Multimedia Card B Data 0 */
-#define AT91_PA10_ETX1         (1 << 10)       /* A: Ethernet Transmit Data 1 */
-#define AT91_PA10_MCDB1                (1 << 10)       /* B: MMC Multimedia Card B Data 1 */
-#define AT91_PA11_ECRS_ECRSDV  (1 << 11)       /* A: Ethernet Carrier Sense / Data Valid */
-#define AT91_PA11_MCDB2                (1 << 11)       /* B: MMC Multimedia Card B Data 2 */
-#define AT91_PA12_ERX0         (1 << 12)       /* A: Ethernet Receive Data 0 */
-#define AT91_PA12_MCDB3                (1 << 12)       /* B: MMC Multimedia Card B Data 3 */
-#define AT91_PA13_ERX1         (1 << 13)       /* A: Ethernet Receive Data 1 */
-#define AT91_PA13_TCLK0                (1 << 13)       /* B: TC External Clock Input 0 */
-#define AT91_PA14_ERXER                (1 << 14)       /* A: Ethernet Receive Error */
-#define AT91_PA14_TCLK1                (1 << 14)       /* B: TC External Clock Input 1 */
-#define AT91_PA15_EMDC         (1 << 15)       /* A: Ethernet Management Data Clock */
-#define AT91_PA15_TCLK2                (1 << 15)       /* B: TC External Clock Input 2 */
-#define AT91_PA16_EMDIO                (1 << 16)       /* A: Ethernet Management Data I/O */
-#define AT91_PA16_IRQ6         (1 << 16)       /* B: External Interrupt 6 */
-#define AT91_PA17_TXD0         (1 << 17)       /* A: USART Transmit Data 0 */
-#define AT91_PA17_TIOA0                (1 << 17)       /* B: TC I/O Line A 0 */
-#define AT91_PA18_RXD0         (1 << 18)       /* A: USART Receive Data 0 */
-#define AT91_PA18_TIOB0                (1 << 18)       /* B: TC I/O Line B 0 */
-#define AT91_PA19_SCK0         (1 << 19)       /* A: USART Serial Clock 0 */
-#define AT91_PA19_TIOA1                (1 << 19)       /* B: TC I/O Line A 1 */
-#define AT91_PA20_CTS0         (1 << 20)       /* A: USART Clear To Send 0 */
-#define AT91_PA20_TIOB1                (1 << 20)       /* B: TC I/O Line B 1 */
-#define AT91_PA21_RTS0         (1 << 21)       /* A: USART Ready To Send 0 */
-#define AT91_PA21_TIOA2                (1 << 21)       /* B: TC I/O Line A 2 */
-#define AT91_PA22_RXD2         (1 << 22)       /* A: USART Receive Data 2 */
-#define AT91_PA22_TIOB2                (1 << 22)       /* B: TC I/O Line B 2 */
-#define AT91_PA23_TXD2         (1 << 23)       /* A: USART Transmit Data 2 */
-#define AT91_PA23_IRQ3         (1 << 23)       /* B: External Interrupt 3 */
-#define AT91_PA24_SCK2         (1 << 24)       /* A: USART Serial Clock 2 */
-#define AT91_PA24_PCK1         (1 << 24)       /* B: PMC Programmable Clock Output 1 */
-#define AT91_PA25_TWD          (1 << 25)       /* A: TWI Two-wire Serial Data */
-#define AT91_PA25_IRQ2         (1 << 25)       /* B: External Interrupt 2 */
-#define AT91_PA26_TWCK         (1 << 26)       /* A: TWI Two-wire Serial Clock */
-#define AT91_PA26_IRQ1         (1 << 26)       /* B: External Interrupt 1 */
-#define AT91_PA27_MCCK         (1 << 27)       /* A: MMC Multimedia Card Clock */
-#define AT91_PA27_TCLK3                (1 << 27)       /* B: TC External Clock Input 3 */
-#define AT91_PA28_MCCDA                (1 << 28)       /* A: MMC Multimedia Card A Command */
-#define AT91_PA28_TCLK4                (1 << 28)       /* B: TC External Clock Input 4 */
-#define AT91_PA29_MCDA0                (1 << 29)       /* A: MMC Multimedia Card A Data 0 */
-#define AT91_PA29_TCLK5                (1 << 29)       /* B: TC External Clock Input 5 */
-#define AT91_PA30_DRXD         (1 << 30)       /* A: DBGU Receive Data */
-#define AT91_PA30_CTS2         (1 << 30)       /* B: USART Clear To Send 2 */
-#define AT91_PA31_DTXD         (1 << 31)       /* A: DBGU Transmit Data */
-#define AT91_PA31_RTS2         (1 << 31)       /* B: USART Ready To Send 2 */
-
-#define AT91_PB0_TF0           (1 <<  0)       /* A: SSC Transmit Frame Sync 0 */
-#define AT91_PB0_RTS3          (1 <<  0)       /* B: USART Ready To Send 3 */
-#define AT91_PB1_TK0           (1 <<  1)       /* A: SSC Transmit Clock 0 */
-#define AT91_PB1_CTS3          (1 <<  1)       /* B: USART Clear To Send 3 */
-#define AT91_PB2_TD0           (1 <<  2)       /* A: SSC Transmit Data 0 */
-#define AT91_PB2_SCK3          (1 <<  2)       /* B: USART Serial Clock 3 */
-#define AT91_PB3_RD0           (1 <<  3)       /* A: SSC Receive Data 0 */
-#define AT91_PB3_MCDA1         (1 <<  3)       /* B: MMC Multimedia Card A Data 1 */
-#define AT91_PB4_RK0           (1 <<  4)       /* A: SSC Receive Clock 0 */
-#define AT91_PB4_MCDA2         (1 <<  4)       /* B: MMC Multimedia Card A Data 2 */
-#define AT91_PB5_RF0           (1 <<  5)       /* A: SSC Receive Frame Sync 0 */
-#define AT91_PB5_MCDA3         (1 <<  5)       /* B: MMC Multimedia Card A Data 3 */
-#define AT91_PB6_TF1           (1 <<  6)       /* A: SSC Transmit Frame Sync 1 */
-#define AT91_PB6_TIOA3         (1 <<  6)       /* B: TC I/O Line A 3 */
-#define AT91_PB7_TK1           (1 <<  7)       /* A: SSC Transmit Clock 1 */
-#define AT91_PB7_TIOB3         (1 <<  7)       /* B: TC I/O Line B 3 */
-#define AT91_PB8_TD1           (1 <<  8)       /* A: SSC Transmit Data 1 */
-#define AT91_PB8_TIOA4         (1 <<  8)       /* B: TC I/O Line A 4 */
-#define AT91_PB9_RD1           (1 <<  9)       /* A: SSC Receive Data 1 */
-#define AT91_PB9_TIOB4         (1 <<  9)       /* B: TC I/O Line B 4 */
-#define AT91_PB10_RK1          (1 << 10)       /* A: SSC Receive Clock 1 */
-#define AT91_PB10_TIOA5                (1 << 10)       /* B: TC I/O Line A 5 */
-#define AT91_PB11_RF1          (1 << 11)       /* A: SSC Receive Frame Sync 1 */
-#define AT91_PB11_TIOB5                (1 << 11)       /* B: TC I/O Line B 5 */
-#define AT91_PB12_TF2          (1 << 12)       /* A: SSC Transmit Frame Sync 2 */
-#define AT91_PB12_ETX2         (1 << 12)       /* B: Ethernet Transmit Data 2 */
-#define AT91_PB13_TK2          (1 << 13)       /* A: SSC Transmit Clock 3 */
-#define AT91_PB13_ETX3         (1 << 13)       /* B: Ethernet Transmit Data 3 */
-#define AT91_PB14_TD2          (1 << 14)       /* A: SSC Transmit Data 2 */
-#define AT91_PB14_ETXER                (1 << 14)       /* B: Ethernet Transmit Coding Error */
-#define AT91_PB15_RD2          (1 << 15)       /* A: SSC Receive Data 2 */
-#define AT91_PB15_ERX2         (1 << 15)       /* B: Ethernet Receive Data 2 */
-#define AT91_PB16_RK2          (1 << 16)       /* A: SSC Receive Clock 2 */
-#define AT91_PB16_ERX3         (1 << 16)       /* B: Ethernet Receive Data 3 */
-#define AT91_PB17_RF2          (1 << 17)       /* A: SSC Receive Frame Sync 2 */
-#define AT91_PB17_ERXDV                (1 << 17)       /* B: Ethernet Receive Data Valid */
-#define AT91_PB18_RI1          (1 << 18)       /* A: USART Ring Indicator 1 */
-#define AT91_PB18_ECOL         (1 << 18)       /* B: Ethernet Collision Detected */
-#define AT91_PB19_DTR1         (1 << 19)       /* A: USART Data Terminal Ready 1 */
-#define AT91_PB19_ERXCK                (1 << 19)       /* B: Ethernet Receive Clock */
-#define AT91_PB20_TXD1         (1 << 20)       /* A: USART Transmit Data 1 */
-#define AT91_PB21_RXD1         (1 << 21)       /* A: USART Receive Data 1 */
-#define AT91_PB22_SCK1         (1 << 22)       /* A: USART Serial Clock 1 */
-#define AT91_PB23_DCD1         (1 << 23)       /* A: USART Data Carrier Detect 1 */
-#define AT91_PB24_CTS1         (1 << 24)       /* A: USART Clear To Send 1 */
-#define AT91_PB25_DSR1         (1 << 25)       /* A: USART Data Set Ready 1 */
-#define AT91_PB25_EF100                (1 << 25)       /* B: Ethernet Force 100 Mbit */
-#define AT91_PB26_RTS1         (1 << 26)       /* A: USART Ready To Send 1 */
-#define AT91_PB27_PCK0         (1 << 27)       /* B: PMC Programmable Clock Output 0 */
-#define AT91_PB28_FIQ          (1 << 28)       /* A: Fast Interrupt */
-#define AT91_PB29_IRQ0         (1 << 29)       /* A: External Interrupt 0 */
-
-#define AT91_PC0_BFCK          (1 <<  0)       /* A: Burst Flash Clock */
-#define AT91_PC1_BFRDY_SMOE    (1 <<  1)       /* A: Burst Flash Ready / SmartMedia Output Enable */
-#define AT91_PC2_BFAVD         (1 <<  2)       /* A: Burst Flash Address Valid */
-#define AT91_PC3_BFBAA_SMWE    (1 <<  3)       /* A: Burst Flash Address Advance / SmartMedia Write Enable */
-#define AT91_PC4_BFOE          (1 <<  4)       /* A: Burst Flash Output Enable */
-#define AT91_PC5_BFWE          (1 <<  5)       /* A: Burst Flash Write Enable */
-#define AT91_PC6_NWAIT         (1 <<  6)       /* A: SMC Wait Signal */
-#define AT91_PC7_A23           (1 <<  7)       /* A: Address Bus 23 */
-#define AT91_PC8_A24           (1 <<  8)       /* A: Address Bus 24 */
-#define AT91_PC9_A25_CFRNW     (1 <<  9)       /* A: Address Bus 25 / Compact Flash Read Not Write */
-#define AT91_PC10_NCS4_CFCS    (1 << 10)       /* A: SMC Chip Select 4 / Compact Flash Chip Select */
-#define AT91_PC11_NCS5_CFCE1   (1 << 11)       /* A: SMC Chip Select 5 / Compact Flash Chip Enable 1 */
-#define AT91_PC12_NCS6_CFCE2   (1 << 12)       /* A: SMC Chip Select 6 / Compact Flash Chip Enable 2 */
-#define AT91_PC13_NCS7         (1 << 13)       /* A: Chip Select 7 */
-
-#define AT91_PD0_ETX0          (1 <<  0)       /* A: Ethernet Transmit Data 0 */
-#define AT91_PD1_ETX1          (1 <<  1)       /* A: Ethernet Transmit Data 1 */
-#define AT91_PD2_ETX2          (1 <<  2)       /* A: Ethernet Transmit Data 2 */
-#define AT91_PD3_ETX3          (1 <<  3)       /* A: Ethernet Transmit Data 3 */
-#define AT91_PD4_ETXEN         (1 <<  4)       /* A: Ethernet Transmit Enable */
-#define AT91_PD5_ETXER         (1 <<  5)       /* A: Ethernet Transmit Coding Error */
-#define AT91_PD6_DTXD          (1 <<  6)       /* A: DBGU Transmit Data */
-#define AT91_PD7_PCK0          (1 <<  7)       /* A: PMC Programmable Clock Output 0 */
-#define AT91_PD7_TSYNC         (1 <<  7)       /* B: ETM Trace Synchronization Signal */
-#define AT91_PD8_PCK1          (1 <<  8)       /* A: PMC Programmable Clock Output 1 */
-#define AT91_PD8_TCLK          (1 <<  8)       /* B: ETM Trace Clock */
-#define AT91_PD9_PCK2          (1 <<  9)       /* A: PMC Programmable Clock Output 2 */
-#define AT91_PD9_TPS0          (1 <<  9)       /* B: ETM Trace ARM Pipeline Status 0 */
-#define AT91_PD10_PCK3         (1 << 10)       /* A: PMC Programmable Clock Output 3 */
-#define AT91_PD10_TPS1         (1 << 10)       /* B: ETM Trace ARM Pipeline Status 1 */
-#define AT91_PD11_TPS2         (1 << 11)       /* B: ETM Trace ARM Pipeline Status 2 */
-#define AT91_PD12_TPK0         (1 << 12)       /* B: ETM Trace Packet Port 0 */
-#define AT91_PD13_TPK1         (1 << 13)       /* B: ETM Trace Packet Port 1 */
-#define AT91_PD14_TPK2         (1 << 14)       /* B: ETM Trace Packet Port 2 */
-#define AT91_PD15_TD0          (1 << 15)       /* A: SSC Transmit Data 0 */
-#define AT91_PD15_TPK3         (1 << 15)       /* B: ETM Trace Packet Port 3 */
-#define AT91_PD16_TD1          (1 << 16)       /* A: SSC Transmit Data 1 */
-#define AT91_PD16_TPK4         (1 << 16)       /* B: ETM Trace Packet Port 4 */
-#define AT91_PD17_TD2          (1 << 17)       /* A: SSC Transmit Data 2 */
-#define AT91_PD17_TPK5         (1 << 17)       /* B: ETM Trace Packet Port 5 */
-#define AT91_PD18_NPCS1                (1 << 18)       /* A: SPI Peripheral Chip Select 1 */
-#define AT91_PD18_TPK6         (1 << 18)       /* B: ETM Trace Packet Port 6 */
-#define AT91_PD19_NPCS2                (1 << 19)       /* A: SPI Peripheral Chip Select 2 */
-#define AT91_PD19_TPK7         (1 << 19)       /* B: ETM Trace Packet Port 7 */
-#define AT91_PD20_NPCS3                (1 << 20)       /* A: SPI Peripheral Chip Select 3 */
-#define AT91_PD20_TPK8         (1 << 20)       /* B: ETM Trace Packet Port 8 */
-#define AT91_PD21_RTS0         (1 << 21)       /* A: USART Ready To Send 0 */
-#define AT91_PD21_TPK9         (1 << 21)       /* B: ETM Trace Packet Port 9 */
-#define AT91_PD22_RTS1         (1 << 22)       /* A: USART Ready To Send 1 */
-#define AT91_PD22_TPK10                (1 << 22)       /* B: ETM Trace Packet Port 10 */
-#define AT91_PD23_RTS2         (1 << 23)       /* A: USART Ready To Send 2 */
-#define AT91_PD23_TPK11                (1 << 23)       /* B: ETM Trace Packet Port 11 */
-#define AT91_PD24_RTS3         (1 << 24)       /* A: USART Ready To Send 3 */
-#define AT91_PD24_TPK12                (1 << 24)       /* B: ETM Trace Packet Port 12 */
-#define AT91_PD25_DTR1         (1 << 25)       /* A: USART Data Terminal Ready 1 */
-#define AT91_PD25_TPK13                (1 << 25)       /* B: ETM Trace Packet Port 13 */
-#define AT91_PD26_TPK14                (1 << 26)       /* B: ETM Trace Packet Port 14 */
-#define AT91_PD27_TPK15                (1 << 27)       /* B: ETM Trace Packet Port 15 */
-#endif
-
 #endif
index 2cadebc36af70fc233fa35c143c52167df5d86ec..0427f8698c07a8e8f43ec675929b1fd907ebb033 100644 (file)
 #define AT91SAM9XE_SRAM_BASE   0x00300000      /* Internal SRAM base address */
 
 
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-
-// TODO: Add
-
-#endif
-
 #endif
index 01b58ffe2e27c2c86c2502e0bcef41abd95f1516..9eb4595703307832b8cc2224fcab032f1a45ee08 100644 (file)
 #define AT91SAM9261_LCDC_BASE  0x00600000      /* LDC controller */
 
 
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-#define AT91_PA0_SPI0_MISO     (1 <<  0)       /* A: SPI0 Master In Slave */
-#define AT91_PA0_MCDA0         (1 <<  0)       /* B: Multimedia Card A Data 0 */
-#define AT91_PA1_SPI0_MOSI     (1 <<  1)       /* A: SPI0 Master Out Slave */
-#define AT91_PA1_MCCDA         (1 <<  1)       /* B: Multimedia Card A Command */
-#define AT91_PA2_SPI0_SPCK     (1 <<  2)       /* A: SPI0 Serial Clock */
-#define AT91_PA2_MCCK          (1 <<  2)       /* B: Multimedia Card Clock */
-#define AT91_PA3_SPI0_NPCS0    (1 <<  3)       /* A: SPI0 Peripheral Chip Select 0 */
-#define AT91_PA4_SPI0_NPCS1    (1 <<  4)       /* A: SPI0 Peripheral Chip Select 1 */
-#define AT91_PA4_MCDA1         (1 <<  4)       /* B: Multimedia Card A Data 1 */
-#define AT91_PA5_SPI0_NPCS2    (1 <<  5)       /* A: SPI0 Peripheral Chip Select 2 */
-#define AT91_PA5_MCDA2         (1 <<  5)       /* B: Multimedia Card A Data 2 */
-#define AT91_PA6_SPI0_NPCS3    (1 <<  6)       /* A: SPI0 Peripheral Chip Select 3 */
-#define AT91_PA6_MCDA3         (1 <<  6)       /* B: Multimedia Card A Data 3 */
-#define AT91_PA7_TWD           (1 <<  7)       /* A: TWI Two-wire Serial Data */
-#define AT91_PA7_PCK0          (1 <<  7)       /* B: PMC Programmable clock Output 0 */
-#define AT91_PA8_TWCK          (1 <<  8)       /* A: TWI Two-wire Serial Clock */
-#define AT91_PA8_PCK1          (1 <<  8)       /* B: PMC Programmable clock Output 1 */
-#define AT91_PA9_DRXD          (1 <<  9)       /* A: DBGU Debug Receive Data */
-#define AT91_PA9_PCK2          (1 <<  9)       /* B: PMC Programmable clock Output 2 */
-#define AT91_PA10_DTXD         (1 << 10)       /* A: DBGU Debug Transmit Data */
-#define AT91_PA10_PCK3         (1 << 10)       /* B: PMC Programmable clock Output 3 */
-#define AT91_PA11_TSYNC                (1 << 11)       /* A: Trace Synchronization Signal */
-#define AT91_PA11_SCK1         (1 << 11)       /* B: USART1 Serial Clock */
-#define AT91_PA12_TCLK         (1 << 12)       /* A: Trace Clock */
-#define AT91_PA12_RTS1         (1 << 12)       /* B: USART1 Ready To Send */
-#define AT91_PA13_TPS0         (1 << 13)       /* A: Trace ARM Pipeline Status 0 */
-#define AT91_PA13_CTS1         (1 << 13)       /* B: USART1 Clear To Send */
-#define AT91_PA14_TPS1         (1 << 14)       /* A: Trace ARM Pipeline Status 1 */
-#define AT91_PA14_SCK2         (1 << 14)       /* B: USART2 Serial Clock */
-#define AT91_PA15_TPS2         (1 << 15)       /* A: Trace ARM Pipeline Status 2 */
-#define AT91_PA15_RTS2         (1 << 15)       /* B: USART2 Ready To Send */
-#define AT91_PA16_TPK0         (1 << 16)       /* A: Trace Packet Port 0 */
-#define AT91_PA16_CTS2         (1 << 16)       /* B: USART2 Clear To Send */
-#define AT91_PA17_TPK1         (1 << 17)       /* A: Trace Packet Port 1 */
-#define AT91_PA17_TF1          (1 << 17)       /* B: SSC1 Transmit Frame Sync */
-#define AT91_PA18_TPK2         (1 << 18)       /* A: Trace Packet Port 2 */
-#define AT91_PA18_TK1          (1 << 18)       /* B: SSC1 Transmit Clock */
-#define AT91_PA19_TPK3         (1 << 19)       /* A: Trace Packet Port 3 */
-#define AT91_PA19_TD1          (1 << 19)       /* B: SSC1 Transmit Data */
-#define AT91_PA20_TPK4         (1 << 20)       /* A: Trace Packet Port 4 */
-#define AT91_PA20_RD1          (1 << 20)       /* B: SSC1 Receive Data */
-#define AT91_PA21_TPK5         (1 << 21)       /* A: Trace Packet Port 5 */
-#define AT91_PA21_RK1          (1 << 21)       /* B: SSC1 Receive Clock */
-#define AT91_PA22_TPK6         (1 << 22)       /* A: Trace Packet Port 6 */
-#define AT91_PA22_RF1          (1 << 22)       /* B: SSC1 Receive Frame Sync */
-#define AT91_PA23_TPK7         (1 << 23)       /* A: Trace Packet Port 7 */
-#define AT91_PA23_RTS0         (1 << 23)       /* B: USART0 Ready To Send */
-#define AT91_PA24_TPK8         (1 << 24)       /* A: Trace Packet Port 8 */
-#define AT91_PA24_SPI1_NPCS1   (1 << 24)       /* B: SPI1 Peripheral Chip Select 1 */
-#define AT91_PA25_TPK9         (1 << 25)       /* A: Trace Packet Port 9 */
-#define AT91_PA25_SPI1_NPCS2   (1 << 25)       /* B: SPI1 Peripheral Chip Select 2 */
-#define AT91_PA26_TPK10                (1 << 26)       /* A: Trace Packet Port 10 */
-#define AT91_PA26_SPI1_NPCS3   (1 << 26)       /* B: SPI1 Peripheral Chip Select 3 */
-#define AT91_PA27_TPK11                (1 << 27)       /* A: Trace Packet Port 11 */
-#define AT91_PA27_SPI0_NPCS1   (1 << 27)       /* B: SPI0 Peripheral Chip Select 1 */
-#define AT91_PA28_TPK12                (1 << 28)       /* A: Trace Packet Port 12 */
-#define AT91_PA28_SPI0_NPCS2   (1 << 28)       /* B: SPI0 Peripheral Chip Select 2 */
-#define AT91_PA29_TPK13                (1 << 29)       /* A: Trace Packet Port 13 */
-#define AT91_PA29_SPI0_NPCS3   (1 << 29)       /* B: SPI0 Peripheral Chip Select 3 */
-#define AT91_PA30_TPK14                (1 << 30)       /* A: Trace Packet Port 14 */
-#define AT91_PA30_A23          (1 << 30)       /* B: Address Bus bit 23 */
-#define AT91_PA31_TPK15                (1 << 31)       /* A: Trace Packet Port 15 */
-#define AT91_PA31_A24          (1 << 31)       /* B: Address Bus bit 24 */
-
-#define AT91_PB0_LCDVSYNC      (1 <<  0)       /* A: LCD Vertical Synchronization */
-#define AT91_PB1_LCDHSYNC      (1 <<  1)       /* A: LCD Horizontal Synchronization */
-#define AT91_PB2_LCDDOTCK      (1 <<  2)       /* A: LCD Dot Clock */
-#define AT91_PB2_PCK0          (1 <<  2)       /* B: PMC Programmable clock Output 0 */
-#define AT91_PB3_LCDDEN                (1 <<  3)       /* A: LCD Data Enable */
-#define AT91_PB4_LCDCC         (1 <<  4)       /* A: LCD Contrast Control */
-#define AT91_PB4_LCDD2         (1 <<  4)       /* B: LCD Data Bus Bit 2 */
-#define AT91_PB5_LCDD0         (1 <<  5)       /* A: LCD Data Bus Bit 0 */
-#define AT91_PB5_LCDD3         (1 <<  5)       /* B: LCD Data Bus Bit 3 */
-#define AT91_PB6_LCDD1         (1 <<  6)       /* A: LCD Data Bus Bit 1 */
-#define AT91_PB6_LCDD4         (1 <<  6)       /* B: LCD Data Bus Bit 4 */
-#define AT91_PB7_LCDD2         (1 <<  7)       /* A: LCD Data Bus Bit 2 */
-#define AT91_PB7_LCDD5         (1 <<  7)       /* B: LCD Data Bus Bit 5 */
-#define AT91_PB8_LCDD3         (1 <<  8)       /* A: LCD Data Bus Bit 3 */
-#define AT91_PB8_LCDD6         (1 <<  8)       /* B: LCD Data Bus Bit 6 */
-#define AT91_PB9_LCDD4         (1 <<  9)       /* A: LCD Data Bus Bit 4 */
-#define AT91_PB9_LCDD7         (1 <<  9)       /* B: LCD Data Bus Bit 7 */
-#define AT91_PB10_LCDD5                (1 << 10)       /* A: LCD Data Bus Bit 5 */
-#define AT91_PB10_LCDD10       (1 << 10)       /* B: LCD Data Bus Bit 10 */
-#define AT91_PB11_LCDD6                (1 << 11)       /* A: LCD Data Bus Bit 6 */
-#define AT91_PB11_LCDD11       (1 << 11)       /* B: LCD Data Bus Bit 11 */
-#define AT91_PB12_LCDD7                (1 << 12)       /* A: LCD Data Bus Bit 7 */
-#define AT91_PB12_LCDD12       (1 << 12)       /* B: LCD Data Bus Bit 12 */
-#define AT91_PB13_LCDD8                (1 << 13)       /* A: LCD Data Bus Bit 8 */
-#define AT91_PB13_LCDD13       (1 << 13)       /* B: LCD Data Bus Bit 13 */
-#define AT91_PB14_LCDD9                (1 << 14)       /* A: LCD Data Bus Bit 9 */
-#define AT91_PB14_LCDD14       (1 << 14)       /* B: LCD Data Bus Bit 14 */
-#define AT91_PB15_LCDD10       (1 << 15)       /* A: LCD Data Bus Bit 10 */
-#define AT91_PB15_LCDD15       (1 << 15)       /* B: LCD Data Bus Bit 15 */
-#define AT91_PB16_LCDD11       (1 << 16)       /* A: LCD Data Bus Bit 11 */
-#define AT91_PB16_LCDD19       (1 << 16)       /* B: LCD Data Bus Bit 19 */
-#define AT91_PB17_LCDD12       (1 << 17)       /* A: LCD Data Bus Bit 12 */
-#define AT91_PB17_LCDD20       (1 << 17)       /* B: LCD Data Bus Bit 20 */
-#define AT91_PB18_LCDD13       (1 << 18)       /* A: LCD Data Bus Bit 13 */
-#define AT91_PB18_LCDD21       (1 << 18)       /* B: LCD Data Bus Bit 21 */
-#define AT91_PB19_LCDD14       (1 << 19)       /* A: LCD Data Bus Bit 14 */
-#define AT91_PB19_LCDD22       (1 << 19)       /* B: LCD Data Bus Bit 22 */
-#define AT91_PB20_LCDD15       (1 << 20)       /* A: LCD Data Bus Bit 15 */
-#define AT91_PB20_LCDD23       (1 << 20)       /* B: LCD Data Bus Bit 23 */
-#define AT91_PB21_TF0          (1 << 21)       /* A: SSC0 Transmit Frame Sync */
-#define AT91_PB21_LCDD16       (1 << 21)       /* B: LCD Data Bus Bit 16 */
-#define AT91_PB22_TK0          (1 << 22)       /* A: SSC0 Transmit Clock */
-#define AT91_PB22_LCDD17       (1 << 22)       /* B: LCD Data Bus Bit 17 */
-#define AT91_PB23_TD0          (1 << 23)       /* A: SSC0 Transmit Data */
-#define AT91_PB23_LCDD18       (1 << 23)       /* B: LCD Data Bus Bit 18 */
-#define AT91_PB24_RD0          (1 << 24)       /* A: SSC0 Receive Data */
-#define AT91_PB24_LCDD19       (1 << 24)       /* B: LCD Data Bus Bit 19 */
-#define AT91_PB25_RK0          (1 << 25)       /* A: SSC0 Receive Clock */
-#define AT91_PB25_LCDD20       (1 << 25)       /* B: LCD Data Bus Bit 20 */
-#define AT91_PB26_RF0          (1 << 26)       /* A: SSC0 Receive Frame Sync */
-#define AT91_PB26_LCDD21       (1 << 26)       /* B: LCD Data Bus Bit 21 */
-#define AT91_PB27_SPI1_NPCS1   (1 << 27)       /* A: SPI1 Peripheral Chip Select 1 */
-#define AT91_PB27_LCDD22       (1 << 27)       /* B: LCD Data Bus Bit 22 */
-#define AT91_PB28_SPI1_NPCS0   (1 << 28)       /* A: SPI1 Peripheral Chip Select 0 */
-#define AT91_PB28_LCDD23       (1 << 28)       /* B: LCD Data Bus Bit 23 */
-#define AT91_PB29_SPI1_SPCK    (1 << 29)       /* A: SPI1 Serial Clock */
-#define AT91_PB29_IRQ2         (1 << 29)       /* B: Interrupt input 2 */
-#define AT91_PB30_SPI1_MISO    (1 << 30)       /* A: SPI1 Master In Slave */
-#define AT91_PB30_IRQ1         (1 << 30)       /* B: Interrupt input 1 */
-#define AT91_PB31_SPI1_MOSI    (1 << 31)       /* A: SPI1 Master Out Slave */
-#define AT91_PB31_PCK2         (1 << 31)       /* B: PMC Programmable clock Output 2 */
-
-#define AT91_PC0_SMOE          (1 << 0)        /* A: SmartMedia Output Enable */
-#define AT91_PC0_NCS6          (1 << 0)        /* B: Chip Select 6 */
-#define AT91_PC1_SMWE          (1 << 1)        /* A: SmartMedia Write Enable */
-#define AT91_PC1_NCS7          (1 << 1)        /* B: Chip Select 7 */
-#define AT91_PC2_NWAIT         (1 << 2)        /* A: NWAIT */
-#define AT91_PC2_IRQ0          (1 << 2)        /* B: Interrupt input 0 */
-#define AT91_PC3_A25_CFRNW     (1 << 3)        /* A: Address Bus[25] / Compact Flash Read Not Write */
-#define AT91_PC4_NCS4_CFCS0    (1 << 4)        /* A: Chip Select 4 / CompactFlash Chip Select 0 */
-#define AT91_PC5_NCS5_CFCS1    (1 << 5)        /* A: Chip Select 5 / CompactFlash Chip Select 1 */
-#define AT91_PC6_CFCE1         (1 << 6)        /* A: CompactFlash Chip Enable 1 */
-#define AT91_PC7_CFCE2         (1 << 7)        /* A: CompactFlash Chip Enable 2 */
-#define AT91_PC8_TXD0          (1 << 8)        /* A: USART0 Transmit Data */
-#define AT91_PC8_PCK2          (1 << 8)        /* B: PMC Programmable clock Output 2 */
-#define AT91_PC9_RXD0          (1 << 9)        /* A: USART0 Receive Data */
-#define AT91_PC9_PCK3          (1 << 9)        /* B: PMC Programmable clock Output 3 */
-#define AT91_PC10_RTS0         (1 << 10)       /* A: USART0 Ready To Send */
-#define AT91_PC10_SCK0         (1 << 10)       /* B: USART0 Serial Clock */
-#define AT91_PC11_CTS0         (1 << 11)       /* A: USART0 Clear To Send */
-#define AT91_PC11_FIQ          (1 << 11)       /* B: AIC Fast Interrupt Input */
-#define AT91_PC12_TXD1         (1 << 12)       /* A: USART1 Transmit Data */
-#define AT91_PC12_NCS6         (1 << 12)       /* B: Chip Select 6 */
-#define AT91_PC13_RXD1         (1 << 13)       /* A: USART1 Receive Data */
-#define AT91_PC13_NCS7         (1 << 13)       /* B: Chip Select 7 */
-#define AT91_PC14_TXD2         (1 << 14)       /* A: USART2 Transmit Data */
-#define AT91_PC14_SPI1_NPCS2   (1 << 14)       /* B: SPI1 Peripheral Chip Select 2 */
-#define AT91_PC15_RXD2         (1 << 15)       /* A: USART2 Receive Data */
-#define AT91_PC15_SPI1_NPCS3   (1 << 15)       /* B: SPI1 Peripheral Chip Select 3 */
-#define AT91_PC16_D16          (1 << 16)       /* A: Data Bus [16] */
-#define AT91_PC16_TCLK0                (1 << 16)       /* B: Timer Counter 0 external clock input */
-#define AT91_PC17_D17          (1 << 17)       /* A: Data Bus [17] */
-#define AT91_PC17_TCLK1                (1 << 17)       /* B: Timer Counter 1 external clock input */
-#define AT91_PC18_D18          (1 << 18)       /* A: Data Bus [18] */
-#define AT91_PC18_TCLK2                (1 << 18)       /* B: Timer Counter 2 external clock input */
-#define AT91_PC19_D19          (1 << 19)       /* A: Data Bus [19] */
-#define AT91_PC19_TIOA0                (1 << 19)       /* B: Timer Counter 0 Multipurpose Timer I/O Pin A */
-#define AT91_PC20_D20          (1 << 20)       /* A: Data Bus [20] */
-#define AT91_PC20_TIOB0                (1 << 20)       /* B: Timer Counter 0 Multipurpose Timer I/O Pin B */
-#define AT91_PC21_D21          (1 << 21)       /* A: Data Bus [21] */
-#define AT91_PC21_TIOA1                (1 << 21)       /* B: Timer Counter 1 Multipurpose Timer I/O Pin A */
-#define AT91_PC22_D22          (1 << 22)       /* A: Data Bus [22] */
-#define AT91_PC22_TIOB1                (1 << 22)       /* B: Timer Counter 1 Multipurpose Timer I/O Pin B */
-#define AT91_PC23_D23          (1 << 23)       /* A: Data Bus [23] */
-#define AT91_PC23_TIOA2                (1 << 23)       /* B: Timer Counter 2 Multipurpose Timer I/O Pin A */
-#define AT91_PC24_D24          (1 << 24)       /* A: Data Bus [24] */
-#define AT91_PC24_TIOB2                (1 << 24)       /* B: Timer Counter 2 Multipurpose Timer I/O Pin B */
-#define AT91_PC25_D25          (1 << 25)       /* A: Data Bus [25] */
-#define AT91_PC25_TF2          (1 << 25)       /* B: SSC2 Transmit Frame Sync */
-#define AT91_PC26_D26          (1 << 26)       /* A: Data Bus [26] */
-#define AT91_PC26_TK2          (1 << 26)       /* B: SSC2 Transmit Clock */
-#define AT91_PC27_D27          (1 << 27)       /* A: Data Bus [27] */
-#define AT91_PC27_TD2          (1 << 27)       /* B: SSC2 Transmit Data */
-#define AT91_PC28_D28          (1 << 28)       /* A: Data Bus [28] */
-#define AT91_PC28_RD2          (1 << 28)       /* B: SSC2 Receive Data */
-#define AT91_PC29_D29          (1 << 29)       /* A: Data Bus [29] */
-#define AT91_PC29_RK2          (1 << 29)       /* B: SSC2 Receive Clock */
-#define AT91_PC30_D30          (1 << 30)       /* A: Data Bus [30] */
-#define AT91_PC30_RF2          (1 << 30)       /* B: SSC2 Receive Frame Sync */
-#define AT91_PC31_D31          (1 << 31)       /* A: Data Bus [31] */
-#define AT91_PC31_PCK1         (1 << 31)       /* B: PMC Programmable clock Output 1 */
-#endif
-
 #endif
index f4af68ae0ea93f7cbbf427323096d302338944ac..115c47ac7ebb0b22b75d00e1ddcfeaf1dee25a21 100644 (file)
 #define AT91SAM9263_DMAC_BASE  0x00800000      /* DMA Controller */
 #define AT91SAM9263_UHP_BASE   0x00a00000      /* USB Host controller */
 
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-
-// TODO: Add
-
-#endif
 
 #endif
index 7a34a5b1fed0dfa4be4c1de940098b32e070cb51..0ce6ee98ed0be0beb1231e20e3b6ea468e7c059e 100644 (file)
@@ -121,7 +121,7 @@ extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
  /* AC97 */
 struct atmel_ac97_data {
        u8              reset_pin;      /* reset */
-}
+};
 extern void __init at91_add_device_ac97(struct atmel_ac97_data *data);
 
  /* LEDs */
index d464ca58cdbc07e427180d235f590953c13a2fc1..7ef4eebe9f8e9e358f2cc3304d00238c6eece3e7 100644 (file)
@@ -68,4 +68,10 @@ static inline unsigned long at91_arch_identify(void)
 #define cpu_is_at91sam9263()   (0)
 #endif
 
+/*
+ * Since this is ARM, we will never run on any AVR32 CPU. But these
+ * definitions may reduce clutter in common drivers.
+ */
+#define cpu_is_at32ap7000()    (0)
+
 #endif
index de6494a4dc6bc7d8cb92760778fdd20261b35385..30de404c61f5ef71e1243e0dada38cbed8e277c9 100644 (file)
 #define SAR(x)  __REG2( IMX_DMAC_BASE + 0x80, (x) << 6)        /* Source Address Registers */
 #define DAR(x)  __REG2( IMX_DMAC_BASE + 0x84, (x) << 6)        /* Destination Address Registers */
 #define CNTR(x) __REG2( IMX_DMAC_BASE + 0x88, (x) << 6)        /* Count Registers */
-#define CCR(x)  __REG2( IMX_DMAC_BASE + 0x8c, (x) << 6)        /* Control Registers */
+#define CCR(x)  __REG2( IMX_DMAC_BASE + 0x8c, (x) << 6)        /* Control Registers */
 #define RSSR(x) __REG2( IMX_DMAC_BASE + 0x90, (x) << 6)        /* Request source select Registers */
 #define BLR(x)  __REG2( IMX_DMAC_BASE + 0x94, (x) << 6)        /* Burst length Registers */
 #define RTOR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)        /* Request timeout Registers */
index 96ad3d2a66d1ead1ce639fb47569e642ebbb6050..83c4c1ceb411dc2615003c3f0304a9b9b8e9e04d 100644 (file)
@@ -17,7 +17,7 @@
  *                 from .s file by awk -f s2h.awk
  */
 /**************************************************************************
- * * Copyright © ARM Limited 1998.  All rights reserved.
+ * * Copyright Â© ARM Limited 1998.  All rights reserved.
  * ***********************************************************************/
 /* ************************************************************************
  *
index 3b065618dd0009d79eb53c43b098d037d45bba3e..bf0665acc1c13bb47b9a3b18e326a20210281169 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm/arch-iop32x/glantank.h
+ * include/asm-arm/arch-iop32x/glantank.h
  *
  * IO-Data GLAN Tank board registers
  */
index fed31a648425845aa2a3dd2f4c42f239f6afef41..77a8af47662975dedf99c486f41ae0cc66d939ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm/arch-iop32x/n2100.h
+ * include/asm-arm/arch-iop32x/n2100.h
  *
  * Thecus N2100 board registers
  */
index 6513065941d0872753ba5ded51dec517f82393de..aec2d65636229a5a49b05e970481eaf2386986db 100644 (file)
 #define TLV320AIC23ID1                  (0x1a) // cs low
 #define TLV320AIC23ID2                  (0x1b) // cs high
 
-void tlv320aic23_power_up(void);
-void tlv320aic23_power_down(void);
+void aic23_power_up(void);
+void aic23_power_down(void);
 
 #endif /* __ASM_ARCH_AIC23_H */
index de0c5b792c5852aa2190f2cc099e51a8410cc64c..dcb587b311f18fa038b21c38ff0044861a6a9bab 100644 (file)
 #define __ASM_ARCH_OMAP_APOLLON_H
 
 /* Placeholder for APOLLON specific defines */
-/* GPMC CS0 */
-#define APOLLON_CS0_BASE               0x00000000
-/* GPMC CS1 */
-#define APOLLON_CS1_BASE               0x08000000
-#define APOLLON_ETHR_START             (APOLLON_CS1_BASE + 0x300)
 #define APOLLON_ETHR_GPIO_IRQ          74
-/* GPMC CS2 - reserved for OneNAND */
-#define APOLLON_CS2_BASE               0x10000000
-/* GPMC CS3 - reserved for NOR or NAND */
-#define APOLLON_CS3_BASE               0x18000000
 
 #endif /*  __ASM_ARCH_OMAP_APOLLON_H */
 
index 7ef664bc9e330c4b284cdd81042ca38bb670066a..7e0efef4bb65a178d310cf3a107856b85ca5a354 100644 (file)
@@ -30,9 +30,6 @@
 #define __ASM_ARCH_OMAP_H4_H
 
 /* Placeholder for H4 specific defines */
-/* GPMC CS1 */
-#define OMAP24XX_ETHR_START             0x08000300
 #define OMAP24XX_ETHR_GPIO_IRQ         92
-#define H4_CS0_BASE                    0x04000000
 #endif /*  __ASM_ARCH_OMAP_H4_H */
 
index edf1dc6ad919b45ec807807762c1cdcd37c487e8..031672c563777667b6f9f37baadea56137b74b43 100644 (file)
@@ -4,7 +4,7 @@
  *  Information structures for board-specific data
  *
  *  Copyright (C) 2004 Nokia Corporation
- *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
  */
 
 #ifndef _OMAP_BOARD_H
@@ -12,6 +12,8 @@
 
 #include <linux/types.h>
 
+#include <asm/arch/gpio-switch.h>
+
 /* Different peripheral ids */
 #define OMAP_TAG_CLOCK         0x4f01
 #define OMAP_TAG_MMC           0x4f02
@@ -99,26 +101,31 @@ struct omap_usb_config {
 struct omap_lcd_config {
        char panel_name[16];
        char ctrl_name[16];
+       s16  nreset_gpio;
+       u8   data_lines;
+};
+
+struct device;
+struct fb_info;
+struct omap_backlight_config {
+       int default_intensity;
+       int (*set_power)(struct device *dev, int state);
+       int (*check_fb)(struct fb_info *fb);
 };
 
 struct omap_fbmem_config {
-       u32 fb_sram_start;
-       u32 fb_sram_size;
-       u32 fb_sdram_start;
-       u32 fb_sdram_size;
-};
-
-/* Cover:
- *      high -> closed
- *      low  -> open
- * Connection:
- *      high -> connected
- *      low  -> disconnected
- */
-#define OMAP_GPIO_SWITCH_TYPE_COVER            0x0000
-#define OMAP_GPIO_SWITCH_TYPE_CONNECTION       0x0001
-#define OMAP_GPIO_SWITCH_FLAG_INVERTED         0x0001
-#define OMAP_GPIO_SWITCH_FLAG_OUTPUT           0x0002
+       u32 start;
+       u32 size;
+};
+
+struct omap_pwm_led_platform_data {
+       const char *name;
+       int intensity_timer;
+       int blink_timer;
+       void (*set_power)(struct omap_pwm_led_platform_data *self, int on_off);
+};
+
+/* See include/asm-arm/arch-omap/gpio-switch.h for definitions */
 struct omap_gpio_switch_config {
        char name[12];
        u16 gpio;
index d591d0585bbab64f7cb944788ac02c5f957d258c..f7774192a41e7aae5fd716e16e2204e47b0c6bd8 100644 (file)
@@ -2,7 +2,7 @@
  *  linux/include/asm-arm/arch-omap/dma.h
  *
  *  Copyright (C) 2003 Nokia Corporation
- *  Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *  Author: Juha Yrjölä <juha.yrjola@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
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
deleted file mode 100644 (file)
index 06dad83..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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_KFUNC_AUDIO_PWR 0x01
-
-#define OMAP_DSP_MBCMD_FBCTL_UPD       0x0000
-#define OMAP_DSP_MBCMD_FBCTL_ENABLE    0x0002
-#define OMAP_DSP_MBCMD_FBCTL_DISABLE   0x0003
-
-#define OMAP_DSP_MBCMD_AUDIO_PWR_UP    0x0000
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002
-
-#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 */
index 16a459dfa714ab770da53bff8680d90a36a70d6c..c61f868f24ee8de1590c0cb0743f7a0ce8452475 100644 (file)
@@ -1,38 +1,34 @@
 /*
- * linux/include/asm-arm/arch-omap/dsp_common.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for OMAP DSP subsystem control
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * 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
+ * version 2 as published by the Free Software Foundation.
  *
- * 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.
+ * 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
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/03:  DSP Gateway version 3.3
  */
 
 #ifndef ASM_ARCH_DSP_COMMON_H
 #define ASM_ARCH_DSP_COMMON_H
 
+#ifdef CONFIG_ARCH_OMAP1
 extern void omap_dsp_request_mpui(void);
 extern void omap_dsp_release_mpui(void);
 extern int omap_dsp_request_mem(void);
 extern int omap_dsp_release_mem(void);
-
-extern void (*omap_dsp_audio_pwr_up_request)(int stage);
-extern void (*omap_dsp_audio_pwr_down_request)(int stage);
+#endif
 
 #endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/gpio-switch.h b/include/asm-arm/arch-omap/gpio-switch.h
new file mode 100644 (file)
index 0000000..10da0e0
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * GPIO switch definitions
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIO_SWITCH_H
+#define __ASM_ARCH_OMAP_GPIO_SWITCH_H
+
+#include <linux/types.h>
+
+/* Cover:
+ *     high -> closed
+ *     low  -> open
+ * Connection:
+ *     high -> connected
+ *     low  -> disconnected
+ * Activity:
+ *     high -> active
+ *     low  -> inactive
+ *
+ */
+#define OMAP_GPIO_SWITCH_TYPE_COVER            0x0000
+#define OMAP_GPIO_SWITCH_TYPE_CONNECTION       0x0001
+#define OMAP_GPIO_SWITCH_TYPE_ACTIVITY         0x0002
+#define OMAP_GPIO_SWITCH_FLAG_INVERTED         0x0001
+#define OMAP_GPIO_SWITCH_FLAG_OUTPUT           0x0002
+
+struct omap_gpio_switch {
+       const char *name;
+       s16 gpio;
+       unsigned flags:4;
+       unsigned type:4;
+
+       /* Time in ms to debounce when transitioning from
+        * inactive state to active state. */
+       u16 debounce_rising;
+       /* Same for transition from active to inactive state. */
+       u16 debounce_falling;
+
+       /* notify board-specific code about state changes */
+       void (* notify)(void *data, int state);
+       void *notify_data;
+};
+
+/* Call at init time only */
+extern void omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
+                                       int count);
+
+#endif
index 590917efc94acdecca3be6fad273f31b24a9ef41..97b397dd7e87934dda0d57d68f37897fbbc7496e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2003-2005 Nokia Corporation
  *
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Written by Juha Yrjölä <juha.yrjola@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
index 7c03ef6c14c4f6e7d4391bb5275ef9be61045aec..995cc83482eb3d71e2624faac2b4acbb34695c7f 100644 (file)
@@ -87,5 +87,7 @@ extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
+extern int gpmc_cs_set_reserved(int cs, int reserved);
+extern int gpmc_cs_reserved(int cs);
 
 #endif
index 481048d65214815d85b22568b742995f3ea3269d..e225f4f39b34920c6c29ee182dcbe47e02798766 100644 (file)
 #define OMAP_LPG2_LCR                  (OMAP_LPG2_BASE + 0x00)
 #define OMAP_LPG2_PMR                  (OMAP_LPG2_BASE + 0x04)
 
+/*
+ * ----------------------------------------------------------------------------
+ * Pulse-Width Light
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP_PWL_BASE                  0xfffb5800
+#define OMAP_PWL_ENABLE                        (OMAP_PWL_BASE + 0x00)
+#define OMAP_PWL_CLK_ENABLE            (OMAP_PWL_BASE + 0x04)
+
 /*
  * ---------------------------------------------------------------------------
  * Processor specific defines
diff --git a/include/asm-arm/arch-omap/hwa742.h b/include/asm-arm/arch-omap/hwa742.h
new file mode 100644 (file)
index 0000000..577f492
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _HWA742_H
+#define _HWA742_H
+
+struct hwa742_platform_data {
+       void            (*power_up)(struct device *dev);
+       void            (*power_down)(struct device *dev);
+       unsigned long   (*get_clock_rate)(struct device *dev);
+
+       unsigned        te_connected:1;
+};
+
+#endif
index 78f68e6a4f0c59a24407cd7fbe8c905dea0b97ec..4aca7e3d7566c1b9619e9ce60ec598fde09e8a82 100644 (file)
 #define io_p2v(pa)     ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
 #define io_v2p(va)     ((va) - IO_OFFSET)      /* Works for L3 and L4 */
 
+/* DSP */
+#define DSP_MEM_24XX_PHYS      OMAP24XX_DSP_MEM_BASE   /* 0x58000000 */
+#define DSP_MEM_24XX_VIRT      0xe0000000
+#define DSP_MEM_24XX_SIZE      0x28000
+#define DSP_IPI_24XX_PHYS      OMAP24XX_DSP_IPI_BASE   /* 0x59000000 */
+#define DSP_IPI_24XX_VIRT      0xe1000000
+#define DSP_IPI_24XX_SIZE      SZ_4K
+#define DSP_MMU_24XX_PHYS      OMAP24XX_DSP_MMU_BASE   /* 0x5a000000 */
+#define DSP_MMU_24XX_VIRT      0xe2000000
+#define DSP_MMU_24XX_SIZE      SZ_4K
+
 #endif
 
 #ifndef __ASSEMBLER__
index c5bb05a69b81ec815c405d79b8b3bd553e29abc3..3ede58b51db28f36688e451d173b51b1fffc12ab 100644 (file)
@@ -37,8 +37,6 @@
 #define INT_DSP_MMU_ABORT      7
 #define INT_HOST               8
 #define INT_ABORT              9
-#define INT_DSP_MAILBOX1       10
-#define INT_DSP_MAILBOX2       11
 #define INT_BRIDGE_PRIV                13
 #define INT_GPIO_BANK1         14
 #define INT_UART3              15
@@ -63,6 +61,8 @@
 #define INT_1510_RES2          2
 #define INT_1510_SPI_TX                4
 #define INT_1510_SPI_RX                5
+#define INT_1510_DSP_MAILBOX1  10
+#define INT_1510_DSP_MAILBOX2  11
 #define INT_1510_RES12         12
 #define INT_1510_LB_MMU                17
 #define INT_1510_RES18         18
@@ -75,6 +75,8 @@
 #define INT_1610_IH2_FIQ       2
 #define INT_1610_McBSP2_TX     4
 #define INT_1610_McBSP2_RX     5
+#define INT_1610_DSP_MAILBOX1  10
+#define INT_1610_DSP_MAILBOX2  11
 #define INT_1610_LCD_LINE      12
 #define INT_1610_GPTIMER1      17
 #define INT_1610_GPTIMER2      18
 #define INT_RTC_TIMER          (25 + IH2_BASE)
 #define INT_RTC_ALARM          (26 + IH2_BASE)
 #define INT_MEM_STICK          (27 + IH2_BASE)
-#define INT_DSP_MMU            (28 + IH2_BASE)
 
 /*
  * OMAP-1510 specific IRQ numbers for interrupt handler 2
  */
+#define INT_1510_DSP_MMU       (28 + IH2_BASE)
 #define INT_1510_COM_SPI_RO    (31 + IH2_BASE)
 
 /*
 #define INT_1610_USB_OTG       (8 + IH2_BASE)
 #define INT_1610_SoSSI         (9 + IH2_BASE)
 #define INT_1610_SoSSI_MATCH   (19 + IH2_BASE)
+#define INT_1610_DSP_MMU       (28 + IH2_BASE)
 #define INT_1610_McBSP2RX_OF   (31 + IH2_BASE)
 #define INT_1610_STI           (32 + IH2_BASE)
 #define INT_1610_STI_WAKEUP    (33 + IH2_BASE)
 #define INT_24XX_SDMA_IRQ3     15
 #define INT_24XX_CAM_IRQ       24
 #define INT_24XX_DSS_IRQ       25
+#define INT_24XX_MAIL_U0_MPU   26
+#define INT_24XX_DSP_UMA       27
+#define INT_24XX_DSP_MMU       28
 #define INT_24XX_GPIO_BANK1    29
 #define INT_24XX_GPIO_BANK2    30
 #define INT_24XX_GPIO_BANK3    31
 #define INT_24XX_GPIO_BANK4    32
+#define INT_24XX_GPIO_BANK5    33
+#define INT_24XX_MAIL_U3_MPU   34
 #define INT_24XX_GPTIMER1      37
 #define INT_24XX_GPTIMER2      38
 #define INT_24XX_GPTIMER3      39
 #define INT_24XX_UART1_IRQ     72
 #define INT_24XX_UART2_IRQ     73
 #define INT_24XX_UART3_IRQ     74
+#define INT_24XX_USB_IRQ_GEN   75
+#define INT_24XX_USB_IRQ_NISO  76
+#define INT_24XX_USB_IRQ_ISO   77
+#define INT_24XX_USB_IRQ_HGEN  78
+#define INT_24XX_USB_IRQ_HSOF  79
+#define INT_24XX_USB_IRQ_OTG   80
 #define INT_24XX_MMC_IRQ       83
 
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h
deleted file mode 100644 (file)
index 004e67e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __LCD_LPH8923_H
-#define __LCD_LPH8923_H
-
-enum lcd_lph8923_test_num {
-       LCD_LPH8923_TEST_RGB_LINES,
-};
-
-enum lcd_lph8923_test_result {
-       LCD_LPH8923_TEST_SUCCESS,
-       LCD_LPH8923_TEST_INVALID,
-       LCD_LPH8923_TEST_FAILED,
-};
-
-#endif
diff --git a/include/asm-arm/arch-omap/lcd_mipid.h b/include/asm-arm/arch-omap/lcd_mipid.h
new file mode 100644 (file)
index 0000000..f8fbc48
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __LCD_MIPID_H
+#define __LCD_MIPID_H
+
+enum mipid_test_num {
+       MIPID_TEST_RGB_LINES,
+};
+
+enum mipid_test_result {
+       MIPID_TEST_SUCCESS,
+       MIPID_TEST_INVALID,
+       MIPID_TEST_FAILED,
+};
+
+#ifdef __KERNEL__
+
+struct mipid_platform_data {
+       int     nreset_gpio;
+       int     data_lines;
+       void    (*shutdown)(struct mipid_platform_data *pdata);
+};
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-omap/led.h b/include/asm-arm/arch-omap/led.h
new file mode 100644 (file)
index 0000000..f3acae2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  linux/include/asm-arm/arch-omap/led.h
+ *
+ *  Copyright (C) 2006 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_ARCH_LED_H
+#define ASMARM_ARCH_LED_H
+
+struct omap_led_config {
+       struct led_classdev     cdev;
+       s16                     gpio;
+};
+
+struct omap_led_platform_data {
+       s16                     nr_leds;
+       struct omap_led_config  *leds;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/mailbox.h b/include/asm-arm/arch-omap/mailbox.h
new file mode 100644 (file)
index 0000000..4bf0909
--- /dev/null
@@ -0,0 +1,73 @@
+/* mailbox.h */
+
+#ifndef MAILBOX_H
+#define MAILBOX_H
+
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/blkdev.h>
+
+typedef u32 mbox_msg_t;
+typedef void (mbox_receiver_t)(mbox_msg_t msg);
+struct omap_mbox;
+
+typedef int __bitwise omap_mbox_irq_t;
+#define IRQ_TX ((__force omap_mbox_irq_t) 1)
+#define IRQ_RX ((__force omap_mbox_irq_t) 2)
+
+typedef int __bitwise omap_mbox_type_t;
+#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
+#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
+
+struct omap_mbox_ops {
+       omap_mbox_type_t        type;
+       int             (*startup)(struct omap_mbox *mbox);
+       void            (*shutdown)(struct omap_mbox *mbox);
+       /* fifo */
+       mbox_msg_t      (*fifo_read)(struct omap_mbox *mbox);
+       void            (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
+       int             (*fifo_empty)(struct omap_mbox *mbox);
+       int             (*fifo_full)(struct omap_mbox *mbox);
+       /* irq */
+       void            (*enable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+       void            (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+       void            (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+       int             (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+};
+
+struct omap_mbox_queue {
+       spinlock_t              lock;
+       request_queue_t         *queue;
+       struct work_struct      work;
+       int     (*callback)(void *);
+       struct omap_mbox        *mbox;
+};
+
+struct omap_mbox {
+       char                    *name;
+       unsigned int            irq;
+
+       struct omap_mbox_queue  *txq, *rxq;
+
+       struct omap_mbox_ops    *ops;
+
+       mbox_msg_t              seq_snd, seq_rcv;
+
+       struct device           dev;
+
+       struct omap_mbox        *next;
+       void                    *priv;
+
+       void                    (*err_notify)(void);
+};
+
+int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg, void *);
+void omap_mbox_init_seq(struct omap_mbox *);
+
+struct omap_mbox *omap_mbox_get(const char *);
+void omap_mbox_put(struct omap_mbox *);
+
+int omap_mbox_register(struct omap_mbox *);
+int omap_mbox_unregister(struct omap_mbox *);
+
+#endif /* MAILBOX_H */
index 9e7f40a88e1b2be0d2d8cabe4fe98a89ddd101e3..1254e4945b6f85d9ede13b23a0df4b99be6e9118 100644 (file)
@@ -2,7 +2,6 @@
 #define _OMAP2_MCSPI_H
 
 struct omap2_mcspi_platform_config {
-       unsigned long   base;
        unsigned short  num_cs;
 };
 
index 48fabc493163fc44c004e8dcac03d86ff6c9ecae..14cba97c18ad061973876d1763aed27c7d8647ba 100644 (file)
 
 #endif /* CONFIG_ARCH_OMAP15XX */
 
+/* Override the ARM default */
+#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+
+#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)
+#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 2
+#endif
+
+#define CONSISTENT_DMA_SIZE \
+       (((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)
+
+#endif
+
 #endif
 
index 88cd4c87f0decd72f22a5ba1d5f012911ff59933..82d276a6bd95b6f8f867ec22fe6b463a5fb32045 100644 (file)
@@ -7,10 +7,19 @@
 #ifndef __ASM_ARCH_MENELAUS_H
 #define __ASM_ARCH_MENELAUS_H
 
-extern void menelaus_mmc_register(void (*callback)(unsigned long data, u8 card_mask),
-                                 unsigned long data);
-extern void menelaus_mmc_remove(void);
-extern void menelaus_mmc_opendrain(int enable);
+extern int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
+                                         void *data);
+extern void menelaus_unregister_mmc_callback(void);
+extern int menelaus_set_mmc_opendrain(int slot, int enable);
+extern int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_on);
+
+extern int menelaus_set_vmem(unsigned int mV);
+extern int menelaus_set_vio(unsigned int mV);
+extern int menelaus_set_vmmc(unsigned int mV);
+extern int menelaus_set_vaux(unsigned int mV);
+extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
+extern int menelaus_set_slot_sel(int enable);
+extern int menelaus_get_slot_pin_states(void);
 
 #if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_MENELAUS)
 #define omap_has_menelaus()    1
index f0c7f0fb4dc032e2a8c2303714b49504c3b7235b..f7f5cdfdccce4f40a4a6a2c9e54240f76864ae49 100644 (file)
 #define UART3_OSC_12M_SEL       (OMAP_UART3_BASE + 0x4C)
 #define UART3_MVR               (OMAP_UART3_BASE + 0x50)
 
-/*
- * ----------------------------------------------------------------------------
- * Pulse-Width Light
- * ----------------------------------------------------------------------------
- */
-#define OMAP16XX_PWL_BASE      (0xfffb5800)
-#define OMAP16XX_PWL_ENABLE    (OMAP16XX_PWL_BASE + 0x00)
-#define OMAP16XX_PWL_CLK_ENABLE        (OMAP16XX_PWL_BASE + 0x04)
-
 /*
  * ---------------------------------------------------------------------------
  * Watchdog timer
 #define WSPR_DISABLE_0         (0x0000aaaa)
 #define WSPR_DISABLE_1         (0x00005555)
 
+/* Mailbox */
+#define OMAP16XX_MAILBOX_BASE  (0xfffcf000)
+
 #endif /*  __ASM_ARCH_OMAP16XX_H */
 
index 6e59805fa6545b8c3edeef8be3e2378b8fb0cf19..708b2fac77f21e7b92544d77e06ca685ab97cef1 100644 (file)
 #define OMAP24XX_PRCM_BASE     (L4_24XX_BASE + 0x8000)
 #define OMAP24XX_SDRC_BASE     (L3_24XX_BASE + 0x9000)
 
+/* DSP SS */
+#define OMAP24XX_DSP_BASE      0x58000000
+#define OMAP24XX_DSP_MEM_BASE  (OMAP24XX_DSP_BASE + 0x0)
+#define OMAP24XX_DSP_IPI_BASE  (OMAP24XX_DSP_BASE + 0x1000000)
+#define OMAP24XX_DSP_MMU_BASE  (OMAP24XX_DSP_BASE + 0x2000000)
+
+/* Mailbox */
+#define OMAP24XX_MAILBOX_BASE  (L4_24XX_BASE + 0x94000)
+
 #endif /* __ASM_ARCH_OMAP24XX_H */
 
index fccdb3db025ff0dc79fd08dc4c5d7a0a27f0d1d3..46d7a4f6085495ec4d86274b61d8a90146cc92fc 100644 (file)
@@ -24,6 +24,9 @@
 #ifndef __OMAPFB_H
 #define __OMAPFB_H
 
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
 /* IOCTL commands. */
 
 #define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
 #define OMAPFB_SYNC_GFX                OMAP_IO(37)
 #define OMAPFB_VSYNC           OMAP_IO(38)
 #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old)
-#define OMAPFB_GET_CAPS                OMAP_IOR(42, unsigned long)
+#define OMAPFB_GET_CAPS                OMAP_IOR(42, struct omapfb_caps)
 #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
 #define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
 #define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
-#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(47, struct omapfb_update_window)
-#define OMAPFB_SETUP_PLANE     OMAP_IOW(48, struct omapfb_setup_plane)
-#define OMAPFB_ENABLE_PLANE    OMAP_IOW(49, struct omapfb_enable_plane)
+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
 #define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
+#define OMAPFB_GET_COLOR_KEY   OMAP_IOW(51, struct omapfb_color_key)
+#define OMAPFB_SETUP_PLANE     OMAP_IOW(52, struct omapfb_plane_info)
+#define OMAPFB_QUERY_PLANE     OMAP_IOW(53, struct omapfb_plane_info)
+#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(54, struct omapfb_update_window)
+#define OMAPFB_SETUP_MEM       OMAP_IOW(55, struct omapfb_mem_info)
+#define OMAPFB_QUERY_MEM       OMAP_IOW(56, struct omapfb_mem_info)
 
 #define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
 #define OMAPFB_CAPS_LCDC_MASK          0x00fff000
 #define OMAPFB_CAPS_PANEL_MASK         0xff000000
 
 #define OMAPFB_CAPS_MANUAL_UPDATE      0x00001000
+#define OMAPFB_CAPS_TEARSYNC           0x00002000
+#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
+#define OMAPFB_CAPS_PLANE_SCALE                0x00008000
+#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE        0x00010000
+#define OMAPFB_CAPS_WINDOW_SCALE       0x00020000
+#define OMAPFB_CAPS_WINDOW_OVERLAY     0x00040000
 #define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
 
 /* Values from DSP must map to lower 16-bits */
-#define OMAPFB_FORMAT_MASK         0x00ff
-#define OMAPFB_FORMAT_FLAG_DOUBLE  0x0100
+#define OMAPFB_FORMAT_MASK             0x00ff
+#define OMAPFB_FORMAT_FLAG_DOUBLE      0x0100
+#define OMAPFB_FORMAT_FLAG_TEARSYNC    0x0200
+#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
+#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY      0x0800
+#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY     0x1000
+
+#define OMAPFB_EVENT_READY     1
+#define OMAPFB_EVENT_DISABLED  2
+
+#define OMAPFB_MEMTYPE_SDRAM           0
+#define OMAPFB_MEMTYPE_SRAM            1
+#define OMAPFB_MEMTYPE_MAX             1
 
 enum omapfb_color_format {
        OMAPFB_COLOR_RGB565 = 0,
@@ -64,17 +87,23 @@ enum omapfb_color_format {
        OMAPFB_COLOR_CLUT_4BPP,
        OMAPFB_COLOR_CLUT_2BPP,
        OMAPFB_COLOR_CLUT_1BPP,
+       OMAPFB_COLOR_RGB444,
+       OMAPFB_COLOR_YUY422,
 };
 
 struct omapfb_update_window {
        __u32 x, y;
        __u32 width, height;
        __u32 format;
+       __u32 out_x, out_y;
+       __u32 out_width, out_height;
+       __u32 reserved[8];
 };
 
 struct omapfb_update_window_old {
        __u32 x, y;
        __u32 width, height;
+       __u32 format;
 };
 
 enum omapfb_plane {
@@ -88,18 +117,28 @@ enum omapfb_channel_out {
        OMAPFB_CHANNEL_OUT_DIGIT,
 };
 
-struct omapfb_setup_plane {
-       __u8  plane;
+struct omapfb_plane_info {
+       __u32 pos_x;
+       __u32 pos_y;
+       __u8  enabled;
        __u8  channel_out;
-       __u32 offset;
-       __u32 pos_x, pos_y;
-       __u32 width, height;
-       __u32 color_mode;
+       __u8  mirror;
+       __u8  reserved1;
+       __u32 out_width;
+       __u32 out_height;
+       __u32 reserved2[12];
 };
 
-struct omapfb_enable_plane {
-       __u8  plane;
-       __u8  enable;
+struct omapfb_mem_info {
+       __u32 size;
+       __u8  type;
+       __u8  reserved[3];
+};
+
+struct omapfb_caps {
+       __u32 ctrl;
+       __u32 plane_color;
+       __u32 wnd_color;
 };
 
 enum omapfb_color_key_type {
@@ -141,6 +180,9 @@ enum omapfb_update_mode {
 
 #define OMAP_LCDC_PANEL_TFT            0x0100
 
+#define OMAPFB_PLANE_XRES_MIN          8
+#define OMAPFB_PLANE_YRES_MIN          8
+
 #ifdef CONFIG_ARCH_OMAP1
 #define OMAPFB_PLANE_NUM               1
 #else
@@ -169,19 +211,19 @@ struct lcd_panel {
        int             pcd;            /* pixel clock divider.
                                           Obsolete use pixel_clock instead */
 
-       int             (*init)         (struct omapfb_device *fbdev);
-       void            (*cleanup)      (void);
-       int             (*enable)       (void);
-       void            (*disable)      (void);
-       unsigned long   (*get_caps)     (void);
-       int             (*set_bklight_level)(unsigned int level);
-       unsigned int    (*get_bklight_level)(void);
-       unsigned int    (*get_bklight_max)  (void);
-       int             (*run_test)     (int test_num);
+       int             (*init)         (struct lcd_panel *panel,
+                                        struct omapfb_device *fbdev);
+       void            (*cleanup)      (struct lcd_panel *panel);
+       int             (*enable)       (struct lcd_panel *panel);
+       void            (*disable)      (struct lcd_panel *panel);
+       unsigned long   (*get_caps)     (struct lcd_panel *panel);
+       int             (*set_bklight_level)(struct lcd_panel *panel,
+                                            unsigned int level);
+       unsigned int    (*get_bklight_level)(struct lcd_panel *panel);
+       unsigned int    (*get_bklight_max)  (struct lcd_panel *panel);
+       int             (*run_test)     (struct lcd_panel *panel, int test_num);
 };
 
-struct omapfb_device;
-
 struct extif_timings {
        int cs_on_time;
        int cs_off_time;
@@ -202,9 +244,10 @@ struct extif_timings {
 };
 
 struct lcd_ctrl_extif {
-       int  (*init)            (void);
+       int  (*init)            (struct omapfb_device *fbdev);
        void (*cleanup)         (void);
        void (*get_clk_info)    (u32 *clk_period, u32 *max_clk_div);
+       unsigned long (*get_max_tx_rate)(void);
        int  (*convert_timings) (struct extif_timings *timings);
        void (*set_timings)     (const struct extif_timings *timings);
        void (*set_bits_per_cycle)(int bpc);
@@ -213,31 +256,48 @@ struct lcd_ctrl_extif {
        void (*write_data)      (const void *buf, unsigned int len);
        void (*transfer_area)   (int width, int height,
                                 void (callback)(void * data), void *data);
+       int  (*setup_tearsync)  (unsigned pin_cnt,
+                                unsigned hs_pulse_time, unsigned vs_pulse_time,
+                                int hs_pol_inv, int vs_pol_inv, int div);
+       int  (*enable_tearsync) (int enable, unsigned line);
+
        unsigned long           max_transmit_size;
 };
 
 struct omapfb_notifier_block {
        struct notifier_block   nb;
        void                    *data;
+       int                     plane_idx;
 };
 
-typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *,
-                                          unsigned long event,
-                                          struct omapfb_device *fbdev);
+typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+                                         unsigned long event,
+                                         void *fbi);
+
+struct omapfb_mem_region {
+       dma_addr_t      paddr;
+       void            *vaddr;
+       unsigned long   size;
+       u8              type;           /* OMAPFB_PLANE_MEM_* */
+       unsigned        alloc:1;        /* allocated by the driver */
+       unsigned        map:1;          /* kernel mapped by the driver */
+};
+
+struct omapfb_mem_desc {
+       int                             region_cnt;
+       struct omapfb_mem_region        region[OMAPFB_PLANE_NUM];
+};
 
 struct lcd_ctrl {
        const char      *name;
        void            *data;
 
        int             (*init)           (struct omapfb_device *fbdev,
-                                          int ext_mode, int req_vram_size);
+                                          int ext_mode,
+                                          struct omapfb_mem_desc *req_md);
        void            (*cleanup)        (void);
        void            (*bind_client)    (struct omapfb_notifier_block *nb);
-       void            (*get_vram_layout)(unsigned long *size,
-                                          void **virt_base,
-                                          dma_addr_t *phys_base);
-       int             (*mmap)           (struct vm_area_struct *vma);
-       unsigned long   (*get_caps)       (void);
+       void            (*get_caps)       (int plane, struct omapfb_caps *caps);
        int             (*set_update_mode)(enum omapfb_update_mode mode);
        enum omapfb_update_mode (*get_update_mode)(void);
        int             (*setup_plane)    (int plane, int channel_out,
@@ -245,8 +305,16 @@ struct lcd_ctrl {
                                           int screen_width,
                                           int pos_x, int pos_y, int width,
                                           int height, int color_mode);
+       int             (*setup_mem)      (int plane, size_t size,
+                                          int mem_type, unsigned long *paddr);
+       int             (*mmap)           (struct fb_info *info,
+                                          struct vm_area_struct *vma);
+       int             (*set_scale)      (int plane,
+                                          int orig_width, int orig_height,
+                                          int out_width, int out_height);
        int             (*enable_plane)   (int plane, int enable);
-       int             (*update_window)  (struct omapfb_update_window *win,
+       int             (*update_window)  (struct fb_info *fbi,
+                                          struct omapfb_update_window *win,
                                           void (*callback)(void *),
                                           void *callback_data);
        void            (*sync)           (void);
@@ -257,7 +325,7 @@ struct lcd_ctrl {
                                           u16 blue, u16 transp,
                                           int update_hw_mem);
        int             (*set_color_key)  (struct omapfb_color_key *ck);
-
+       int             (*get_color_key)  (struct omapfb_color_key *ck);
 };
 
 enum omapfb_state {
@@ -266,19 +334,20 @@ enum omapfb_state {
        OMAPFB_ACTIVE   = 100
 };
 
+struct omapfb_plane_struct {
+       int                             idx;
+       struct omapfb_plane_info        info;
+       enum omapfb_color_format        color_mode;
+       struct omapfb_device            *fbdev;
+};
+
 struct omapfb_device {
        int                     state;
        int                     ext_lcdc;               /* Using external
                                                            LCD controller */
        struct mutex            rqueue_mutex;
 
-       void                    *vram_virt_base;
-       dma_addr_t              vram_phys_base;
-       unsigned long           vram_size;
-
-       int                     color_mode;
        int                     palette_size;
-       int                     mirror;
        u32                     pseudo_palette[17];
 
        struct lcd_panel        *panel;                 /* LCD panel */
@@ -286,19 +355,19 @@ struct omapfb_device {
        struct lcd_ctrl         *int_ctrl;              /* internal LCD ctrl */
        struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
                                                           interface */
-       struct fb_info          *fb_info;
-
        struct device           *dev;
+       struct fb_var_screeninfo        new_var;        /* for mode changes */
+
+       struct omapfb_mem_desc          mem_desc;
+       struct fb_info                  *fb_info[OMAPFB_PLANE_NUM];
 };
 
 struct omapfb_platform_data {
-       struct omap_lcd_config   lcd;
-       struct omap_fbmem_config fbmem;
+       struct omap_lcd_config          lcd;
+       struct omapfb_mem_desc          mem_desc;
+       void                            *ctrl_platform_data;
 };
 
-#define OMAPFB_EVENT_READY     1
-#define OMAPFB_EVENT_DISABLED  2
-
 #ifdef CONFIG_ARCH_OMAP1
 extern struct lcd_ctrl omap1_lcd_ctrl;
 #else
@@ -310,15 +379,16 @@ extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
 extern void omapfb_notify_clients(struct omapfb_device *fbdev,
                                  unsigned long event);
 extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
-                                   omapfb_notifier_callback_t callback,
-                                   void *callback_data);
+                                  omapfb_notifier_callback_t callback,
+                                  void *callback_data);
 extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
-extern int  omapfb_update_window_async(struct omapfb_update_window *win,
-                                       void (*callback)(void *),
-                                       void *callback_data);
+extern int  omapfb_update_window_async(struct fb_info *fbi,
+                                      struct omapfb_update_window *win,
+                                      void (*callback)(void *),
+                                      void *callback_data);
 
-/* in arch/arm/plat-omap/devices.c */
-extern void omapfb_reserve_mem(void);
+/* in arch/arm/plat-omap/fb.c */
+extern void omapfb_set_ctrl_platform_data(void *pdata);
 
 #endif /* __KERNEL__ */
 
index 6fc0dd57b7c383ae69c6aea14679e4f6c5bc1115..bb9bb3fd532f7c88e715db8fe4ddf48f4507844e 100644 (file)
@@ -20,9 +20,6 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
                                      u32 mem_type);
 extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
 
-extern unsigned long omap_fb_sram_start;
-extern unsigned long omap_fb_sram_size;
-
 /* Do not use these */
 extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
 extern unsigned long sram_reprogram_clock_sz;
index 054fb9a8e0c684052ec4046be5c887c61538582b..99ae9eabaf71bb3740aabe11cc6b2667065d91f5 100644 (file)
@@ -7,9 +7,27 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define OTG_BASE                       0xfffb0400
-#define UDC_BASE                       0xfffb4000
-#define OMAP_OHCI_BASE                 0xfffba000
+#define OMAP1_OTG_BASE                 0xfffb0400
+#define OMAP1_UDC_BASE                 0xfffb4000
+#define OMAP1_OHCI_BASE                        0xfffba000
+
+#define OMAP2_OHCI_BASE                        0x4805e000
+#define OMAP2_UDC_BASE                 0x4805e200
+#define OMAP2_OTG_BASE                 0x4805e300
+
+#ifdef CONFIG_ARCH_OMAP1
+
+#define OTG_BASE                       OMAP1_OTG_BASE
+#define UDC_BASE                       OMAP1_UDC_BASE
+#define OMAP_OHCI_BASE                 OMAP1_OHCI_BASE
+
+#else
+
+#define OTG_BASE                       OMAP2_OTG_BASE
+#define UDC_BASE                       OMAP2_UDC_BASE
+#define OMAP_OHCI_BASE                 OMAP2_OHCI_BASE
+
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -28,6 +46,7 @@
 #      define   HST_IDLE_EN            (1 << 14)
 #      define   DEV_IDLE_EN            (1 << 13)
 #      define   OTG_RESET_DONE         (1 << 2)
+#      define   OTG_SOFT_RESET         (1 << 1)
 #define OTG_SYSCON_2_REG               OTG_REG32(0x08)
 #      define   OTG_EN                 (1 << 31)
 #      define   USBX_SYNCHRO           (1 << 30)
 
 /*-------------------------------------------------------------------------*/
 
+/* OMAP1 */
 #define        USB_TRANSCEIVER_CTRL_REG        __REG32(0xfffe1000 + 0x0064)
 #      define  CONF_USB2_UNI_R         (1 << 8)
 #      define  CONF_USB1_UNI_R         (1 << 7)
 #      define  CONF_USB_PWRDN_DM_R     (1 << 2)
 #      define  CONF_USB_PWRDN_DP_R     (1 << 1)
 
-
-
+/* OMAP2 */
+#define        CONTROL_DEVCONF_REG             __REG32(L4_24XX_BASE + 0x0274)
+#      define  USB_UNIDIR                      0x0
+#      define  USB_UNIDIR_TLL                  0x1
+#      define  USB_BIDIR                       0x2
+#      define  USB_BIDIR_TLL                   0x3
+#      define  USBT0WRMODEI(x)         ((x) << 22)
+#      define  USBT1WRMODEI(x)         ((x) << 20)
+#      define  USBT2WRMODEI(x)         ((x) << 18)
+#      define  USBT2TLL5PI             (1 << 17)
+#      define  USB0PUENACTLOI          (1 << 16)
+#      define  USBSTANDBYCTRL          (1 << 15)
 
 #endif /* __ASM_ARCH_OMAP_USB_H */
index 6c319ea2afac3044d446003c0a624c6a2b26782c..94ff96505b6aadac08a88e0d6d171e4d242db7f1 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm/arch-s3c2410/regs-power.h
+/* linux/include/asm-arm/arch-s3c2410/regs-power.h
  *
  * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk>
  *                   http://armlinux.simtec.co.uk/
index ff0536d2de42644c6ab6e371ba676bcbc4748679..cd9e26568f858254fd15f3895d083a7782567fee 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/arch-s3c2410/regs-clock.h
+/* linux/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
  *
  * Copyright (c) 2007 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
index f4fff448c7bdc808b4d915ba466b39f1c2421d44..a9c5d491bdb6b691c40261c724aec6a72149d51a 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm/arch-s3c2410/regs-watchdog.h
+/* linux/include/asm-arm/arch-s3c2410/regs-watchdog.h
  *
  * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  *                   http://www.simtec.co.uk/products/SWLINUX/
index e59ec339d614158411209029e06b81b1079eb048..b8aa6cb69b58ec5c8a7269ea9e2a54398db00d9d 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm/arch-s3c2410/udc.h
+/* linux/include/asm-arm/arch-s3c2410/udc.h
  *
  * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
index f266c2795124901fc05b6ba3cff0bb607e393655..3b59f94b5a3d3f345bf5bfeff53440063ae3f426 100644 (file)
@@ -12,6 +12,7 @@
 #define __ASM_ARM_ATOMIC_H
 
 #include <linux/compiler.h>
+#include <asm/system.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
index afad32c76e6c964df908c6493441139ccb328977..d1294a46c70c62237c9d0e266d90c645f1182bf0 100644 (file)
 //# endif
 #endif
 
+#if defined(CONFIG_CPU_V7)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v7
+//# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintainence model
 #endif
@@ -418,11 +426,19 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
  */
 #define flush_icache_page(vma,page)    do { } while (0)
 
-#define __cacheid_present(val)         (val != read_cpuid(CPUID_ID))
-#define __cacheid_vivt(val)            ((val & (15 << 25)) != (14 << 25))
-#define __cacheid_vipt(val)            ((val & (15 << 25)) == (14 << 25))
-#define __cacheid_vipt_nonaliasing(val)        ((val & (15 << 25 | 1 << 23)) == (14 << 25))
-#define __cacheid_vipt_aliasing(val)   ((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23))
+#define __cacheid_present(val)                 (val != read_cpuid(CPUID_ID))
+#define __cacheid_type_v7(val)                 ((val & (7 << 29)) == (4 << 29))
+
+#define __cacheid_vivt_prev7(val)              ((val & (15 << 25)) != (14 << 25))
+#define __cacheid_vipt_prev7(val)              ((val & (15 << 25)) == (14 << 25))
+#define __cacheid_vipt_nonaliasing_prev7(val)  ((val & (15 << 25 | 1 << 23)) == (14 << 25))
+#define __cacheid_vipt_aliasing_prev7(val)     ((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23))
+
+#define __cacheid_vivt(val)                    (__cacheid_type_v7(val) ? 0 : __cacheid_vivt_prev7(val))
+#define __cacheid_vipt(val)                    (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_prev7(val))
+#define __cacheid_vipt_nonaliasing(val)                (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_nonaliasing_prev7(val))
+#define __cacheid_vipt_aliasing(val)           (__cacheid_type_v7(val) ? 0 : __cacheid_vipt_aliasing_prev7(val))
+#define __cacheid_vivt_asid_tagged_instr(val)  (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0)
 
 #if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
 
@@ -430,6 +446,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 #define cache_is_vipt()                        0
 #define cache_is_vipt_nonaliasing()    0
 #define cache_is_vipt_aliasing()       0
+#define icache_is_vivt_asid_tagged()   0
 
 #elif defined(CONFIG_CPU_CACHE_VIPT)
 
@@ -447,6 +464,12 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
                __cacheid_vipt_aliasing(__val);                         \
        })
 
+#define icache_is_vivt_asid_tagged()                                   \
+       ({                                                              \
+               unsigned int __val = read_cpuid(CPUID_CACHETYPE);       \
+               __cacheid_vivt_asid_tagged_instr(__val);                \
+       })
+
 #else
 
 #define cache_is_vivt()                                                        \
@@ -475,6 +498,13 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
                 __cacheid_vipt_aliasing(__val);                        \
        })
 
+#define icache_is_vivt_asid_tagged()                                   \
+       ({                                                              \
+               unsigned int __val = read_cpuid(CPUID_CACHETYPE);       \
+               __cacheid_present(__val) &&                             \
+                __cacheid_vivt_asid_tagged_instr(__val);               \
+       })
+
 #endif
 
 #endif
index abfb75b654c7df7f8795b1f0db4ea4aa173fd0e8..c8b5d0db0cf08d8580efdffed8227dbf83f0624f 100644 (file)
@@ -445,7 +445,7 @@ extern void dmabounce_unregister_dev(struct device *);
  *
  * The dmabounce routines call this function whenever a dma-mapping
  * is requested to determine whether a given buffer needs to be bounced
- * or not. The function must return 0 if the the buffer is OK for
+ * or not. The function must return 0 if the buffer is OK for
  * DMA access and 1 if the buffer needs to be bounced.
  *
  */
index 0cc5d3b10ce2fb888a7735eb17e1e65a620514aa..22274ce8137509175dcd2664e2632edac0a167e7 100644 (file)
@@ -38,6 +38,7 @@
  *       v5tej_early   - ARMv5 with Thumb and Java early abort handler
  *       xscale        - ARMv5 with Thumb with Xscale extensions
  *       v6_early      - ARMv6 generic early abort handler
+ *       v7_early      - ARMv7 generic early abort handler
  */
 #undef CPU_ABORT_HANDLER
 #undef MULTI_ABORT
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_EV7
+# ifdef CPU_ABORT_HANDLER
+#  define MULTI_ABORT 1
+# else
+#  define CPU_ABORT_HANDLER v7_early_abort
+# endif
+#endif
+
 #ifndef CPU_ABORT_HANDLER
 #error Unknown data abort handler type
 #endif
diff --git a/include/asm-arm/kdebug.h b/include/asm-arm/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 8c1c6162a80c1595c7b314bd752390dc7b824bde..b5b030ef633d67d0fc254fcefea1d110687ab775 100644 (file)
@@ -16,8 +16,6 @@
 
 #ifndef __ASSEMBLY__
 
-#define MAX_NOTE_BYTES 1024
-
 struct kimage;
 /* Provide a dummy definition to avoid build failures. */
 static inline void crash_setup_regs(struct pt_regs *newregs,
index f8755c818b5462549e39ed8bd0102ae3b02ed0a0..4981ad419198d1cf91d8f38cc0d54450f18c0c06 100644 (file)
@@ -36,8 +36,9 @@ void __check_kvm_seq(struct mm_struct *mm);
  * The context ID is used by debuggers and trace logic, and
  * should be unique within all running processes.
  */
-#define ASID_BITS      8
-#define ASID_MASK      ((~0) << ASID_BITS)
+#define ASID_BITS              8
+#define ASID_MASK              ((~0) << ASID_BITS)
+#define ASID_FIRST_VERSION     (1 << ASID_BITS)
 
 extern unsigned int cpu_last_asid;
 
@@ -96,8 +97,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #ifdef CONFIG_MMU
        unsigned int cpu = smp_processor_id();
 
-       if (prev != next) {
-               cpu_set(cpu, next->cpu_vm_mask);
+       if (!cpu_test_and_set(cpu, next->cpu_vm_mask) || prev != next) {
                check_context(next);
                cpu_switch_mm(next->pgd, next);
                if (cache_is_vivt())
index 7b1c9acdf79a876da4c81c1f26bd8c41b9784495..0c8be19fd66bff98f1ec13ef7484bfde6722c4a0 100644 (file)
@@ -83,10 +83,6 @@ extern int is_in_rom(unsigned long);
 #define io_remap_page_range    remap_page_range
 #define io_remap_pfn_range     remap_pfn_range
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 
 /*
  * All 32bit addresses are effectively valid for vmalloc...
index 7b2bafce21a254924cdedcd17dfaf4e0e721e7f9..21dec9f258d822d081a0e7da9251de908f5e0462 100644 (file)
@@ -395,10 +395,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
                remap_pfn_range(vma, from, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #define pgtable_cache_init() do { } while (0)
 
 #endif /* !__ASSEMBLY__ */
index ea7e54c319be535ed1777640f0e1740b36c748a5..5599d4e5e7080afdb23ac2e8eb1cac308158e9cd 100644 (file)
 #   define CPU_NAME cpu_v6
 #  endif
 # endif
+# ifdef CONFIG_CPU_V7
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_v7
+#  endif
+# endif
 #endif
 
 #ifndef __ASSEMBLY__
index 63b3080bdac4c331b88ae0a938f13cba8ee322c1..6f8e6a69dc5f4334391dc03ff6ef53b3d1bd032a 100644 (file)
@@ -14,6 +14,7 @@
 #define CPU_ARCH_ARMv5TE       6
 #define CPU_ARCH_ARMv5TEJ      7
 #define CPU_ARCH_ARMv6         8
+#define CPU_ARCH_ARMv7         9
 
 /*
  * CR1 bits (CP#15 CR1)
@@ -93,7 +94,7 @@ void die(const char *msg, struct pt_regs *regs, int err)
                __attribute__((noreturn));
 
 struct siginfo;
-void notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
+void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
                unsigned long err, unsigned long trap);
 
 void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
@@ -103,8 +104,6 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
 #define xchg(ptr,x) \
        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-#define tas(ptr) (xchg((ptr),1))
-
 extern asmlinkage void __backtrace(void);
 extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
 
@@ -157,7 +156,11 @@ extern unsigned int user_debug;
 #define vectors_high() (0)
 #endif
 
-#if defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ >= 6
+#if __LINUX_ARM_ARCH__ >= 7
+#define isb() __asm__ __volatile__ ("isb" : : : "memory")
+#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
+#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
+#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
 #define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
                                    : : "r" (0) : "memory")
 #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
index 97e944fe1cff4c9bf4d9c0eb7603fca6e43bf916..d6dd42374cf3aaef8f2586efb13da4d948451af2 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-
 #ifdef CONFIG_SMP
 #error SMP is NOT supported
 #endif
index 2aa033bd0678b07ba8936aedb375a5a21b757df1..a5a7a4d5e09c29ad8723155795ae41d419f2489e 100644 (file)
@@ -321,7 +321,7 @@ DECLARE_IO(int,l,"")
 
 #define mmiowb()
 
-/* the following macro is depreciated */
+/* the following macro is deprecated */
 #define ioaddr(port)                    __ioaddr((port))
 
 /*
diff --git a/include/asm-arm26/kdebug.h b/include/asm-arm26/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index a65f10b80dfb8dc0cae7c5260a12204beac04c65..7c1e5be39060dd291f0863f6b631b2dc5c6554e2 100644 (file)
@@ -60,7 +60,7 @@ static inline void *phys_to_virt(unsigned long x)
 /*
  * Virtual <-> DMA view memory address translations
  * Again, these are *only* valid on the kernel direct mapped RAM
- * memory.  Use of these is *depreciated*.
+ * memory.  Use of these is *deprecated*.
  */
 #define virt_to_bus(x)         ((unsigned long)(x))
 #define bus_to_virt(x)         ((void *)((unsigned long)(x)))
@@ -93,7 +93,7 @@ static inline void *phys_to_virt(unsigned long x)
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
 
 /*
- * We should really eliminate virt_to_bus() here - it's depreciated.
+ * We should really eliminate virt_to_bus() here - it's deprecated.
  */
 #define page_to_bus(page)      (page_address(page))
 
index 63a8881fae13723a30e05d5f451707e5f1ad745f..2b20e9f08857483a100b81fd25751c732682d247 100644 (file)
@@ -297,10 +297,6 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
                remap_pfn_range(vma, from, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASMARM_PGTABLE_H */
index 1a867b4e8d531e4f86b81feb4680e6ab15de7636..10fd07c7666264b5f39c0387f66bf4d3200d94b7 100644 (file)
@@ -70,7 +70,7 @@ struct tag_ramdisk {
 /* describes where the compressed ramdisk image lives */
 /*
  * this one accidentally used virtual addresses - as such,
- * its depreciated.
+ * it's deprecated.
  */
 #define ATAG_INITRD    0x54410005
 
index 00ae32aa1dbaf2f1ad0ac3e86d66b55d09581b1b..4703593b3bb52212c5118a4b113380960784c861 100644 (file)
@@ -52,8 +52,6 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
 #define xchg(ptr,x) \
        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-#define tas(ptr) (xchg((ptr),1))
-
 extern asmlinkage void __backtrace(void);
 
 #define set_cr(x)                                      \
diff --git a/include/asm-avr32/arch-at32ap/cpu.h b/include/asm-avr32/arch-at32ap/cpu.h
new file mode 100644 (file)
index 0000000..2bdc5bd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * AVR32 and (fake) AT91 CPU identification
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_CPU_H
+#define __ASM_ARCH_CPU_H
+
+/*
+ * Only AT32AP7000 is defined for now. We can identify the specific
+ * chip at runtime, but I'm not sure if it's really worth it.
+ */
+#ifdef CONFIG_CPU_AT32AP7000
+# define cpu_is_at32ap7000()   (1)
+#else
+# define cpu_is_at32ap7000()   (0)
+#endif
+
+/*
+ * Since this is AVR32, we will never run on any AT91 CPU. But these
+ * definitions may reduce clutter in common drivers.
+ */
+#define cpu_is_at91rm9200()    (0)
+#define cpu_is_at91sam9xe()    (0)
+#define cpu_is_at91sam9260()   (0)
+#define cpu_is_at91sam9261()   (0)
+#define cpu_is_at91sam9263()   (0)
+
+#endif /* __ASM_ARCH_CPU_H */
index f583b643ffb2b61235b387fa37159cb19f6ac88e..de419278fc39dacb5cc7c450d3c58ba8da9e96d2 100644 (file)
@@ -3,19 +3,6 @@
 
 #include <linux/notifier.h>
 
-struct pt_regs;
-
-struct die_args {
-       struct pt_regs *regs;
-       int trapnr;
-};
-
-int register_die_notifier(struct notifier_block *nb);
-int unregister_die_notifier(struct notifier_block *nb);
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
-extern struct atomic_notifier_head avr32_die_chain;
-
 /* Grossly misnamed. */
 enum die_val {
        DIE_FAULT,
@@ -24,15 +11,7 @@ enum die_val {
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, struct pt_regs *regs,
-                            int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .trapnr = trap,
-       };
-
-       return atomic_notifier_call_chain(&avr32_die_chain, val, &args);
-}
+int register_page_fault_notifier(struct notifier_block *nb);
+int unregister_page_fault_notifier(struct notifier_block *nb);
 
 #endif /* __ASM_AVR32_KDEBUG_H */
index 6b8ca9db2bd537c29cf9ed739001058ba8512252..f6cc2b0f75c3118ce0b7adb3e4f989da042c5d83 100644 (file)
@@ -394,10 +394,6 @@ typedef pte_t *pte_addr_t;
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)        \
        remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /* No page table caches to initialize (?) */
 #define pgtable_cache_init()   do { } while(0)
 
index 1ff1a217015d85d2e6eaedf8bcc5af61acd0a41f..b0828d43e110c93f27b65adf593fc0c40e58a676 100644 (file)
@@ -110,7 +110,7 @@ struct tagtable {
        int     (*parse)(struct tag *);
 };
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist")))
+#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
 #define __tagtable(tag, fn)                                            \
        static struct tagtable __tagtable_##fn __tag = { tag, fn }
 
index 8f51204718193751bc131cc4f9ce772c2405a36b..2418cce624cc18775a459436aaaef18e140f9398 100644 (file)
 #define __NR_shmdt             276
 #define __NR_shmctl            277
 
+#define __NR_utimensat         278
+
 #ifdef __KERNEL__
-#define NR_syscalls            278
+#define NR_syscalls            279
 
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
index 997465c93e82fbce217ec50107d54543881481d5..0336ff132c16db742f756643cc1a01ff221e1aea 100644 (file)
@@ -58,10 +58,10 @@ do {                                                                        \
        (_regs)->pc = (_pc);                                            \
        if (current->mm)                                                \
                (_regs)->p5 = current->mm->start_data;                  \
-       current->thread_info->l1_task_info.stack_start                  \
+       task_thread_info(current)->l1_task_info.stack_start             \
                = (void *)current->mm->context.stack_start;             \
-       current->thread_info->l1_task_info.lowest_sp = (void *)(_usp);          \
-       memcpy(L1_SCRATCH_TASK_INFO, &current->thread_info->l1_task_info,       \
+       task_thread_info(current)->l1_task_info.lowest_sp = (void *)(_usp); \
+       memcpy(L1_SCRATCH_TASK_INFO, &task_thread_info(current)->l1_task_info, \
                sizeof(*L1_SCRATCH_TASK_INFO));                         \
        wrusp(_usp);                                                    \
 } while(0)
index 758bac7c1e7453db57bc077bba42ff96b08dec2d..5e5f1a0566c0fe6b1c90d9d0d0b039ed23c289e8 100644 (file)
@@ -138,7 +138,6 @@ extern unsigned long irq_flags;
 #endif
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) ((void)xchg((ptr),1))
 
 struct __xchg_dummy {
        unsigned long a[100];
@@ -240,9 +239,9 @@ asmlinkage struct task_struct *resume(struct task_struct *prev, struct task_stru
 
 #define switch_to(prev,next,last) \
 do {    \
-       memcpy (&prev->thread_info->l1_task_info, L1_SCRATCH_TASK_INFO, \
+       memcpy (&task_thread_info(prev)->l1_task_info, L1_SCRATCH_TASK_INFO, \
                sizeof *L1_SCRATCH_TASK_INFO); \
-       memcpy (L1_SCRATCH_TASK_INFO, &next->thread_info->l1_task_info, \
+       memcpy (L1_SCRATCH_TASK_INFO, &task_thread_info(next)->l1_task_info, \
                sizeof *L1_SCRATCH_TASK_INFO); \
        (last) = resume (prev, next);   \
 } while (0)
diff --git a/include/asm-cris/kdebug.h b/include/asm-cris/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 066386ac238e9719fde46e714da1cce668e2f77b..d425d8d0ad7758c73d40000a9a792f740ff78a5d 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/types.h>
 #include <asm/spr-regs.h>
+#include <asm/system.h>
 
 #ifdef CONFIG_SMP
 #error not SMP safe
@@ -258,85 +259,23 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
 
 #define tas(ptr) (xchg((ptr), 1))
 
-/*****************************************************************************/
-/*
- * compare and conditionally exchange value with memory
- * - if (*ptr == test) then orig = *ptr; *ptr = test;
- * - if (*ptr != test) then orig = *ptr;
- */
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4:                                                                 \
-               asm volatile(                                                   \
-                       "0:                                             \n"     \
-                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
-                       "       ckeq            icc3,cc7                \n"     \
-                       "       ld.p            %M0,%1                  \n"     \
-                       "       orcr            cc7,cc7,cc3             \n"     \
-                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
-                       "       bne             icc0,#0,1f              \n"     \
-                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
-                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
-                       "       beq             icc3,#0,0b              \n"     \
-                       "1:                                             \n"     \
-                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
-                       : "r"(__xg_new), "NPr"(__xg_test)                       \
-                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
-                       );                                                      \
-               break;                                                          \
-                                                                               \
-       default:                                                                \
-               __xg_orig = 0;                                                  \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#else
-
-extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig;                                           \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
-       default:                                                                \
-               __xg_orig = 0;                                                  \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#endif
-
 #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
diff --git a/include/asm-frv/kdebug.h b/include/asm-frv/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 8a05aa168616f6d548bd78e03d7e474eee3cf1ad..2687c77151204da45f07c300c3661b03880a94cd 100644 (file)
@@ -509,10 +509,6 @@ static inline int pte_file(pte_t pte)
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
index 907c5c3643cced5eb8e3ecef3b33dd8a6607a213..09586528e00794f391d7cd680d0950db4a9307ae 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 
-#define SEMAPHORE_DEBUG                0
-
 /*
  * the semaphore definition
  * - if counter is >0 then there are tokens available on the semaphore for down to collect
@@ -32,12 +30,12 @@ struct semaphore {
        unsigned                counter;
        spinlock_t              wait_lock;
        struct list_head        wait_list;
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
        unsigned                __magic;
 #endif
 };
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
 # define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
 #else
 # define __SEM_DEBUG_INIT(name)
@@ -76,7 +74,7 @@ static inline void down(struct semaphore *sem)
 {
        unsigned long flags;
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
        CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -95,7 +93,7 @@ static inline int down_interruptible(struct semaphore *sem)
        unsigned long flags;
        int ret = 0;
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
        CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -119,7 +117,7 @@ static inline int down_trylock(struct semaphore *sem)
        unsigned long flags;
        int success = 0;
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
        CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -136,7 +134,7 @@ static inline void up(struct semaphore *sem)
 {
        unsigned long flags;
 
-#if SEMAPHORE_DEBUG
+#ifdef CONFIG_DEBUG_SEMAPHORE
        CHECK_MAGIC(sem->__magic);
 #endif
 
index 1166899317d78a8ca248d798216d3391e0484b8e..be303b3eef4096e06be42497583fec69ea097e94 100644 (file)
@@ -13,7 +13,6 @@
 #define _ASM_SYSTEM_H
 
 #include <linux/linkage.h>
-#include <asm/atomic.h>
 
 struct thread_struct;
 
@@ -197,4 +196,73 @@ extern void free_initmem(void);
 
 #define arch_align_stack(x) (x)
 
+/*****************************************************************************/
+/*
+ * compare and conditionally exchange value with memory
+ * - if (*ptr == test) then orig = *ptr; *ptr = test;
+ * - if (*ptr != test) then orig = *ptr;
+ */
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4:                                                                 \
+               asm volatile(                                                   \
+                       "0:                                             \n"     \
+                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
+                       "       ckeq            icc3,cc7                \n"     \
+                       "       ld.p            %M0,%1                  \n"     \
+                       "       orcr            cc7,cc7,cc3             \n"     \
+                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
+                       "       bne             icc0,#0,1f              \n"     \
+                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
+                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
+                       "       beq             icc3,#0,0b              \n"     \
+                       "1:                                             \n"     \
+                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
+                       : "r"(__xg_new), "NPr"(__xg_test)                       \
+                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
+                       );                                                      \
+               break;                                                          \
+                                                                               \
+       default:                                                                \
+               __xg_orig = 0;                                                  \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#else
+
+extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig;                                           \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
+       default:                                                                \
+               __xg_orig = 0;                                                  \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#endif
+
+
 #endif /* _ASM_SYSTEM_H */
index f94fe5cb9b3aebd4180c0be159f33e53b1ee46af..cd458eb6d75ed113469d257d62a901ffb7f18701 100644 (file)
@@ -3,7 +3,11 @@
 
 #include <asm/tlbflush.h>
 
+#ifdef CONFIG_MMU
+extern void check_pgt_cache(void);
+#else
 #define check_pgt_cache() do {} while(0)
+#endif
 
 /*
  * we don't need any special per-pte or per-vma handling...
index 584c0417ae4de9ed74a0e167e6afd7cc30fc9738..d0ea6789b31e530cca93f92716aa474ff3a7bc45 100644 (file)
 #define __NR_rt_sigtimedwait   177
 #define __NR_rt_sigqueueinfo   178
 #define __NR_rt_sigsuspend     179
-#define __NR_pread             180
-#define __NR_pwrite            181
+#define __NR_pread64           180
+#define __NR_pwrite64          181
 #define __NR_chown             182
 #define __NR_getcwd            183
 #define __NR_capget            184
 #define __NR_faccessat         307
 #define __NR_pselect6          308
 #define __NR_ppoll             309
+#define __NR_unshare           310
+#define __NR_set_robust_list   311
+#define __NR_get_robust_list   312
+#define __NR_splice            313
+#define __NR_sync_file_range   314
+#define __NR_tee               315
+#define __NR_vmsplice          316
+#define __NR_move_pages                317
+#define __NR_getcpu            318
+#define __NR_epoll_pwait       319
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 310
+#define NR_syscalls 320
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
index b7e4a0467cb1283ed82b9cd74bf2238178376a87..85fd0aa27a8cd3f48a8ee9a9b47646316ddbed15 100644 (file)
@@ -66,6 +66,76 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
        atomic64_sub(i, v);
 }
 
+static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return atomic64_sub_and_test(i, v);
+}
+
+static inline int atomic_long_dec_and_test(atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return atomic64_dec_and_test(v);
+}
+
+static inline int atomic_long_inc_and_test(atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return atomic64_inc_and_test(v);
+}
+
+static inline int atomic_long_add_negative(long i, atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return atomic64_add_negative(i, v);
+}
+
+static inline long atomic_long_add_return(long i, atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return (long)atomic64_add_return(i, v);
+}
+
+static inline long atomic_long_sub_return(long i, atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return (long)atomic64_sub_return(i, v);
+}
+
+static inline long atomic_long_inc_return(atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return (long)atomic64_inc_return(v);
+}
+
+static inline long atomic_long_dec_return(atomic_long_t *l)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return (long)atomic64_dec_return(v);
+}
+
+static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
+{
+       atomic64_t *v = (atomic64_t *)l;
+
+       return (long)atomic64_add_unless(v, a, u);
+}
+
+#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
+
+#define atomic_long_cmpxchg(l, old, new) \
+       (atomic_cmpxchg((atomic64_t *)(l), (old), (new)))
+#define atomic_long_xchg(v, new) \
+       (atomic_xchg((atomic64_t *)(l), (new)))
+
 #else  /*  BITS_PER_LONG == 64  */
 
 typedef atomic_t atomic_long_t;
@@ -113,6 +183,76 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
        atomic_sub(i, v);
 }
 
+static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return atomic_sub_and_test(i, v);
+}
+
+static inline int atomic_long_dec_and_test(atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return atomic_dec_and_test(v);
+}
+
+static inline int atomic_long_inc_and_test(atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return atomic_inc_and_test(v);
+}
+
+static inline int atomic_long_add_negative(long i, atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return atomic_add_negative(i, v);
+}
+
+static inline long atomic_long_add_return(long i, atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return (long)atomic_add_return(i, v);
+}
+
+static inline long atomic_long_sub_return(long i, atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return (long)atomic_sub_return(i, v);
+}
+
+static inline long atomic_long_inc_return(atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return (long)atomic_inc_return(v);
+}
+
+static inline long atomic_long_dec_return(atomic_long_t *l)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return (long)atomic_dec_return(v);
+}
+
+static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
+{
+       atomic_t *v = (atomic_t *)l;
+
+       return (long)atomic_add_unless(v, a, u);
+}
+
+#define atomic_long_inc_not_zero(l) atomic_inc_not_zero((atomic_t *)(l))
+
+#define atomic_long_cmpxchg(l, old, new) \
+       (atomic_cmpxchg((atomic_t *)(l), (old), (new)))
+#define atomic_long_xchg(v, new) \
+       (atomic_xchg((atomic_t *)(l), (new)))
+
 #endif  /*  BITS_PER_LONG == 64  */
 
 #endif  /*  _ASM_GENERIC_ATOMIC_H  */
index 78339319ba02cbcb019fd875612b9291499a944c..cd8a9641bd668e5e0ae2da5bebac5d1e7bf8704f 100644 (file)
@@ -58,7 +58,7 @@ extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
  * if you do not require the atomic guarantees.
  *
  * Note: there are no guarantees that this function will not be reordered
- * on non x86 architectures, so if you are writting portable code,
+ * on non x86 architectures, so if you are writing portable code,
  * make sure not to rely on its reordering guarantees.
  *
  * Note that @nr may be almost arbitrarily large; this function is not
diff --git a/include/asm-generic/kdebug.h b/include/asm-generic/kdebug.h
new file mode 100644 (file)
index 0000000..2b799c9
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASM_GENERIC_KDEBUG_H
+#define _ASM_GENERIC_KDEBUG_H
+
+enum die_val {
+       DIE_UNUSED,
+};
+
+#endif /* _ASM_GENERIC_KDEBUG_H */
index ab469297272c1da3e8cee1d77a6ab5f70a2805fc..33d7d04e41192cf11cebd8234220a36b298979df 100644 (file)
@@ -33,6 +33,19 @@ typedef struct
 #define local_add(i,l) atomic_long_add((i),(&(l)->a))
 #define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
 
+#define local_sub_and_test(i, l) atomic_long_sub_and_test((i), (&(l)->a))
+#define local_dec_and_test(l) atomic_long_dec_and_test(&(l)->a)
+#define local_inc_and_test(l) atomic_long_inc_and_test(&(l)->a)
+#define local_add_negative(i, l) atomic_long_add_negative((i), (&(l)->a))
+#define local_add_return(i, l) atomic_long_add_return((i), (&(l)->a))
+#define local_sub_return(i, l) atomic_long_sub_return((i), (&(l)->a))
+#define local_inc_return(l) atomic_long_inc_return(&(l)->a)
+
+#define local_cmpxchg(l, o, n) atomic_long_cmpxchg((&(l)->a), (o), (n))
+#define local_xchg(l, n) atomic_long_xchg((&(l)->a), (n))
+#define local_add_unless(l, a, u) atomic_long_add_unless((&(l)->a), (a), (u))
+#define local_inc_not_zero(l) atomic_long_inc_not_zero(&(l)->a)
+
 /* Non-atomic variants, ie. preemption disabled and won't be touched
  * in interrupt, etc.  Some archs can optimize this case well. */
 #define __local_inc(l)         local_set((l), local_read(l) + 1)
@@ -44,19 +57,19 @@ typedef struct
  * much more efficient than these naive implementations.  Note they take
  * a variable (eg. mystruct.foo), not an address.
  */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
+#define cpu_local_read(l)      local_read(&__get_cpu_var(l))
+#define cpu_local_set(l, i)    local_set(&__get_cpu_var(l), (i))
+#define cpu_local_inc(l)       local_inc(&__get_cpu_var(l))
+#define cpu_local_dec(l)       local_dec(&__get_cpu_var(l))
+#define cpu_local_add(i, l)    local_add((i), &__get_cpu_var(l))
+#define cpu_local_sub(i, l)    local_sub((i), &__get_cpu_var(l))
 
 /* Non-atomic increments, ie. preemption disabled and won't be touched
  * in interrupt, etc.  Some archs can optimize this case well.
  */
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
+#define __cpu_local_inc(l)     __local_inc(&__get_cpu_var(l))
+#define __cpu_local_dec(l)     __local_dec(&__get_cpu_var(l))
+#define __cpu_local_add(i, l)  __local_add((i), &__get_cpu_var(l))
+#define __cpu_local_sub(i, l)  __local_sub((i), &__get_cpu_var(l))
 
 #endif /* _ASM_GENERIC_LOCAL_H */
diff --git a/include/asm-h8300/kdebug.h b/include/asm-h8300/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index ddd07f485dd8b3fe23456e7364b8887e83a54f72..a09230a08e02d201e4c2b214a0bd6cabc5a8c223 100644 (file)
@@ -55,10 +55,6 @@ extern int is_in_rom(unsigned long);
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /*
  * All 32bit addresses are effectively valid for vmalloc...
  * Sort of meaningless for non-VM targets.
index 5084a9d4292254f28a638302cc3bc0eb9b609069..7807018f85002cd201db14dc74926f469b3c11b5 100644 (file)
@@ -98,7 +98,6 @@ asmlinkage void resume(void);
 #endif
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
index 4dd272331361c7eb747305366810fc92c28b3b08..0baa2f89463c70a96f3ef1b42ffe23adf63a5a55 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/compiler.h>
 #include <asm/processor.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -51,7 +52,7 @@ static __inline__ void atomic_add(int i, atomic_t *v)
 }
 
 /**
- * atomic_sub - subtract the atomic variable
+ * atomic_sub - subtract integer from atomic variable
  * @i: integer value to subtract
  * @v: pointer of type atomic_t
  * 
@@ -170,7 +171,7 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
 }
 
 /**
- * atomic_add_return - add and return
+ * atomic_add_return - add integer and return
  * @v: pointer of type atomic_t
  * @i: integer value to add
  *
@@ -202,13 +203,20 @@ no_xadd: /* Legacy 386 processor */
 #endif
 }
 
+/**
+ * atomic_sub_return - subtract integer and return
+ * @v: pointer of type atomic_t
+ * @i: integer value to subtract
+ *
+ * Atomically subtracts @i from @v and returns @v - @i
+ */
 static __inline__ int atomic_sub_return(int i, atomic_t *v)
 {
        return atomic_add_return(-i,v);
 }
 
-#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
 
 /**
  * atomic_add_unless - add unless the number is already a given value
@@ -219,20 +227,21 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
  * Atomically adds @a to @v, so long as @v was not already @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       for (;;) {                                              \
-               if (unlikely(c == (u)))                         \
-                       break;                                  \
-               old = atomic_cmpxchg((v), c, c + (a));          \
-               if (likely(old == c))                           \
-                       break;                                  \
-               c = old;                                        \
-       }                                                       \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_inc_return(v)  (atomic_add_return(1,v))
index 273b50629357bf15955b6c433a9d95f19af9dfbe..a20fe9822f6002db96607331fd7ae50f0a95ee58 100644 (file)
@@ -27,7 +27,7 @@
  * if you do not require the atomic guarantees.
  *
  * Note: there are no guarantees that this function will not be reordered
- * on non x86 architectures, so if you are writting portable code,
+ * on non x86 architectures, so if you are writing portable code,
  * make sure not to rely on its reordering guarantees.
  *
  * Note that @nr may be almost arbitrarily large; this function is not
index e7686d0a84136be4e4756a5a6bfdc762f55e35a0..bd024ab4fe53b02f6e9b0fe678defb0d1a982242 100644 (file)
@@ -12,7 +12,7 @@
 #define EXTENDED_VGA   0xfffe          /* 80x50 mode */
 #define ASK_VGA                0xfffd          /* ask for it at bootup */
 
-/* Physical address where kenrel should be loaded. */
+/* Physical address where kernel should be loaded. */
 #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
                                + (CONFIG_PHYSICAL_ALIGN - 1)) \
                                & ~(CONFIG_PHYSICAL_ALIGN - 1))
diff --git a/include/asm-i386/cmpxchg.h b/include/asm-i386/cmpxchg.h
new file mode 100644 (file)
index 0000000..7adcef0
--- /dev/null
@@ -0,0 +1,293 @@
+#ifndef __ASM_CMPXCHG_H
+#define __ASM_CMPXCHG_H
+
+#include <linux/bitops.h> /* for LOCK_PREFIX */
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+
+#ifdef CONFIG_X86_CMPXCHG64
+
+/*
+ * The semantics of XCHGCMP8B are a bit strange, this is why
+ * there is a loop and the loading of %%eax and %%edx has to
+ * be inside. This inlines well in most cases, the cached
+ * cost is around ~38 cycles. (in the future we might want
+ * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
+ * might have an implicit FPU-save as a cost, so it's not
+ * clear which path to go.)
+ *
+ * cmpxchg8b must be used with the lock prefix here to allow
+ * the instruction to be executed atomically, see page 3-102
+ * of the instruction set reference 24319102.pdf. We need
+ * the reader side to see the coherent 64bit value.
+ */
+static inline void __set_64bit (unsigned long long * ptr,
+               unsigned int low, unsigned int high)
+{
+       __asm__ __volatile__ (
+               "\n1:\t"
+               "movl (%0), %%eax\n\t"
+               "movl 4(%0), %%edx\n\t"
+               "lock cmpxchg8b (%0)\n\t"
+               "jnz 1b"
+               : /* no outputs */
+               :       "D"(ptr),
+                       "b"(low),
+                       "c"(high)
+               :       "ax","dx","memory");
+}
+
+static inline void __set_64bit_constant (unsigned long long *ptr,
+                                                unsigned long long value)
+{
+       __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
+}
+#define ll_low(x)      *(((unsigned int*)&(x))+0)
+#define ll_high(x)     *(((unsigned int*)&(x))+1)
+
+static inline void __set_64bit_var (unsigned long long *ptr,
+                        unsigned long long value)
+{
+       __set_64bit(ptr,ll_low(value), ll_high(value));
+}
+
+#define set_64bit(ptr,value) \
+(__builtin_constant_p(value) ? \
+ __set_64bit_constant(ptr, value) : \
+ __set_64bit_var(ptr, value) )
+
+#define _set_64bit(ptr,value) \
+(__builtin_constant_p(value) ? \
+ __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+ __set_64bit(ptr, ll_low(value), ll_high(value)) )
+
+#endif
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ *       but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+               case 1:
+                       __asm__ __volatile__("xchgb %b0,%1"
+                               :"=q" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 2:
+                       __asm__ __volatile__("xchgw %w0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 4:
+                       __asm__ __volatile__("xchgl %0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+       }
+       return x;
+}
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#ifdef CONFIG_X86_CMPXCHG
+#define __HAVE_ARCH_CMPXCHG 1
+#define cmpxchg(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+#define sync_cmpxchg(ptr,o,n)\
+       ((__typeof__(*(ptr)))__sync_cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+#define cmpxchg_local(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+#endif
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+/*
+ * Always use locked operations when touching memory shared with a
+ * hypervisor, since the system may be SMP even if the guest kernel
+ * isn't.
+ */
+static inline unsigned long __sync_cmpxchg(volatile void *ptr,
+                                           unsigned long old,
+                                           unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__("lock; cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__("lock; cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__("lock; cmpxchgl %1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                       unsigned long old, unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__("cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__("cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__("cmpxchgl %1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+#ifndef CONFIG_X86_CMPXCHG
+/*
+ * Building a kernel capable running on 80386. It may be necessary to
+ * simulate the cmpxchg on the 80386 CPU. For that purpose we define
+ * a function for each of the sizes we support.
+ */
+
+extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8);
+extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
+extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
+
+static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 1:
+               return cmpxchg_386_u8(ptr, old, new);
+       case 2:
+               return cmpxchg_386_u16(ptr, old, new);
+       case 4:
+               return cmpxchg_386_u32(ptr, old, new);
+       }
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                               \
+({                                                                     \
+       __typeof__(*(ptr)) __ret;                                       \
+       if (likely(boot_cpu_data.x86 > 3))                              \
+               __ret = __cmpxchg((ptr), (unsigned long)(o),            \
+                                       (unsigned long)(n), sizeof(*(ptr))); \
+       else                                                            \
+               __ret = cmpxchg_386((ptr), (unsigned long)(o),          \
+                                       (unsigned long)(n), sizeof(*(ptr))); \
+       __ret;                                                          \
+})
+#define cmpxchg_local(ptr,o,n)                                         \
+({                                                                     \
+       __typeof__(*(ptr)) __ret;                                       \
+       if (likely(boot_cpu_data.x86 > 3))                              \
+               __ret = __cmpxchg_local((ptr), (unsigned long)(o),      \
+                                       (unsigned long)(n), sizeof(*(ptr))); \
+       else                                                            \
+               __ret = cmpxchg_386((ptr), (unsigned long)(o),          \
+                                       (unsigned long)(n), sizeof(*(ptr))); \
+       __ret;                                                          \
+})
+#endif
+
+#ifdef CONFIG_X86_CMPXCHG64
+
+static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
+                                     unsigned long long new)
+{
+       unsigned long long prev;
+       __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+                            : "=A"(prev)
+                            : "b"((unsigned long)new),
+                              "c"((unsigned long)(new >> 32)),
+                              "m"(*__xg(ptr)),
+                              "0"(old)
+                            : "memory");
+       return prev;
+}
+
+static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
+                       unsigned long long old, unsigned long long new)
+{
+       unsigned long long prev;
+       __asm__ __volatile__("cmpxchg8b %3"
+                            : "=A"(prev)
+                            : "b"((unsigned long)new),
+                              "c"((unsigned long)(new >> 32)),
+                              "m"(*__xg(ptr)),
+                              "0"(old)
+                            : "memory");
+       return prev;
+}
+
+#define cmpxchg64(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
+                                       (unsigned long long)(n)))
+#define cmpxchg64_local(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg64_local((ptr),(unsigned long long)(o),\
+                                       (unsigned long long)(n)))
+#endif
+
+#endif
index d304ab4161ffc885af273bb4c6500a6692905a20..b32df3a332da12853ff4ea102411bd81c13a59d5 100644 (file)
@@ -9,8 +9,6 @@
 #include <asm/user.h>
 #include <asm/auxvec.h>
 
-#include <linux/utsname.h>
-
 #define R_386_NONE     0
 #define R_386_32       1
 #define R_386_PC32     2
index f962fadab0fadb61c3e85b984f5b9594c73c6c76..ef5878762dc997b3441c64f614238a94755776cf 100644 (file)
 #define TIOCSBRK       0x5427  /* BSD compatibility */
 #define TIOCCBRK       0x5428  /* BSD compatibility */
 #define TIOCGSID       0x5429  /* Return the session ID of FD */
+#define TCGETS2                _IOR('T',0x2A, struct termios2)
+#define TCSETS2                _IOW('T',0x2B, struct termios2)
+#define TCSETSW2       _IOW('T',0x2C, struct termios2)
+#define TCSETSF2       _IOW('T',0x2D, struct termios2)
 #define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
 
index d18cdb9fc9a685148f5281fb4e3f289aba2b1fbe..05c3117788b930634669f20ee22be5ac36a466e1 100644 (file)
@@ -9,19 +9,8 @@
 
 struct pt_regs;
 
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
 extern int register_page_fault_notifier(struct notifier_block *);
 extern int unregister_page_fault_notifier(struct notifier_block *);
-extern struct atomic_notifier_head i386die_chain;
 
 
 /* Grossly misnamed. */
@@ -38,20 +27,8 @@ enum die_val {
        DIE_GPF,
        DIE_CALL,
        DIE_NMI_IPI,
+       DIE_NMI_POST,
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .str = str,
-               .err = err,
-               .trapnr = trap,
-               .signr = sig
-       };
-       return atomic_notifier_call_chain(&i386die_chain, val, &args);
-}
-
 #endif
index bcb5b21de2d2dc27107a2bf6d743f5fcd1b73384..4b9dc9e6b701de5987d3ffe4f1d2709af183695d 100644 (file)
@@ -45,8 +45,6 @@
 /* We can also handle crash dumps from 64 bit kernel. */
 #define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
 
-#define MAX_NOTE_BYTES 1024
-
 /* CPU does not save ss and esp on stack if execution is already
  * running in kernel mode at the time of NMI occurrence. This code
  * fixes it.
index 12060e22f7e2a53204f4f8cfec20f95abfa6eeda..e13d3e98823f90a7ee8113855c5adf02b5b3a6a1 100644 (file)
 #define _ARCH_I386_LOCAL_H
 
 #include <linux/percpu.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
 
 typedef struct
 {
-       volatile long counter;
+       atomic_long_t a;
 } local_t;
 
-#define LOCAL_INIT(i)  { (i) }
+#define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
 
-#define local_read(v)  ((v)->counter)
-#define local_set(v,i) (((v)->counter) = (i))
+#define local_read(l)  atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set(&(l)->a, (i))
 
-static __inline__ void local_inc(local_t *v)
+static __inline__ void local_inc(local_t *l)
 {
        __asm__ __volatile__(
                "incl %0"
-               :"+m" (v->counter));
+               :"+m" (l->a.counter));
 }
 
-static __inline__ void local_dec(local_t *v)
+static __inline__ void local_dec(local_t *l)
 {
        __asm__ __volatile__(
                "decl %0"
-               :"+m" (v->counter));
+               :"+m" (l->a.counter));
 }
 
-static __inline__ void local_add(long i, local_t *v)
+static __inline__ void local_add(long i, local_t *l)
 {
        __asm__ __volatile__(
                "addl %1,%0"
-               :"+m" (v->counter)
+               :"+m" (l->a.counter)
                :"ir" (i));
 }
 
-static __inline__ void local_sub(long i, local_t *v)
+static __inline__ void local_sub(long i, local_t *l)
 {
        __asm__ __volatile__(
                "subl %1,%0"
-               :"+m" (v->counter)
+               :"+m" (l->a.counter)
                :"ir" (i));
 }
 
+/**
+ * local_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @l: pointer of type local_t
+ *
+ * Atomically subtracts @i from @l and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int local_sub_and_test(long i, local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "subl %2,%0; sete %1"
+               :"+m" (l->a.counter), "=qm" (c)
+               :"ir" (i) : "memory");
+       return c;
+}
+
+/**
+ * local_dec_and_test - decrement and test
+ * @l: pointer of type local_t
+ *
+ * Atomically decrements @l by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int local_dec_and_test(local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "decl %0; sete %1"
+               :"+m" (l->a.counter), "=qm" (c)
+               : : "memory");
+       return c != 0;
+}
+
+/**
+ * local_inc_and_test - increment and test
+ * @l: pointer of type local_t
+ *
+ * Atomically increments @l by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int local_inc_and_test(local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "incl %0; sete %1"
+               :"+m" (l->a.counter), "=qm" (c)
+               : : "memory");
+       return c != 0;
+}
+
+/**
+ * local_add_negative - add and test if negative
+ * @l: pointer of type local_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @l and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ int local_add_negative(long i, local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "addl %2,%0; sets %1"
+               :"+m" (l->a.counter), "=qm" (c)
+               :"ir" (i) : "memory");
+       return c;
+}
+
+/**
+ * local_add_return - add and return
+ * @l: pointer of type local_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @l and returns @i + @l
+ */
+static __inline__ long local_add_return(long i, local_t *l)
+{
+       long __i;
+#ifdef CONFIG_M386
+       unsigned long flags;
+       if(unlikely(boot_cpu_data.x86==3))
+               goto no_xadd;
+#endif
+       /* Modern 486+ processor */
+       __i = i;
+       __asm__ __volatile__(
+               "xaddl %0, %1;"
+               :"+r" (i), "+m" (l->a.counter)
+               : : "memory");
+       return i + __i;
+
+#ifdef CONFIG_M386
+no_xadd: /* Legacy 386 processor */
+       local_irq_save(flags);
+       __i = local_read(l);
+       local_set(l, i + __i);
+       local_irq_restore(flags);
+       return i + __i;
+#endif
+}
+
+static __inline__ long local_sub_return(long i, local_t *l)
+{
+       return local_add_return(-i,l);
+}
+
+#define local_inc_return(l)  (local_add_return(1,l))
+#define local_dec_return(l)  (local_sub_return(1,l))
+
+#define local_cmpxchg(l, o, n) \
+       (cmpxchg_local(&((l)->a.counter), (o), (n)))
+/* Always has a lock prefix */
+#define local_xchg(l, n) (xchg(&((l)->a.counter), (n)))
+
+/**
+ * local_add_unless - add unless the number is a given value
+ * @l: pointer of type local_t
+ * @a: the amount to add to l...
+ * @u: ...unless l is equal to u.
+ *
+ * Atomically adds @a to @l, so long as it was not @u.
+ * Returns non-zero if @l was not @u, and zero otherwise.
+ */
+#define local_add_unless(l, a, u)                              \
+({                                                             \
+       long c, old;                                            \
+       c = local_read(l);                                      \
+       for (;;) {                                              \
+               if (unlikely(c == (u)))                         \
+                       break;                                  \
+               old = local_cmpxchg((l), c, c + (a));   \
+               if (likely(old == c))                           \
+                       break;                                  \
+               c = old;                                        \
+       }                                                       \
+       c != (u);                                               \
+})
+#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+
 /* On x86, these are no better than the atomic variants. */
 #define __local_inc(l)         local_inc(l)
 #define __local_dec(l)         local_dec(l)
@@ -56,27 +207,27 @@ static __inline__ void local_sub(long i, local_t *v)
 
 /* Need to disable preemption for the cpu local counters otherwise we could
    still access a variable of a previous CPU in a non atomic way. */
-#define cpu_local_wrap_v(v)            \
+#define cpu_local_wrap_v(l)            \
        ({ local_t res__;               \
           preempt_disable();           \
-          res__ = (v);                 \
+          res__ = (l);                 \
           preempt_enable();            \
           res__; })
-#define cpu_local_wrap(v)              \
+#define cpu_local_wrap(l)              \
        ({ preempt_disable();           \
-          v;                           \
+          l;                           \
           preempt_enable(); })         \
 
-#define cpu_local_read(v)    cpu_local_wrap_v(local_read(&__get_cpu_var(v)))
-#define cpu_local_set(v, i)  cpu_local_wrap(local_set(&__get_cpu_var(v), (i)))
-#define cpu_local_inc(v)     cpu_local_wrap(local_inc(&__get_cpu_var(v)))
-#define cpu_local_dec(v)     cpu_local_wrap(local_dec(&__get_cpu_var(v)))
-#define cpu_local_add(i, v)  cpu_local_wrap(local_add((i), &__get_cpu_var(v)))
-#define cpu_local_sub(i, v)  cpu_local_wrap(local_sub((i), &__get_cpu_var(v)))
-
-#define __cpu_local_inc(v)     cpu_local_inc(v)
-#define __cpu_local_dec(v)     cpu_local_dec(v)
-#define __cpu_local_add(i, v)  cpu_local_add((i), (v))
-#define __cpu_local_sub(i, v)  cpu_local_sub((i), (v))
+#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
+
+#define __cpu_local_inc(l)     cpu_local_inc(l)
+#define __cpu_local_dec(l)     cpu_local_dec(l)
+#define __cpu_local_add(i, l)  cpu_local_add((i), (l))
+#define __cpu_local_sub(i, l)  cpu_local_sub((i), (l))
 
 #endif /* _ARCH_I386_LOCAL_H */
index 3503ad66945ec4a488cbd192635e5cc7c7db1b4f..118e9812778fd857f832632d2cbaa38a888cf9b0 100644 (file)
@@ -122,21 +122,21 @@ static inline int pfn_valid(int pfn)
        __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
 #define alloc_bootmem_node(pgdat, x)                                   \
 ({                                                                     \
-       struct pglist_data  __attribute__ ((unused))                    \
+       struct pglist_data  __maybe_unused                      \
                                *__alloc_bootmem_node__pgdat = (pgdat); \
        __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES,        \
                                                __pa(MAX_DMA_ADDRESS)); \
 })
 #define alloc_bootmem_pages_node(pgdat, x)                             \
 ({                                                                     \
-       struct pglist_data  __attribute__ ((unused))                    \
+       struct pglist_data  __maybe_unused                      \
                                *__alloc_bootmem_node__pgdat = (pgdat); \
        __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE,              \
                                                __pa(MAX_DMA_ADDRESS))  \
 })
 #define alloc_bootmem_low_pages_node(pgdat, x)                         \
 ({                                                                     \
-       struct pglist_data  __attribute__ ((unused))                    \
+       struct pglist_data  __maybe_unused                      \
                                *__alloc_bootmem_node__pgdat = (pgdat); \
        __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0);          \
 })
index 9559894c765882975450972db6ae54078a847b18..df21ea0493694a43db95b28f760263d6595f222d 100644 (file)
@@ -77,7 +77,7 @@ static inline unsigned long long native_read_pmc(void)
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
-
+#include <linux/errno.h>
 /*
  * Access to machine-specific registers (available on 586 and better only)
  * Note: the rd* operations modify the parameters directly (without using
@@ -86,68 +86,58 @@ static inline unsigned long long native_read_pmc(void)
 
 #define rdmsr(msr,val1,val2)                                           \
        do {                                                            \
-               unsigned long long __val = native_read_msr(msr);        \
-               val1 = __val;                                           \
-               val2 = __val >> 32;                                     \
+               u64 __val = native_read_msr(msr);                       \
+               (val1) = (u32)__val;                                    \
+               (val2) = (u32)(__val >> 32);                            \
        } while(0)
 
-#define wrmsr(msr,val1,val2)                                           \
-       native_write_msr(msr, ((unsigned long long)val2 << 32) | val1)
-
-#define rdmsrl(msr,val)                                        \
-       do {                                            \
-               (val) = native_read_msr(msr);           \
-       } while(0)
-
-static inline void wrmsrl (unsigned long msr, unsigned long long val)
+static inline void wrmsr(u32 __msr, u32 __low, u32 __high)
 {
-       unsigned long lo, hi;
-       lo = (unsigned long) val;
-       hi = val >> 32;
-       wrmsr (msr, lo, hi);
+       native_write_msr(__msr, ((u64)__high << 32) | __low);
 }
 
+#define rdmsrl(msr,val)                                                        \
+       ((val) = native_read_msr(msr))
+
+#define wrmsrl(msr,val)        native_write_msr(msr, val)
+
 /* wrmsr with exception handling */
-#define wrmsr_safe(msr,val1,val2)                                              \
-       (native_write_msr_safe(msr, ((unsigned long long)val2 << 32) | val1))
+static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high)
+{
+       return native_write_msr_safe(__msr, ((u64)__high << 32) | __low);
+}
 
 /* rdmsr with exception handling */
 #define rdmsr_safe(msr,p1,p2)                                          \
        ({                                                              \
                int __err;                                              \
-               unsigned long long __val = native_read_msr_safe(msr, &__err);\
-               (*p1) = __val;                                          \
-               (*p2) = __val >> 32;                                    \
+               u64 __val = native_read_msr_safe(msr, &__err);          \
+               (*p1) = (u32)__val;                                     \
+               (*p2) = (u32)(__val >> 32);                             \
                __err;                                                  \
        })
 
-#define rdtsc(low,high)                                                \
-       do {                                                    \
-               u64 _l = native_read_tsc();                     \
-               (low) = (u32)_l;                                \
-               (high) = _l >> 32;                              \
-       } while(0)
-
 #define rdtscl(low)                                            \
-       do {                                                    \
-               (low) = native_read_tsc();                      \
-       } while(0)
+       ((low) = (u32)native_read_tsc())
 
-#define rdtscll(val) ((val) = native_read_tsc())
+#define rdtscll(val)                                           \
+       ((val) = native_read_tsc())
 
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
 #define rdpmc(counter,low,high)                                        \
        do {                                                    \
                u64 _l = native_read_pmc();                     \
-               low = (u32)_l;                                  \
-               high = _l >> 32;                                \
+               (low)  = (u32)_l;                               \
+               (high) = (u32)(_l >> 32);                       \
        } while(0)
 #endif /* !CONFIG_PARAVIRT */
 
 #ifdef CONFIG_SMP
 void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 #else  /*  CONFIG_SMP  */
 static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 {
@@ -157,6 +147,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        wrmsr(msr_no, l, h);
 }
+static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       return rdmsr_safe(msr_no, l, h);
+}
+static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       return wrmsr_safe(msr_no, l, h);
+}
 #endif  /*  CONFIG_SMP  */
 #endif
 #endif
index e2e7f98723c57fac6c3f45c797a1a7a1060df45a..bc5c12c135817c2c2b8da89c27656a91a9a2b280 100644 (file)
@@ -560,11 +560,6 @@ static inline u64 paravirt_read_tsc(void)
 {
        return PVOP_CALL0(u64, read_tsc);
 }
-#define rdtsc(low,high) do {                   \
-       u64 _l = paravirt_read_tsc();           \
-       low = (u32)_l;                          \
-       high = _l >> 32;                        \
-} while(0)
 
 #define rdtscl(low) do {                       \
        u64 _l = paravirt_read_tsc();           \
index e16359f81a40cc8716eb8fc783035e1998ac8ff7..edce9d51a676cd4822c09c21b0663801d52e03e3 100644 (file)
@@ -243,8 +243,6 @@ static inline pte_t pte_mkyoung(pte_t pte)  { (pte).pte_low |= _PAGE_ACCESSED; re
 static inline pte_t pte_mkwrite(pte_t pte)     { (pte).pte_low |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)      { (pte).pte_low |= _PAGE_PSE; return pte; }
 
-extern void vmalloc_sync_all(void);
-
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
@@ -544,10 +542,6 @@ static inline void paravirt_pagetable_setup_done(pgd_t *base)
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #include <asm-generic/pgtable.h>
 
 #endif /* _I386_PGTABLE_H */
index bd67480ca1094f9896aacdf5395d0b541552fb75..57a4306cdf63e33f7a5eea692be606d90bc6cfee 100644 (file)
  * megabits/second; but this requires the faster clock.
  */
 #define BASE_BAUD ( 1843200 / 16 )
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#define SERIAL_PORT_DFNS                       \
-       /* UART CLK   PORT IRQ     FLAGS        */                      \
-       { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
-       { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },      /* ttyS1 */     \
-       { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },      /* ttyS2 */     \
-       { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },     /* ttyS3 */
index 090abc1da32a158b786be16dd7a610cf507d3380..0c713278706262e60abaa34229ccedfa4e9a45d9 100644 (file)
@@ -124,20 +124,6 @@ static inline int num_booting_cpus(void)
        return cpus_weight(cpu_callout_map);
 }
 
-#ifdef CONFIG_X86_LOCAL_APIC
-
-#ifdef APIC_DEFINITION
-extern int hard_smp_processor_id(void);
-#else
-#include <mach_apicdef.h>
-static inline int hard_smp_processor_id(void)
-{
-       /* we don't want to mark this access volatile - bad code generation */
-       return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
-}
-#endif
-#endif
-
 extern int safe_smp_processor_id(void);
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
@@ -152,10 +138,31 @@ extern unsigned int num_processors;
 
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 
-#endif
+#endif /* CONFIG_SMP */
 
 #ifndef __ASSEMBLY__
 
+#ifdef CONFIG_X86_LOCAL_APIC
+
+#ifdef APIC_DEFINITION
+extern int hard_smp_processor_id(void);
+#else
+#include <mach_apicdef.h>
+static inline int hard_smp_processor_id(void)
+{
+       /* we don't want to mark this access volatile - bad code generation */
+       return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
+}
+#endif /* APIC_DEFINITION */
+
+#else /* CONFIG_X86_LOCAL_APIC */
+
+#ifndef CONFIG_SMP
+#define hard_smp_processor_id()                0
+#endif
+
+#endif /* CONFIG_X86_LOCAL_APIC */
+
 extern u8 apicid_2_node[];
 
 #ifdef CONFIG_X86_LOCAL_APIC
index 7d72351bea753f54d79d26e32aa460f2dd01ea06..cbce08a2d135e22b721bbfe7a643a3f01e3f321f 100644 (file)
@@ -24,7 +24,7 @@
  * if you do not require the atomic guarantees.
  *
  * Note: there are no guarantees that this function will not be reordered
- * on non x86 architectures, so if you are writting portable code,
+ * on non-x86 architectures, so if you are writing portable code,
  * make sure not to rely on its reordering guarantees.
  *
  * Note that @nr may be almost arbitrarily large; this function is not
index c3a58c08c49506dcd120e92fa73d0fd3e95ca602..94ed3686a5f30a79ecd5085262ceab745019f7ba 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/kernel.h>
 #include <asm/segment.h>
 #include <asm/cpufeature.h>
-#include <linux/bitops.h> /* for LOCK_PREFIX */
+#include <asm/cmpxchg.h>
 
 #ifdef __KERNEL__
 
@@ -195,238 +195,6 @@ static inline unsigned long get_limit(unsigned long segment)
 
 #define nop() __asm__ __volatile__ ("nop")
 
-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
-
-#define tas(ptr) (xchg((ptr),1))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-
-#ifdef CONFIG_X86_CMPXCHG64
-
-/*
- * The semantics of XCHGCMP8B are a bit strange, this is why
- * there is a loop and the loading of %%eax and %%edx has to
- * be inside. This inlines well in most cases, the cached
- * cost is around ~38 cycles. (in the future we might want
- * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
- * might have an implicit FPU-save as a cost, so it's not
- * clear which path to go.)
- *
- * cmpxchg8b must be used with the lock prefix here to allow
- * the instruction to be executed atomically, see page 3-102
- * of the instruction set reference 24319102.pdf. We need
- * the reader side to see the coherent 64bit value.
- */
-static inline void __set_64bit (unsigned long long * ptr,
-               unsigned int low, unsigned int high)
-{
-       __asm__ __volatile__ (
-               "\n1:\t"
-               "movl (%0), %%eax\n\t"
-               "movl 4(%0), %%edx\n\t"
-               "lock cmpxchg8b (%0)\n\t"
-               "jnz 1b"
-               : /* no outputs */
-               :       "D"(ptr),
-                       "b"(low),
-                       "c"(high)
-               :       "ax","dx","memory");
-}
-
-static inline void __set_64bit_constant (unsigned long long *ptr,
-                                                unsigned long long value)
-{
-       __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
-}
-#define ll_low(x)      *(((unsigned int*)&(x))+0)
-#define ll_high(x)     *(((unsigned int*)&(x))+1)
-
-static inline void __set_64bit_var (unsigned long long *ptr,
-                        unsigned long long value)
-{
-       __set_64bit(ptr,ll_low(value), ll_high(value));
-}
-
-#define set_64bit(ptr,value) \
-(__builtin_constant_p(value) ? \
- __set_64bit_constant(ptr, value) : \
- __set_64bit_var(ptr, value) )
-
-#define _set_64bit(ptr,value) \
-(__builtin_constant_p(value) ? \
- __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
- __set_64bit(ptr, ll_low(value), ll_high(value)) )
-
-#endif
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
- * Note 2: xchg has side effect, so that attribute volatile is necessary,
- *       but generally the primitive is invalid, *ptr is output argument. --ANK
- */
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-               case 1:
-                       __asm__ __volatile__("xchgb %b0,%1"
-                               :"=q" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-               case 2:
-                       __asm__ __volatile__("xchgw %w0,%1"
-                               :"=r" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-               case 4:
-                       __asm__ __volatile__("xchgl %0,%1"
-                               :"=r" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-       }
-       return x;
-}
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#ifdef CONFIG_X86_CMPXCHG
-#define __HAVE_ARCH_CMPXCHG 1
-#define cmpxchg(ptr,o,n)\
-       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-                                       (unsigned long)(n),sizeof(*(ptr))))
-#define sync_cmpxchg(ptr,o,n)\
-       ((__typeof__(*(ptr)))__sync_cmpxchg((ptr),(unsigned long)(o),\
-                                       (unsigned long)(n),sizeof(*(ptr))))
-#endif
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 2:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 4:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       }
-       return old;
-}
-
-/*
- * Always use locked operations when touching memory shared with a
- * hypervisor, since the system may be SMP even if the guest kernel
- * isn't.
- */
-static inline unsigned long __sync_cmpxchg(volatile void *ptr,
-                                           unsigned long old,
-                                           unsigned long new, int size)
-{
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               __asm__ __volatile__("lock; cmpxchgb %b1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 2:
-               __asm__ __volatile__("lock; cmpxchgw %w1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 4:
-               __asm__ __volatile__("lock; cmpxchgl %1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       }
-       return old;
-}
-
-#ifndef CONFIG_X86_CMPXCHG
-/*
- * Building a kernel capable running on 80386. It may be necessary to
- * simulate the cmpxchg on the 80386 CPU. For that purpose we define
- * a function for each of the sizes we support.
- */
-
-extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8);
-extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
-extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
-
-static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 1:
-               return cmpxchg_386_u8(ptr, old, new);
-       case 2:
-               return cmpxchg_386_u16(ptr, old, new);
-       case 4:
-               return cmpxchg_386_u32(ptr, old, new);
-       }
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                               \
-({                                                                     \
-       __typeof__(*(ptr)) __ret;                                       \
-       if (likely(boot_cpu_data.x86 > 3))                              \
-               __ret = __cmpxchg((ptr), (unsigned long)(o),            \
-                                       (unsigned long)(n), sizeof(*(ptr))); \
-       else                                                            \
-               __ret = cmpxchg_386((ptr), (unsigned long)(o),          \
-                                       (unsigned long)(n), sizeof(*(ptr))); \
-       __ret;                                                          \
-})
-#endif
-
-#ifdef CONFIG_X86_CMPXCHG64
-
-static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
-                                     unsigned long long new)
-{
-       unsigned long long prev;
-       __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
-                            : "=A"(prev)
-                            : "b"((unsigned long)new),
-                              "c"((unsigned long)(new >> 32)),
-                              "m"(*__xg(ptr)),
-                              "0"(old)
-                            : "memory");
-       return prev;
-}
-
-#define cmpxchg64(ptr,o,n)\
-       ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
-                                       (unsigned long long)(n)))
-
-#endif
-    
 /*
  * Force strict CPU ordering.
  * And yes, this is required on UP too when we're talking
index 2e6237693814e8d6d50e738b38b3ff36579cc80d..a21700352e7b0932e8f859bb8cdf0abf826bab3b 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 struct ktermios {
        tcflag_t c_iflag;               /* input mode flags */
        tcflag_t c_oflag;               /* output mode flags */
@@ -129,6 +140,7 @@ struct ktermios {
 #define HUPCL  0002000
 #define CLOCAL 0004000
 #define CBAUDEX 0010000
+#define   BOTHER  0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -148,6 +160,8 @@ struct ktermios {
 #define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
 
+#define IBSHIFT          16            /* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG   0000001
 #define ICANON 0000002
index 7c99678a8f863ab546568bb31ae25ac82c15c1f7..f520b7c16fa2f3178fcc0a44326d8b5d7690b189 100644 (file)
@@ -81,8 +81,10 @@ struct termio {
        copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif /* __KERNEL__ */
 
index bf01d4b342bd40978997695c6298f65b55232c1d..4cb0f91ae64f3dc01e7a945012fe6184be784fd4 100644 (file)
@@ -172,7 +172,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TS_USEDFPU             0x0001  /* FPU was used by this task this quantum (SMP) */
 #define TS_POLLING             0x0002  /* True if in idle loop and not sleeping */
 
-#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
 #endif /* __KERNEL__ */
 
index 833fa1704ff995c32a412f6fdf09b9f62a9cdf43..bd21e795197c5689d823ae2d9abda8a3cc3693ad 100644 (file)
 #define __NR_move_pages                317
 #define __NR_getcpu            318
 #define __NR_epoll_pwait       319
+#define __NR_utimensat         320
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 320
+#define NR_syscalls 321
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 569ec7574baf24b01ce450c4f6a5cdc32d805a60..1fc3b83325dab4fa0c20fb46abbc6d16228b34fa 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 
 #include <asm/intrinsics.h>
+#include <asm/system.h>
 
 /*
  * On IA-64, counter must always be volatile to ensure that that the
@@ -88,25 +89,47 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)
        return new;
 }
 
-#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       for (;;) {                                              \
-               if (unlikely(c == (u)))                         \
-                       break;                                  \
-               old = atomic_cmpxchg((v), c, c + (a));          \
-               if (likely(old == c))                           \
-                       break;                                  \
-               c = old;                                        \
-       }                                                       \
-       c != (u);                                               \
-})
+#define atomic64_cmpxchg(v, old, new) \
+       (cmpxchg(&((v)->counter), old, new))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #define atomic_add_return(i,v)                                         \
 ({                                                                     \
        int __ia64_aar_i = (i);                                         \
index aed7142f9e4a520b9df81fe8b906e656a787f96f..ba211e011a1d4d22dcfa4d8d7a0bcaed3a9747e1 100644 (file)
  */
 #include <linux/notifier.h>
 
-struct pt_regs;
-
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
 extern int register_page_fault_notifier(struct notifier_block *);
 extern int unregister_page_fault_notifier(struct notifier_block *);
-extern struct atomic_notifier_head ia64die_chain;
 
 enum die_val {
        DIE_BREAK = 1,
@@ -74,18 +61,4 @@ enum die_val {
        DIE_KDUMP_LEAVE,
 };
 
-static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
-                            long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs   = regs,
-               .str    = str,
-               .err    = err,
-               .trapnr = trap,
-               .signr  = sig
-       };
-
-       return atomic_notifier_call_chain(&ia64die_chain, val, &args);
-}
-
 #endif
index 41299ddfee30e0c742102420725e3645bd711999..541be835fc5a16f7ee6019fa6f2812f3e310a1cb 100644 (file)
@@ -14,8 +14,6 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_IA_64
 
-#define MAX_NOTE_BYTES 1024
-
 #define kexec_flush_icache_page(page) do { \
                 unsigned long page_addr = (unsigned long)page_address(page); \
                 flush_icache_range(page_addr, page_addr + PAGE_SIZE); \
index dc519092ef4d65099a3c8ad7dec8e7a902cb29a3..c11c530f74d02877738b3b6edb5d59102a9bf01c 100644 (file)
@@ -1,50 +1 @@
-#ifndef _ASM_IA64_LOCAL_H
-#define _ASM_IA64_LOCAL_H
-
-/*
- * Copyright (C) 2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/percpu.h>
-
-typedef struct {
-       atomic64_t val;
-} local_t;
-
-#define LOCAL_INIT(i)  ((local_t) { { (i) } })
-#define local_read(l)  atomic64_read(&(l)->val)
-#define local_set(l, i)        atomic64_set(&(l)->val, i)
-#define local_inc(l)   atomic64_inc(&(l)->val)
-#define local_dec(l)   atomic64_dec(&(l)->val)
-#define local_add(i, l)        atomic64_add((i), &(l)->val)
-#define local_sub(i, l)        atomic64_sub((i), &(l)->val)
-
-/* Non-atomic variants, i.e., preemption disabled and won't be touched in interrupt, etc.  */
-
-#define __local_inc(l)         (++(l)->val.counter)
-#define __local_dec(l)         (--(l)->val.counter)
-#define __local_add(i,l)       ((l)->val.counter += (i))
-#define __local_sub(i,l)       ((l)->val.counter -= (i))
-
-/*
- * Use these for per-cpu local_t variables.  Note they take a variable (eg. mystruct.foo),
- * not an address.
- */
-#define cpu_local_read(v)      local_read(&__ia64_per_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__ia64_per_cpu_var(v), (i))
-#define cpu_local_inc(v)       local_inc(&__ia64_per_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__ia64_per_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__ia64_per_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__ia64_per_cpu_var(v))
-
-/*
- * Non-atomic increments, i.e., preemption disabled and won't be touched in interrupt,
- * etc.
- */
-#define __cpu_local_inc(v)     __local_inc(&__ia64_per_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__ia64_per_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__ia64_per_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__ia64_per_cpu_var(v))
-
-#endif /* _ASM_IA64_LOCAL_H */
+#include <asm-generic/local.h>
index 553182747722464293494ef0be217cca5863cad2..670b706411b88c01c5a1785e467f387510ecfe2a 100644 (file)
@@ -485,10 +485,6 @@ extern void paging_init (void);
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
index 60fd4ae014f6fbe8a3fe19b8e9171a7e277f609e..c60024989ebd59b70bd090d01cc0ada6a95ad9d4 100644 (file)
@@ -38,6 +38,8 @@ ia64_get_lid (void)
        return lid.f.id << 8 | lid.f.eid;
 }
 
+#define hard_smp_processor_id()                ia64_get_lid()
+
 #ifdef CONFIG_SMP
 
 #define XTP_OFFSET             0x1e0008
@@ -110,8 +112,6 @@ max_xtp (void)
                writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
 }
 
-#define hard_smp_processor_id()                ia64_get_lid()
-
 /* Upping and downing of CPUs */
 extern int __cpu_disable (void);
 extern void __cpu_die (unsigned int cpu);
@@ -128,7 +128,7 @@ extern void unlock_ipi_calllock(void);
 extern void identify_siblings (struct cpuinfo_ia64 *);
 extern int is_multithreading_enabled(void);
 
-#else
+#else /* CONFIG_SMP */
 
 #define cpu_logical_id(i)              0
 #define cpu_physical_id(i)             ia64_get_lid()
index 077d6778575a2b0f4bffedc26519f8d9f745b5f3..7d0241db622b0e19f6ca350782b214c348d05e4c 100644 (file)
@@ -112,6 +112,6 @@ struct thread_info {
 
 #define TS_POLLING             1       /* true if in idle loop and not sleeping */
 
-#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
 #endif /* _ASM_IA64_THREAD_INFO_H */
index f5a7d7301c72170523cc265402acfc487d16b553..3a38ffe4a4f49991e43b59eb9f18dcb1cb3d32d0 100644 (file)
@@ -253,14 +253,21 @@ static __inline__ int atomic_dec_return(atomic_t *v)
  * Atomically adds @a to @v, so long as it was not @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
diff --git a/include/asm-m32r/kdebug.h b/include/asm-m32r/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 1c15ba7ce319dd3b6a2bce9a6be4bfb84628bc08..8b2a2f17e69559e42c21894c0448f9d2ac048947 100644 (file)
@@ -381,10 +381,6 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)        \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
index abd937ac5239ae91503275cea548652bf020db23..078e1a51a042a74a6eeda6c48d3f8882a466f2fc 100644 (file)
@@ -108,6 +108,10 @@ extern unsigned long send_IPI_mask_phys(cpumask_t, int, int);
 #define IPI_SHIFT      (0)
 #define NR_IPIS                (8)
 
-#endif /* CONFIG_SMP */
+#else  /* CONFIG_SMP */
+
+#define hard_smp_processor_id()                0
+
+#endif /* CONFIG_SMP */
 
 #endif /* _ASM_M32R_SMP_H */
index 99ee09889ff78578ca1c913e1c75a1ce4b65f319..f62f5c9abba6a32a42b8af0cee0d4a03d7df2071 100644 (file)
@@ -122,8 +122,6 @@ static inline void local_irq_disable(void)
 #define xchg(ptr,x) \
        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-#define tas(ptr)       (xchg((ptr),1))
-
 #ifdef CONFIG_SMP
 extern void  __xchg_called_with_bad_pointer(void);
 #endif
@@ -138,7 +136,7 @@ extern void  __xchg_called_with_bad_pointer(void);
        "add3   "reg0", "addr", #0x2000;                \n\t"   \
        "ld     "reg0", @"reg0";                        \n\t"   \
        "unlock "reg0", @"reg1";                        \n\t"
-       /* FIXME: This workaround code cannot handle kenrel modules
+       /* FIXME: This workaround code cannot handle kernel modules
         * correctly under SMP environment.
         */
 #else  /* CONFIG_CHIP_M32700_TS1 */
index f28acd0fd689f17c62a4b76d20bb359853ad907a..6211363a345ff4a7353ad2a2b2d5a20d20c5625c 100644 (file)
@@ -2,7 +2,7 @@
 ** linux/atarihw.h -- This header defines some macros and pointers for
 **                    the various Atari custom hardware registers.
 **
-** Copyright 1994 by Bj\94rn Brauel
+** Copyright 1994 by BjÂ\94rn Brauel
 **
 ** 5/1/94 Roman Hodek:
 **   Added definitions for TT specific chips.
index 0ed454fc24bb5416e0b4f0c1c17b1c95fc15fe6e..ce6c445805bde61e7dab52c5173089024362ec39 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ** atariints.h -- Atari Linux interrupt handling structs and prototypes
 **
-** Copyright 1994 by Bj\94rn Brauel
+** Copyright 1994 by BjÂ\94rn Brauel
 **
 ** 5/2/94 Roman Hodek:
 **   TT interrupt definitions added.
index d5eed64cb833d277bcc459ab0175022c045232be..4915294fea63a726cb901ec1799ed9e7bc4586f9 100644 (file)
@@ -2,7 +2,7 @@
 #define __ARCH_M68K_ATOMIC__
 
 
-#include <asm/system.h>        /* local_irq_XXX() */
+#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -170,20 +170,21 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
        __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
 }
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       for (;;) {                                              \
-               if (unlikely(c == (u)))                         \
-                       break;                                  \
-               old = atomic_cmpxchg((v), c, c + (a));          \
-               if (likely(old == c))                           \
-                       break;                                  \
-               c = old;                                        \
-       }                                                       \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* Atomic operations are already serializing */
diff --git a/include/asm-m68k/kdebug.h b/include/asm-m68k/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index f3aa05377987d0a08b50a040c56064fc87303bd3..555b87a1f7e3220ff562c60ab0409b4273e90568 100644 (file)
@@ -143,10 +143,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /* MMU-specific headers */
 
 #ifdef CONFIG_SUN3
index 8e612266da51bb1bcc6871bf55663b144d1d2d12..24887a2d9c7bd09290b6980fee23e4a1d74090fa 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _M68K_SCATTERLIST_H
 #define _M68K_SCATTERLIST_H
 
+#include <linux/types.h>
+
 struct scatterlist {
        struct page *page;
        unsigned int offset;
index 243dd13e6bfc0895fcf0cfcd7081ac333a2f07bf..198878b53a618c92cf5f37261b0476807754c722 100644 (file)
@@ -88,7 +88,6 @@ static inline int irqs_disabled(void)
 
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
index c4d622a57dfbf5d3bfb9913bfa257bc8c0ab58da..d635a375248896149ba6a14fcfc7392ca62873f0 100644 (file)
@@ -37,17 +37,17 @@ struct thread_info {
 #define init_stack             (init_thread_union.stack)
 
 #define task_thread_info(tsk)  (&(tsk)->thread.info)
-#define task_stack_page(tsk)   ((void *)(tsk)->thread_info)
+#define task_stack_page(tsk)   ((tsk)->stack)
 #define current_thread_info()  task_thread_info(current)
 
 #define __HAVE_THREAD_FUNCTIONS
 
 #define setup_thread_stack(p, org) ({                  \
-       *(struct task_struct **)(p)->thread_info = (p); \
+       *(struct task_struct **)(p)->stack = (p);       \
        task_thread_info(p)->task = (p);                \
 })
 
-#define end_of_stack(p) ((unsigned long *)(p)->thread_info + 1)
+#define end_of_stack(p) ((unsigned long *)(p)->stack + 1)
 
 /* entry.S relies on these definitions!
  * bits 0-7 are tested at every exception exit
index 6c4e4b63e45454f018e5f3bfc599a506bcaa4827..d5632a305dae8e992626dc7d79efc778805f5a51 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ARCH_M68KNOMMU_ATOMIC__
 #define __ARCH_M68KNOMMU_ATOMIC__
 
-#include <asm/system.h>        /* local_irq_XXX() */
+#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -131,14 +131,21 @@ static inline int atomic_sub_return(int i, atomic_t * v)
 #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
diff --git a/include/asm-m68knommu/kdebug.h b/include/asm-m68knommu/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 549ad231efadb0b1fc7cc76315b7781279327e32..9dfbbc24aa7161546654ff4025225755c7d6a211 100644 (file)
@@ -59,10 +59,6 @@ extern int is_in_rom(unsigned long);
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /*
  * All 32bit addresses are effectively valid for vmalloc...
  * Sort of meaningless for non-VM targets.
index 2a814498672d72408c149f4d64580232f697c5df..5e5ed18bb78f54185da3d69ecfc0b1e9fd2373f7 100644 (file)
@@ -120,7 +120,6 @@ asmlinkage void resume(void);
 #endif
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
index 1ac50b6c47adfc634ad55a3b023dc1d63fce7d3e..62daa746a9c9180101af1e566635778c36d1d269 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
+#include <asm/system.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
@@ -306,8 +307,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
        return result;
 }
 
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
 
 /**
  * atomic_add_unless - add unless the number is a given value
@@ -318,14 +319,20 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
  * Atomically adds @a to @v, so long as it was not @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
@@ -681,6 +688,36 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
        return result;
 }
 
+#define atomic64_cmpxchg(v, o, n) \
+       (((__typeof__((v)->counter)))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #define atomic64_dec_return(v) atomic64_sub_return(1,(v))
 #define atomic64_inc_return(v) atomic64_add_return(1,(v))
 
index c7c945baf1ee6c4140468baa7f84d90e2391cf47..dbf834f4dac41a7a3888933b53cea2b518a5b0ba 100644 (file)
@@ -254,7 +254,7 @@ extern void free_init_pages(const char *what,
 extern char arcs_cmdline[CL_SIZE];
 
 /*
- * Registers a0, a1, a3 and a4 as passed to the kenrel entry by firmware
+ * Registers a0, a1, a3 and a4 as passed to the kernel entry by firmware
  */
 extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
 
diff --git a/include/asm-mips/kdebug.h b/include/asm-mips/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index b25267ebcb095c017f956ddcc9dda30025ea1e5b..cdbab43b7d3a6c3b98f0cfd330435148617c4f85 100644 (file)
@@ -21,8 +21,6 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_MIPS
 
-#define MAX_NOTE_BYTES 1024
-
 static inline void crash_setup_regs(struct pt_regs *newregs,
                                    struct pt_regs *oldregs)
 {
index 9e2d43bae388c06da2ae83f8e17ec7b14772dc78..ed882c88e0caa0e8d9add0be6b7c8ce7576c36cd 100644 (file)
-#ifndef _ASM_LOCAL_H
-#define _ASM_LOCAL_H
+#ifndef _ARCH_MIPS_LOCAL_H
+#define _ARCH_MIPS_LOCAL_H
 
 #include <linux/percpu.h>
+#include <linux/bitops.h>
 #include <asm/atomic.h>
+#include <asm/war.h>
 
-#ifdef CONFIG_32BIT
+typedef struct
+{
+       atomic_long_t a;
+} local_t;
 
-typedef atomic_t local_t;
+#define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
 
-#define LOCAL_INIT(i)  ATOMIC_INIT(i)
-#define local_read(v)  atomic_read(v)
-#define local_set(v,i) atomic_set(v,i)
+#define local_read(l)  atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set(&(l)->a, (i))
 
-#define local_inc(v)   atomic_inc(v)
-#define local_dec(v)   atomic_dec(v)
-#define local_add(i, v)        atomic_add(i, v)
-#define local_sub(i, v)        atomic_sub(i, v)
+#define local_add(i,l) atomic_long_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
+#define local_inc(l)   atomic_long_inc(&(l)->a)
+#define local_dec(l)   atomic_long_dec(&(l)->a)
 
-#endif
+/*
+ * Same as above, but return the result value
+ */
+static __inline__ long local_add_return(long i, local_t * l)
+{
+       unsigned long result;
+
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               unsigned long temp;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_add_return      \n"
+               "       addu    %0, %1, %3                              \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqzl   %0, 1b                                  \n"
+               "       addu    %0, %1, %3                              \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               unsigned long temp;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_add_return      \n"
+               "       addu    %0, %1, %3                              \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqz    %0, 1b                                  \n"
+               "       addu    %0, %1, %3                              \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else {
+               unsigned long flags;
 
-#ifdef CONFIG_64BIT
+               local_irq_save(flags);
+               result = l->a.counter;
+               result += i;
+               l->a.counter = result;
+               local_irq_restore(flags);
+       }
 
-typedef atomic64_t local_t;
+       return result;
+}
 
-#define LOCAL_INIT(i)  ATOMIC64_INIT(i)
-#define local_read(v)  atomic64_read(v)
-#define local_set(v,i) atomic64_set(v,i)
+static __inline__ long local_sub_return(long i, local_t * l)
+{
+       unsigned long result;
 
-#define local_inc(v)   atomic64_inc(v)
-#define local_dec(v)   atomic64_dec(v)
-#define local_add(i, v)        atomic64_add(i, v)
-#define local_sub(i, v)        atomic64_sub(i, v)
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               unsigned long temp;
 
-#endif
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_return      \n"
+               "       subu    %0, %1, %3                              \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqzl   %0, 1b                                  \n"
+               "       subu    %0, %1, %3                              \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               unsigned long temp;
 
-#define __local_inc(v)         ((v)->counter++)
-#define __local_dec(v)         ((v)->counter--)
-#define __local_add(i,v)       ((v)->counter+=(i))
-#define __local_sub(i,v)       ((v)->counter-=(i))
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_return      \n"
+               "       subu    %0, %1, %3                              \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqz    %0, 1b                                  \n"
+               "       subu    %0, %1, %3                              \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               result = l->a.counter;
+               result -= i;
+               l->a.counter = result;
+               local_irq_restore(flags);
+       }
+
+       return result;
+}
 
 /*
- * Use these for per-cpu local_t variables: on some archs they are
+ * local_sub_if_positive - conditionally subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @l: pointer of type local_t
+ *
+ * Atomically test @l and subtract @i if @l is greater or equal than @i.
+ * The function returns the old value of @l minus @i.
+ */
+static __inline__ long local_sub_if_positive(long i, local_t * l)
+{
+       unsigned long result;
+
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               unsigned long temp;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_if_positive\n"
+               "       dsubu   %0, %1, %3                              \n"
+               "       bltz    %0, 1f                                  \n"
+                       __SC    "%0, %2                                 \n"
+               "       .set    noreorder                               \n"
+               "       beqzl   %0, 1b                                  \n"
+               "        dsubu  %0, %1, %3                              \n"
+               "       .set    reorder                                 \n"
+               "1:                                                     \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               unsigned long temp;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_if_positive\n"
+               "       dsubu   %0, %1, %3                              \n"
+               "       bltz    %0, 1f                                  \n"
+                       __SC    "%0, %2                                 \n"
+               "       .set    noreorder                               \n"
+               "       beqz    %0, 1b                                  \n"
+               "        dsubu  %0, %1, %3                              \n"
+               "       .set    reorder                                 \n"
+               "1:                                                     \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
+               : "Ir" (i), "m" (l->a.counter)
+               : "memory");
+       } else {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               result = l->a.counter;
+               result -= i;
+               if (result >= 0)
+                       l->a.counter = result;
+               local_irq_restore(flags);
+       }
+
+       return result;
+}
+
+#define local_cmpxchg(l, o, n) \
+       ((long)cmpxchg_local(&((l)->a.counter), (o), (n)))
+#define local_xchg(l, n) (xchg_local(&((l)->a.counter),(n)))
+
+/**
+ * local_add_unless - add unless the number is a given value
+ * @l: pointer of type local_t
+ * @a: the amount to add to l...
+ * @u: ...unless l is equal to u.
+ *
+ * Atomically adds @a to @l, so long as it was not @u.
+ * Returns non-zero if @l was not @u, and zero otherwise.
+ */
+#define local_add_unless(l, a, u)                              \
+({                                                             \
+       long c, old;                                            \
+       c = local_read(l);                                      \
+       while (c != (u) && (old = local_cmpxchg((l), c, c + (a))) != c) \
+               c = old;                                        \
+       c != (u);                                               \
+})
+#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+
+#define local_dec_return(l) local_sub_return(1,(l))
+#define local_inc_return(l) local_add_return(1,(l))
+
+/*
+ * local_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @l: pointer of type local_t
+ *
+ * Atomically subtracts @i from @l and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define local_sub_and_test(i,l) (local_sub_return((i), (l)) == 0)
+
+/*
+ * local_inc_and_test - increment and test
+ * @l: pointer of type local_t
+ *
+ * Atomically increments @l by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define local_inc_and_test(l) (local_inc_return(l) == 0)
+
+/*
+ * local_dec_and_test - decrement by 1 and test
+ * @l: pointer of type local_t
+ *
+ * Atomically decrements @l by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define local_dec_and_test(l) (local_sub_return(1, (l)) == 0)
+
+/*
+ * local_dec_if_positive - decrement by 1 if old value positive
+ * @l: pointer of type local_t
+ */
+#define local_dec_if_positive(l)       local_sub_if_positive(1, l)
+
+/*
+ * local_add_negative - add and test if negative
+ * @l: pointer of type local_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @l and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define local_add_negative(i,l) (local_add_return(i, (l)) < 0)
+
+/* Use these for per-cpu local_t variables: on some archs they are
  * much more efficient than these naive implementations.  Note they take
  * a variable, not an address.
  */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
 
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
+#define __local_inc(l)         ((l)->a.counter++)
+#define __local_dec(l)         ((l)->a.counter++)
+#define __local_add(i,l)       ((l)->a.counter+=(i))
+#define __local_sub(i,l)       ((l)->a.counter-=(i))
+
+/* Need to disable preemption for the cpu local counters otherwise we could
+   still access a variable of a previous CPU in a non atomic way. */
+#define cpu_local_wrap_v(l)            \
+       ({ local_t res__;               \
+          preempt_disable();           \
+          res__ = (l);                 \
+          preempt_enable();            \
+          res__; })
+#define cpu_local_wrap(l)              \
+       ({ preempt_disable();           \
+          l;                           \
+          preempt_enable(); })         \
+
+#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
 
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
+#define __cpu_local_inc(l)     cpu_local_inc(l)
+#define __cpu_local_dec(l)     cpu_local_dec(l)
+#define __cpu_local_add(i, l)  cpu_local_add((i), (l))
+#define __cpu_local_sub(i, l)  cpu_local_sub((i), (l))
 
-#endif /* _ASM_LOCAL_H */
+#endif /* _ARCH_MIPS_LOCAL_H */
diff --git a/include/asm-mips/mach-au1x00/au1550_spi.h b/include/asm-mips/mach-au1x00/au1550_spi.h
new file mode 100644 (file)
index 0000000..c2f0466
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * au1550_spi.h - au1550 psc spi controller driver - platform data struct
+ */
+
+#ifndef _AU1550_SPI_H_
+#define _AU1550_SPI_H_
+
+struct au1550_spi_info {
+       s16 bus_num;            /* defines which PSC and IRQ to use */
+       u32 mainclk_hz;         /* main input clock frequency of PSC */
+       u16 num_chipselect;     /* number of chipselects supported */
+       void (*activate_cs)(struct au1550_spi_info *spi, int cs, int polarity);
+       void (*deactivate_cs)(struct au1550_spi_info *spi, int cs, int polarity);
+};
+
+#endif
index 0d3295f57a959dfbcd7b25c48ae5f9608ac2254b..27d77d981937008b2e0de983e9f11867c8102c4d 100644 (file)
@@ -387,10 +387,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #include <asm-generic/pgtable.h>
 
 /*
index 290887077e4497cda1812a13da6b24d5fd07d243..3713d256d36958d52d6ac750315f414c3610ff77 100644 (file)
@@ -55,7 +55,7 @@ do {                                                                  \
        if (cpu_has_dsp)                                                \
                __save_dsp(prev);                                       \
        next->thread.emulated_fp = 0;                                   \
-       (last) = resume(prev, next, next->thread_info);                 \
+       (last) = resume(prev, next, task_thread_info(next));            \
        if (cpu_has_dsp)                                                \
                __restore_dsp(current);                                 \
 } while(0)
@@ -201,7 +201,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 }
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 #define __HAVE_ARCH_CMPXCHG 1
 
@@ -262,6 +261,58 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
        return retval;
 }
 
+static inline unsigned long __cmpxchg_u32_local(volatile int * m,
+       unsigned long old, unsigned long new)
+{
+       __u32 retval;
+
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
+               "       bne     %0, %z3, 2f                             \n"
+               "       .set    mips0                                   \n"
+               "       move    $1, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "       sc      $1, %1                                  \n"
+               "       beqzl   $1, 1b                                  \n"
+               "2:                                                     \n"
+               "       .set    pop                                     \n"
+               : "=&r" (retval), "=R" (*m)
+               : "R" (*m), "Jr" (old), "Jr" (new)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               __asm__ __volatile__(
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
+               "       bne     %0, %z3, 2f                             \n"
+               "       .set    mips0                                   \n"
+               "       move    $1, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "       sc      $1, %1                                  \n"
+               "       beqz    $1, 1b                                  \n"
+               "2:                                                     \n"
+               "       .set    pop                                     \n"
+               : "=&r" (retval), "=R" (*m)
+               : "R" (*m), "Jr" (old), "Jr" (new)
+               : "memory");
+       } else {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               retval = *m;
+               if (retval == old)
+                       *m = new;
+               local_irq_restore(flags);       /* implies memory barrier  */
+       }
+
+       return retval;
+}
+
 #ifdef CONFIG_64BIT
 static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
        unsigned long new)
@@ -315,10 +366,62 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
 
        return retval;
 }
+
+static inline unsigned long __cmpxchg_u64_local(volatile int * m,
+       unsigned long old, unsigned long new)
+{
+       __u64 retval;
+
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
+               "       bne     %0, %z3, 2f                             \n"
+               "       move    $1, %z4                                 \n"
+               "       scd     $1, %1                                  \n"
+               "       beqzl   $1, 1b                                  \n"
+               "2:                                                     \n"
+               "       .set    pop                                     \n"
+               : "=&r" (retval), "=R" (*m)
+               : "R" (*m), "Jr" (old), "Jr" (new)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               __asm__ __volatile__(
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
+               "       bne     %0, %z3, 2f                             \n"
+               "       move    $1, %z4                                 \n"
+               "       scd     $1, %1                                  \n"
+               "       beqz    $1, 1b                                  \n"
+               "2:                                                     \n"
+               "       .set    pop                                     \n"
+               : "=&r" (retval), "=R" (*m)
+               : "R" (*m), "Jr" (old), "Jr" (new)
+               : "memory");
+       } else {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               retval = *m;
+               if (retval == old)
+                       *m = new;
+               local_irq_restore(flags);       /* implies memory barrier  */
+       }
+
+       return retval;
+}
+
 #else
 extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
        volatile int * m, unsigned long old, unsigned long new);
 #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
+extern unsigned long __cmpxchg_u64_local_unsupported_on_32bit_kernels(
+       volatile int * m, unsigned long old, unsigned long new);
+#define __cmpxchg_u64_local __cmpxchg_u64_local_unsupported_on_32bit_kernels
 #endif
 
 /* This function doesn't exist, so you'll get a linker error
@@ -338,7 +441,26 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
        return old;
 }
 
-#define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
+static inline unsigned long __cmpxchg_local(volatile void * ptr,
+       unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_local(ptr, old, new);
+       case 8:
+               return __cmpxchg_u64_local(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,old,new) \
+       ((__typeof__(*(ptr)))__cmpxchg((ptr), \
+               (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
+
+#define cmpxchg_local(ptr,old,new) \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \
+               (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
 
 extern void set_handler (unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
index 7d57d34fcca8a969e520e4817b04cfe641506857..e894ee35074b05c0890692584ecf4c85bcc2128e 100644 (file)
@@ -163,7 +163,7 @@ static __inline__ int atomic_read(const atomic_t *v)
 }
 
 /* exported interface */
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
@@ -175,14 +175,21 @@ static __inline__ int atomic_read(const atomic_t *v)
  * Atomically adds @a to @v, so long as it was not @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_add(i,v)        ((void)(__atomic_add_return( ((int)i),(v))))
@@ -270,6 +277,37 @@ atomic64_read(const atomic64_t *v)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return(v) == 0)
 #define atomic64_sub_and_test(i,v)     (atomic64_sub_return((i),(v)) == 0)
 
+/* exported interface */
+#define atomic64_cmpxchg(v, o, n) \
+       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #endif /* CONFIG_64BIT */
 
 #include <asm-generic/atomic.h>
index fe8579023531d5a8e8788eea06c7f672f161fa36..11f4222597a067c1f9c41b60b222078d0bf4dfc9 100644 (file)
@@ -152,7 +152,7 @@ static __inline__ void __user *compat_alloc_user_space(long len)
 
 static inline int __is_compat_task(struct task_struct *t)
 {
-       return test_ti_thread_flag(t->thread_info, TIF_32BIT);
+       return test_ti_thread_flag(task_thread_info(t), TIF_32BIT);
 }
 
 static inline int is_compat_task(void)
diff --git a/include/asm-parisc/kdebug.h b/include/asm-parisc/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index d0f550912755baa8eae049aaf7d460c9308cff65..c11c530f74d02877738b3b6edb5d59102a9bf01c 100644 (file)
@@ -1,40 +1 @@
-#ifndef _ARCH_PARISC_LOCAL_H
-#define _ARCH_PARISC_LOCAL_H
-
-#include <linux/percpu.h>
-#include <asm/atomic.h>
-
-typedef atomic_long_t local_t;
-
-#define LOCAL_INIT(i)  ATOMIC_LONG_INIT(i)
-#define local_read(v)  atomic_long_read(v)
-#define local_set(v,i) atomic_long_set(v,i)
-
-#define local_inc(v)   atomic_long_inc(v)
-#define local_dec(v)   atomic_long_dec(v)
-#define local_add(i, v)        atomic_long_add(i, v)
-#define local_sub(i, v)        atomic_long_sub(i, v)
-
-#define __local_inc(v)         ((v)->counter++)
-#define __local_dec(v)         ((v)->counter--)
-#define __local_add(i,v)       ((v)->counter+=(i))
-#define __local_sub(i,v)       ((v)->counter-=(i))
-
-/* Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
-
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
-
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
-
-#endif /* _ARCH_PARISC_LOCAL_H */
+#include <asm-generic/local.h>
index d7e1b10da5c62bdebc0124380ff74965305ab054..beb2adb979d9d65afb7dd74f4a810b724bc9cc74 100644 (file)
@@ -528,10 +528,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 
 #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_NO_CACHE)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /* We provide our own get_unmapped_area to provide cache coherency */
 
 #define HAVE_ARCH_UNMAPPED_AREA
index 2ce4b6b7b34887456961fdc9227a184bcec535b8..c44810b9d3224dbc54474b4a6cb7eab5a2a9af3d 100644 (file)
@@ -11,6 +11,7 @@ typedef struct { volatile int counter; } atomic_t;
 #include <linux/compiler.h>
 #include <asm/synch.h>
 #include <asm/asm-compat.h>
+#include <asm/system.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 
@@ -165,8 +166,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
        return t;
 }
 
-#define atomic_cmpxchg(v, o, n) \
-       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
@@ -414,8 +414,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
        return t;
 }
 
-#define atomic64_cmpxchg(v, o, n) \
-       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
index 8f757f6246e4effe36e790c811dd0b7939f4d875..8144a2788db67bc101e47b20545d8fecf03ded35 100644 (file)
@@ -39,7 +39,6 @@
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
 #include <asm/asm-compat.h>
 #include <asm/synch.h>
 
index b2e56b30306a4eacd253c863d896fb824c3ffc0f..870967e47204e32642106b61702eb4580be1e69e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <asm/machdep.h>
 #include <asm/types.h>
 #include <asm/bitops.h>
 
@@ -109,6 +110,19 @@ static inline void pci_iommu_init(void) { }
 #endif
 
 extern void alloc_dart_table(void);
+#if defined(CONFIG_PPC64) && defined(CONFIG_PM)
+static inline void iommu_save(void)
+{
+       if (ppc_md.iommu_save)
+               ppc_md.iommu_save();
+}
+
+static inline void iommu_restore(void)
+{
+       if (ppc_md.iommu_restore)
+               ppc_md.iommu_restore();
+}
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IOMMU_H */
index 532bfee934f43328912e5d88045197feba350da7..295f0162c60827a750664b9ece653d134f1a277f 100644 (file)
@@ -6,20 +6,19 @@
 
 #include <linux/notifier.h>
 
-struct pt_regs;
-
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation.  Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
 extern struct atomic_notifier_head powerpc_die_chain;
 
 /* Grossly misnamed. */
@@ -29,14 +28,7 @@ enum die_val {
        DIE_DABR_MATCH,
        DIE_BPT,
        DIE_SSTEP,
-       DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
-{
-       struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
-       return atomic_notifier_call_chain(&powerpc_die_chain, val, &args);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KDEBUG_H */
index 11cbdf81fd2e8f5113f1359660ce1f16eb1add91..b6f817b8ba3d3528cb500ffeed16879bcc5fcb2c 100644 (file)
@@ -108,8 +108,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
                                        struct pt_regs *oldregs) { }
 #endif /* !__powerpc64 __ */
 
-#define MAX_NOTE_BYTES 1024
-
 extern void kexec_smp_wait(void);      /* get and clear naca physid, wait for
                                          master to copy new code to 0 */
 extern int crashing_cpu;
index f850ca7020ed4becd50d98a85742f536d7a94805..b0e40ff32ee02208378657196d294584b14f3c9f 100644 (file)
@@ -64,6 +64,12 @@ typedef unsigned int kprobe_opcode_t;
                                addr = *(kprobe_opcode_t **)addr;       \
                } else if (name[0] != '.')                              \
                        addr = *(kprobe_opcode_t **)addr;               \
+       } else {                                                        \
+               char dot_name[KSYM_NAME_LEN+1];                         \
+               dot_name[0] = '.';                                      \
+               dot_name[1] = '\0';                                     \
+               strncat(dot_name, name, KSYM_NAME_LEN);                 \
+               addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
        }                                                               \
 }
 
@@ -110,5 +116,6 @@ struct kprobe_ctlblk {
 
 extern int kprobe_exceptions_notify(struct notifier_block *self,
                                        unsigned long val, void *data);
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KPROBES_H */
index c11c530f74d02877738b3b6edb5d59102a9bf01c..612d8327665351c43b39dcd41e5323178ecc6f60 100644 (file)
@@ -1 +1,200 @@
-#include <asm-generic/local.h>
+#ifndef _ARCH_POWERPC_LOCAL_H
+#define _ARCH_POWERPC_LOCAL_H
+
+#include <linux/percpu.h>
+#include <asm/atomic.h>
+
+typedef struct
+{
+       atomic_long_t a;
+} local_t;
+
+#define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
+
+#define local_read(l)  atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set(&(l)->a, (i))
+
+#define local_add(i,l) atomic_long_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
+#define local_inc(l)   atomic_long_inc(&(l)->a)
+#define local_dec(l)   atomic_long_dec(&(l)->a)
+
+static __inline__ long local_add_return(long a, local_t *l)
+{
+       long t;
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX       "%0,0,%2                # local_add_return\n\
+       add     %0,%1,%0\n"
+       PPC405_ERR77(0,%2)
+       PPC_STLCX       "%0,0,%2 \n\
+       bne-    1b"
+       : "=&r" (t)
+       : "r" (a), "r" (&(l->a.counter))
+       : "cc", "memory");
+
+       return t;
+}
+
+#define local_add_negative(a, l)       (local_add_return((a), (l)) < 0)
+
+static __inline__ long local_sub_return(long a, local_t *l)
+{
+       long t;
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX       "%0,0,%2                # local_sub_return\n\
+       subf    %0,%1,%0\n"
+       PPC405_ERR77(0,%2)
+       PPC_STLCX       "%0,0,%2 \n\
+       bne-    1b"
+       : "=&r" (t)
+       : "r" (a), "r" (&(l->a.counter))
+       : "cc", "memory");
+
+       return t;
+}
+
+static __inline__ long local_inc_return(local_t *l)
+{
+       long t;
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX       "%0,0,%1                # local_inc_return\n\
+       addic   %0,%0,1\n"
+       PPC405_ERR77(0,%1)
+       PPC_STLCX       "%0,0,%1 \n\
+       bne-    1b"
+       : "=&r" (t)
+       : "r" (&(l->a.counter))
+       : "cc", "memory");
+
+       return t;
+}
+
+/*
+ * local_inc_and_test - increment and test
+ * @l: pointer of type local_t
+ *
+ * Atomically increments @l by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define local_inc_and_test(l) (local_inc_return(l) == 0)
+
+static __inline__ long local_dec_return(local_t *l)
+{
+       long t;
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX       "%0,0,%1                # local_dec_return\n\
+       addic   %0,%0,-1\n"
+       PPC405_ERR77(0,%1)
+       PPC_STLCX       "%0,0,%1\n\
+       bne-    1b"
+       : "=&r" (t)
+       : "r" (&(l->a.counter))
+       : "cc", "memory");
+
+       return t;
+}
+
+#define local_cmpxchg(l, o, n) \
+       (cmpxchg_local(&((l)->a.counter), (o), (n)))
+#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n)))
+
+/**
+ * local_add_unless - add unless the number is a given value
+ * @l: pointer of type local_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @l, so long as it was not @u.
+ * Returns non-zero if @l was not @u, and zero otherwise.
+ */
+static __inline__ int local_add_unless(local_t *l, long a, long u)
+{
+       long t;
+
+       __asm__ __volatile__ (
+"1:"   PPC_LLARX       "%0,0,%1                # local_add_unless\n\
+       cmpw    0,%0,%3 \n\
+       beq-    2f \n\
+       add     %0,%2,%0 \n"
+       PPC405_ERR77(0,%2)
+       PPC_STLCX       "%0,0,%1 \n\
+       bne-    1b \n"
+"      subf    %0,%2,%0 \n\
+2:"
+       : "=&r" (t)
+       : "r" (&(l->a.counter)), "r" (a), "r" (u)
+       : "cc", "memory");
+
+       return t != u;
+}
+
+#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+
+#define local_sub_and_test(a, l)       (local_sub_return((a), (l)) == 0)
+#define local_dec_and_test(l)          (local_dec_return((l)) == 0)
+
+/*
+ * Atomically test *l and decrement if it is greater than 0.
+ * The function returns the old value of *l minus 1.
+ */
+static __inline__ long local_dec_if_positive(local_t *l)
+{
+       long t;
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX       "%0,0,%1                # local_dec_if_positive\n\
+       cmpwi   %0,1\n\
+       addi    %0,%0,-1\n\
+       blt-    2f\n"
+       PPC405_ERR77(0,%1)
+       PPC_STLCX       "%0,0,%1\n\
+       bne-    1b"
+       "\n\
+2:"    : "=&b" (t)
+       : "r" (&(l->a.counter))
+       : "cc", "memory");
+
+       return t;
+}
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations.  Note they take
+ * a variable, not an address.
+ */
+
+#define __local_inc(l)         ((l)->a.counter++)
+#define __local_dec(l)         ((l)->a.counter++)
+#define __local_add(i,l)       ((l)->a.counter+=(i))
+#define __local_sub(i,l)       ((l)->a.counter-=(i))
+
+/* Need to disable preemption for the cpu local counters otherwise we could
+   still access a variable of a previous CPU in a non atomic way. */
+#define cpu_local_wrap_v(l)            \
+       ({ local_t res__;               \
+          preempt_disable();           \
+          res__ = (l);                 \
+          preempt_enable();            \
+          res__; })
+#define cpu_local_wrap(l)              \
+       ({ preempt_disable();           \
+          l;                           \
+          preempt_enable(); })         \
+
+#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
+
+#define __cpu_local_inc(l)     cpu_local_inc(l)
+#define __cpu_local_dec(l)     cpu_local_dec(l)
+#define __cpu_local_add(i, l)  cpu_local_add((i), (l))
+#define __cpu_local_sub(i, l)  cpu_local_sub((i), (l))
+
+#endif /* _ARCH_POWERPC_LOCAL_H */
index b204926ce91348a296618c8e350ce0f292136246..6cf1a831f550835692c2d06f63e10b540524adba 100644 (file)
@@ -91,6 +91,11 @@ struct machdep_calls {
        void __iomem *  (*ioremap)(phys_addr_t addr, unsigned long size,
                                   unsigned long flags);
        void            (*iounmap)(volatile void __iomem *token);
+
+#ifdef CONFIG_PM
+       void            (*iommu_save)(void);
+       void            (*iommu_restore)(void);
+#endif
 #endif /* CONFIG_PPC64 */
 
        int             (*probe)(void);
@@ -115,6 +120,14 @@ struct machdep_calls {
        /* To setup PHBs when using automatic OF platform driver for PCI */
        int             (*pci_setup_phb)(struct pci_controller *host);
 
+#ifdef CONFIG_PCI_MSI
+       int             (*msi_check_device)(struct pci_dev* dev,
+                                           int nvec, int type);
+       int             (*setup_msi_irqs)(struct pci_dev *dev,
+                                         int nvec, int type);
+       void            (*teardown_msi_irqs)(struct pci_dev *dev);
+#endif
+
        void            (*restart)(char *cmd);
        void            (*power_off)(void);
        void            (*halt)(void);
@@ -240,14 +253,10 @@ struct machdep_calls {
         */
        void (*machine_kexec)(struct kimage *image);
 #endif /* CONFIG_KEXEC */
-
-#ifdef CONFIG_PCI_MSI
-       int (*enable_msi)(struct pci_dev *pdev);
-       void (*disable_msi)(struct pci_dev *pdev);
-#endif /* CONFIG_PCI_MSI */
 };
 
 extern void power4_idle(void);
+extern void power4_cpu_offline_powersave(void);
 extern void ppc6xx_idle(void);
 
 /*
diff --git a/include/asm-powerpc/mmu-44x.h b/include/asm-powerpc/mmu-44x.h
new file mode 100644 (file)
index 0000000..d5ce7a8
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _ASM_POWERPC_MMU_44X_H_
+#define _ASM_POWERPC_MMU_44X_H_
+/*
+ * PPC440 support
+ */
+
+#define PPC44x_MMUCR_TID       0x000000ff
+#define PPC44x_MMUCR_STS       0x00010000
+
+#define        PPC44x_TLB_PAGEID       0
+#define        PPC44x_TLB_XLAT         1
+#define        PPC44x_TLB_ATTRIB       2
+
+/* Page identification fields */
+#define PPC44x_TLB_EPN_MASK    0xfffffc00      /* Effective Page Number */
+#define        PPC44x_TLB_VALID        0x00000200      /* Valid flag */
+#define PPC44x_TLB_TS          0x00000100      /* Translation address space */
+#define PPC44x_TLB_1K          0x00000000      /* Page sizes */
+#define PPC44x_TLB_4K          0x00000010
+#define PPC44x_TLB_16K         0x00000020
+#define PPC44x_TLB_64K         0x00000030
+#define PPC44x_TLB_256K                0x00000040
+#define PPC44x_TLB_1M          0x00000050
+#define PPC44x_TLB_16M         0x00000070
+#define        PPC44x_TLB_256M         0x00000090
+
+/* Translation fields */
+#define PPC44x_TLB_RPN_MASK    0xfffffc00      /* Real Page Number */
+#define        PPC44x_TLB_ERPN_MASK    0x0000000f
+
+/* Storage attribute and access control fields */
+#define PPC44x_TLB_ATTR_MASK   0x0000ff80
+#define PPC44x_TLB_U0          0x00008000      /* User 0 */
+#define PPC44x_TLB_U1          0x00004000      /* User 1 */
+#define PPC44x_TLB_U2          0x00002000      /* User 2 */
+#define PPC44x_TLB_U3          0x00001000      /* User 3 */
+#define PPC44x_TLB_W           0x00000800      /* Caching is write-through */
+#define PPC44x_TLB_I           0x00000400      /* Caching is inhibited */
+#define PPC44x_TLB_M           0x00000200      /* Memory is coherent */
+#define PPC44x_TLB_G           0x00000100      /* Memory is guarded */
+#define PPC44x_TLB_E           0x00000080      /* Memory is guarded */
+
+#define PPC44x_TLB_PERM_MASK   0x0000003f
+#define PPC44x_TLB_UX          0x00000020      /* User execution */
+#define PPC44x_TLB_UW          0x00000010      /* User write */
+#define PPC44x_TLB_UR          0x00000008      /* User read */
+#define PPC44x_TLB_SX          0x00000004      /* Super execution */
+#define PPC44x_TLB_SW          0x00000002      /* Super write */
+#define PPC44x_TLB_SR          0x00000001      /* Super read */
+
+/* Number of TLB entries */
+#define PPC44x_TLB_SIZE                64
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long long phys_addr_t;
+
+extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t);
+
+typedef struct {
+       unsigned long id;
+       unsigned long vdso_base;
+} mm_context_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#ifndef CONFIG_PPC_EARLY_DEBUG_44x
+#define PPC44x_EARLY_TLBS      1
+#else
+#define PPC44x_EARLY_TLBS      2
+#define PPC44x_EARLY_DEBUG_VIRTADDR    (ASM_CONST(0xf0000000) \
+       | (ASM_CONST(CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW) & 0xffff))
+#endif
+
+/* Size of the TLBs used for pinning in lowmem */
+#define PPC_PIN_SIZE   (1 << 28)       /* 256M */
+
+#endif /* _ASM_POWERPC_MMU_44X_H_ */
index 6739457d8bc02aa3fbf45935c967a70be668e369..e2ca55bcfe0b64de87c79e00a36430738980a0ff 100644 (file)
@@ -350,10 +350,13 @@ typedef unsigned long mm_context_id_t;
 
 typedef struct {
        mm_context_id_t id;
-       u16 user_psize;                 /* page size index */
-       u16 sllp;                       /* SLB entry page size encoding */
-#ifdef CONFIG_HUGETLB_PAGE
-       u16 low_htlb_areas, high_htlb_areas;
+       u16 user_psize;         /* page size index */
+
+#ifdef CONFIG_PPC_MM_SLICES
+       u64 low_slices_psize;   /* SLB page size encodings */
+       u64 high_slices_psize;  /* 4 bits per slice for now */
+#else
+       u16 sllp;               /* SLB page size encoding */
 #endif
        unsigned long vdso_base;
 } mm_context_t;
index 06b3e6d336cbad8a72732bb34836dc3edda8152b..fe510fff89078e36a365543c406fff9a9d630fa8 100644 (file)
@@ -5,9 +5,12 @@
 #ifdef CONFIG_PPC64
 /* 64-bit classic hash table MMU */
 #  include <asm/mmu-hash64.h>
+#elif defined(CONFIG_44x)
+/* 44x-style software loaded TLB */
+#  include <asm/mmu-44x.h>
 #else
-/* 32-bit.  FIXME: split up the 32-bit MMU types, and revise for
- * arch/powerpc */
+/* Other 32-bit.  FIXME: split up the other 32-bit MMU types, and
+ * revise for arch/powerpc */
 #  include <asm-ppc/mmu.h>
 #endif
 
index 7afd5bf945288f2ac73580cefd4951d309537fc2..c4631f6dd4f970be98c4609857511347f45211b7 100644 (file)
@@ -253,5 +253,16 @@ extern int __init mpc52xx_add_bridge(struct device_node *node);
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_PM
+struct mpc52xx_suspend {
+       void (*board_suspend_prepare)(void __iomem *mbar);
+       void (*board_resume_finish)(void __iomem *mbar);
+};
+
+extern struct mpc52xx_suspend mpc52xx_suspend;
+extern int __init mpc52xx_pm_init(void);
+extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level);
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_POWERPC_MPC52xx_H__ */
 
index e4d5fc5362a02e3389fc75f3d5fd9710fc0488ea..2ffb06abe881c703d98347ee3bf9c0f0528a35c2 100644 (file)
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #include <linux/irq.h>
+#include <linux/sysdev.h>
 #include <asm/dcr.h>
 
 /*
@@ -228,6 +229,14 @@ struct mpic_reg_bank {
 #endif /* CONFIG_PPC_DCR */
 };
 
+struct mpic_irq_save {
+       u32             vecprio,
+                       dest;
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+       u32             fixup_data;
+#endif
+};
+
 /* The instance data of a given MPIC */
 struct mpic
 {
@@ -292,8 +301,19 @@ struct mpic
        u32                     *hw_set;
 #endif
 
+#ifdef CONFIG_PCI_MSI
+       spinlock_t              bitmap_lock;
+       unsigned long           *hwirq_bitmap;
+#endif
+
        /* link */
        struct mpic             *next;
+
+       struct sys_device       sysdev;
+
+#ifdef CONFIG_PM
+       struct mpic_irq_save    *save_data;
+#endif
 };
 
 /*
index 4f1aabe0ce7305cdfcb12f8c2d276894d929408d..e9af49eb1aa85060bc63f5773bf9a5bd8bde32db 100644 (file)
@@ -32,6 +32,8 @@ extern int of_device_register(struct of_device *ofdev);
 extern void of_device_unregister(struct of_device *ofdev);
 extern void of_release_dev(struct device *dev);
 
+extern ssize_t of_device_get_modalias(struct of_device *ofdev,
+                                       char *str, ssize_t len);
 extern int of_device_uevent(struct device *dev,
        char **envp, int num_envp, char *buffer, int buffer_size);
 
index cf95274f735e43ea3e9120b9697e0b0be75177bf..c6a5b173566676c5d5bef92336f687c95bc13142 100644 (file)
@@ -83,8 +83,8 @@ struct paca_struct {
 
        mm_context_t context;
        u16 vmalloc_sllp;
-       u16 slb_cache[SLB_CACHE_ENTRIES];
        u16 slb_cache_ptr;
+       u16 slb_cache[SLB_CACHE_ENTRIES];
 
        /*
         * then miscellaneous read-write fields
index b4d38b0b15f8389b897b0b63f4ef1cb57672aef2..10c51f457d4887c1e89f9803e1c0e63355f4da6a 100644 (file)
@@ -121,6 +121,7 @@ typedef struct { pte_t pte; } real_pte_t;
 #endif
 
 /* PMD level */
+#ifdef CONFIG_PPC64
 typedef struct { unsigned long pmd; } pmd_t;
 #define pmd_val(x)     ((x).pmd)
 #define __pmd(x)       ((pmd_t) { (x) })
@@ -130,7 +131,8 @@ typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pud; } pud_t;
 #define pud_val(x)     ((x).pud)
 #define __pud(x)       ((pud_t) { (x) })
-#endif
+#endif /* !CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC64 */
 
 /* PGD level */
 typedef struct { unsigned long pgd; } pgd_t;
@@ -159,15 +161,17 @@ typedef unsigned long real_pte_t;
 #endif
 
 
+#ifdef CONFIG_PPC64
 typedef unsigned long pmd_t;
 #define pmd_val(x)     (x)
 #define __pmd(x)       (x)
 
-#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_64K_PAGES)
+#ifndef CONFIG_PPC_64K_PAGES
 typedef unsigned long pud_t;
 #define pud_val(x)     (x)
 #define __pud(x)       (x)
-#endif
+#endif /* !CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC64 */
 
 typedef unsigned long pgd_t;
 #define pgd_val(x)     (x)
index 07f6d3cf5e5aac4338dc44ce3be37c1660ba2680..374d0db37e1c1babf0ee08d935d5f3888e443f6c 100644 (file)
 #ifdef CONFIG_PTE_64BIT
 typedef unsigned long long pte_basic_t;
 #define PTE_SHIFT      (PAGE_SHIFT - 3)        /* 512 ptes per page */
-#define PTE_FMT                "%16Lx"
 #else
 typedef unsigned long pte_basic_t;
 #define PTE_SHIFT      (PAGE_SHIFT - 2)        /* 1024 ptes per page */
-#define PTE_FMT                "%.8lx"
 #endif
 
 struct page;
index eab779c219958b18b82afd1ff5c55bc5de05f89b..3448a3d4bc64efc74d84a9c3e337a8989b108fd9 100644 (file)
@@ -88,57 +88,55 @@ extern unsigned int HPAGE_SHIFT;
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_PPC_MM_SLICES
 
-#define HTLB_AREA_SHIFT                40
-#define HTLB_AREA_SIZE         (1UL << HTLB_AREA_SHIFT)
-#define GET_HTLB_AREA(x)       ((x) >> HTLB_AREA_SHIFT)
+#define SLICE_LOW_SHIFT                28
+#define SLICE_HIGH_SHIFT       40
 
-#define LOW_ESID_MASK(addr, len)    \
-       (((1U << (GET_ESID(min((addr)+(len)-1, 0x100000000UL))+1)) \
-         - (1U << GET_ESID(min((addr), 0x100000000UL)))) & 0xffff)
-#define HTLB_AREA_MASK(addr, len)   (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \
-                                     - (1U << GET_HTLB_AREA(addr))) & 0xffff)
+#define SLICE_LOW_TOP          (0x100000000ul)
+#define SLICE_NUM_LOW          (SLICE_LOW_TOP >> SLICE_LOW_SHIFT)
+#define SLICE_NUM_HIGH         (PGTABLE_RANGE >> SLICE_HIGH_SHIFT)
 
-#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
-#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
-#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
-#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define GET_LOW_SLICE_INDEX(addr)      ((addr) >> SLICE_LOW_SHIFT)
+#define GET_HIGH_SLICE_INDEX(addr)     ((addr) >> SLICE_HIGH_SHIFT)
 
-#define touches_hugepage_low_range(mm, addr, len) \
-       (((addr) < 0x100000000UL) \
-        && (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas))
-#define touches_hugepage_high_range(mm, addr, len) \
-       ((((addr) + (len)) > 0x100000000UL) \
-         && (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas))
-
-#define __within_hugepage_low_range(addr, len, segmask) \
-       ( (((addr)+(len)) <= 0x100000000UL) \
-         && ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)))
-#define within_hugepage_low_range(addr, len) \
-       __within_hugepage_low_range((addr), (len), \
-                                   current->mm->context.low_htlb_areas)
-#define __within_hugepage_high_range(addr, len, zonemask) \
-       ( ((addr) >= 0x100000000UL) \
-         && ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)))
-#define within_hugepage_high_range(addr, len) \
-       __within_hugepage_high_range((addr), (len), \
-                                   current->mm->context.high_htlb_areas)
-
-#define is_hugepage_only_range(mm, addr, len) \
-       (touches_hugepage_high_range((mm), (addr), (len)) || \
-         touches_hugepage_low_range((mm), (addr), (len)))
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#ifndef __ASSEMBLY__
+
+struct slice_mask {
+       u16 low_slices;
+       u16 high_slices;
+};
+
+struct mm_struct;
 
-#define in_hugepage_area(context, addr) \
-       (cpu_has_feature(CPU_FTR_16M_PAGE) && \
-        ( ( (addr) >= 0x100000000UL) \
-          ? ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) \
-          : ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) )
+extern unsigned long slice_get_unmapped_area(unsigned long addr,
+                                            unsigned long len,
+                                            unsigned long flags,
+                                            unsigned int psize,
+                                            int topdown,
+                                            int use_cache);
 
-#else /* !CONFIG_HUGETLB_PAGE */
+extern unsigned int get_slice_psize(struct mm_struct *mm,
+                                   unsigned long addr);
 
-#define in_hugepage_area(mm, addr)     0
+extern void slice_init_context(struct mm_struct *mm, unsigned int psize);
+extern void slice_set_user_psize(struct mm_struct *mm, unsigned int psize);
+
+#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+extern int is_hugepage_only_range(struct mm_struct *m,
+                                 unsigned long addr,
+                                 unsigned long len);
+
+#endif /* __ASSEMBLY__ */
+#else
+#define slice_init()
+#endif /* CONFIG_PPC_MM_SLICES */
+
+#ifdef CONFIG_HUGETLB_PAGE
+
+#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #endif /* !CONFIG_HUGETLB_PAGE */
 
index b37b81e3727848d66f76a4baa214575c7a187694..414c50e2e8819df9d1cef2e06655801927db6359 100644 (file)
 
 #include <asm/prom.h>
 
-extern struct parport *parport_pc_probe_port (unsigned long int base,
-                                              unsigned long int base_hi,
-                                              int irq, int dma,
-                                              struct pci_dev *dev);
-
 static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
        struct device_node *np;
diff --git a/include/asm-powerpc/pgalloc-32.h b/include/asm-powerpc/pgalloc-32.h
new file mode 100644 (file)
index 0000000..e130743
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _ASM_POWERPC_PGALLOC_32_H
+#define _ASM_POWERPC_PGALLOC_32_H
+
+#include <linux/threads.h>
+
+extern void __bad_pte(pmd_t *pmd);
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(pgd_t *pgd);
+
+/*
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
+ */
+/* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
+#define pmd_free(x)                     do { } while (0)
+#define __pmd_free_tlb(tlb,x)          do { } while (0)
+/* #define pgd_populate(mm, pmd, pte)      BUG() */
+
+#ifndef CONFIG_BOOKE
+#define pmd_populate_kernel(mm, pmd, pte)      \
+               (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT)
+#define pmd_populate(mm, pmd, pte)     \
+               (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT)
+#else
+#define pmd_populate_kernel(mm, pmd, pte)      \
+               (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT)
+#define pmd_populate(mm, pmd, pte)     \
+               (pmd_val(*(pmd)) = (unsigned long)lowmem_page_address(pte) | _PMD_PRESENT)
+#endif
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+extern void pte_free_kernel(pte_t *pte);
+extern void pte_free(struct page *pte);
+
+#define __pte_free_tlb(tlb, pte)       pte_free((pte))
+
+#define check_pgt_cache()      do { } while (0)
+
+#endif /* _ASM_POWERPC_PGALLOC_32_H */
diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
new file mode 100644 (file)
index 0000000..d9a3a8c
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef _ASM_POWERPC_PGALLOC_64_H
+#define _ASM_POWERPC_PGALLOC_64_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.
+ */
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+
+extern struct kmem_cache *pgtable_cache[];
+
+#define PGD_CACHE_NUM          0
+#define PUD_CACHE_NUM          1
+#define PMD_CACHE_NUM          1
+#define HUGEPTE_CACHE_NUM      2
+#define PTE_NONCACHE_NUM       3  /* from GFP rather than kmem_cache */
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+       return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
+}
+
+static inline void pgd_free(pgd_t *pgd)
+{
+       kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
+}
+
+#ifndef CONFIG_PPC_64K_PAGES
+
+#define pgd_populate(MM, PGD, PUD)     pgd_set(PGD, PUD)
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+       return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
+                               GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pud_free(pud_t *pud)
+{
+       kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
+}
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+       pud_set(pud, (unsigned long)pmd);
+}
+
+#define pmd_populate(mm, pmd, pte_page) \
+       pmd_populate_kernel(mm, pmd, page_address(pte_page))
+#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
+
+
+#else /* CONFIG_PPC_64K_PAGES */
+
+#define pud_populate(mm, pud, pmd)     pud_set(pud, (unsigned long)pmd)
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+                                      pte_t *pte)
+{
+       pmd_set(pmd, (unsigned long)pte);
+}
+
+#define pmd_populate(mm, pmd, pte_page) \
+       pmd_populate_kernel(mm, pmd, page_address(pte_page))
+
+#endif /* CONFIG_PPC_64K_PAGES */
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+       return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
+                               GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pmd_free(pmd_t *pmd)
+{
+       kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
+}
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+                                         unsigned long address)
+{
+        return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+                                        unsigned long address)
+{
+       return virt_to_page(pte_alloc_one_kernel(mm, address));
+}
+
+static inline void pte_free_kernel(pte_t *pte)
+{
+       free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct page *ptepage)
+{
+       __free_page(ptepage);
+}
+
+#define PGF_CACHENUM_MASK      0x3
+
+typedef struct pgtable_free {
+       unsigned long val;
+} pgtable_free_t;
+
+static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
+                                               unsigned long mask)
+{
+       BUG_ON(cachenum > PGF_CACHENUM_MASK);
+
+       return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
+}
+
+static inline void pgtable_free(pgtable_free_t pgf)
+{
+       void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
+       int cachenum = pgf.val & PGF_CACHENUM_MASK;
+
+       if (cachenum == PTE_NONCACHE_NUM)
+               free_page((unsigned long)p);
+       else
+               kmem_cache_free(pgtable_cache[cachenum], p);
+}
+
+extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
+
+#define __pte_free_tlb(tlb, ptepage)   \
+       pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
+               PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1))
+#define __pmd_free_tlb(tlb, pmd)       \
+       pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
+               PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
+#ifndef CONFIG_PPC_64K_PAGES
+#define __pud_free_tlb(tlb, pud)       \
+       pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
+               PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
+#endif /* CONFIG_PPC_64K_PAGES */
+
+#define check_pgt_cache()      do { } while (0)
+
+#endif /* _ASM_POWERPC_PGALLOC_64_H */
index b0830db68f8af1a6ad87b6dd6aa87413aa4d0a90..b4505ed0f0f26843c6432a25cec991f16ecd0130 100644 (file)
 #define _ASM_POWERPC_PGALLOC_H
 #ifdef __KERNEL__
 
-#ifndef CONFIG_PPC64
-#include <asm-ppc/pgalloc.h>
+#ifdef CONFIG_PPC64
+#include <asm/pgalloc-64.h>
 #else
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/cpumask.h>
-#include <linux/percpu.h>
-
-extern struct kmem_cache *pgtable_cache[];
-
-#ifdef CONFIG_PPC_64K_PAGES
-#define PTE_CACHE_NUM  0
-#define PMD_CACHE_NUM  1
-#define PGD_CACHE_NUM  2
-#define HUGEPTE_CACHE_NUM 3
-#else
-#define PTE_CACHE_NUM  0
-#define PMD_CACHE_NUM  1
-#define PUD_CACHE_NUM  1
-#define PGD_CACHE_NUM  0
-#define HUGEPTE_CACHE_NUM 2
+#include <asm/pgalloc-32.h>
 #endif
 
-/*
- * 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.
- */
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
-}
-
-static inline void pgd_free(pgd_t *pgd)
-{
-       kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
-}
-
-#ifndef CONFIG_PPC_64K_PAGES
-
-#define pgd_populate(MM, PGD, PUD)     pgd_set(PGD, PUD)
-
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-       return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
-                               GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pud_free(pud_t *pud)
-{
-       kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
-}
-
-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
-{
-       pud_set(pud, (unsigned long)pmd);
-}
-
-#define pmd_populate(mm, pmd, pte_page) \
-       pmd_populate_kernel(mm, pmd, page_address(pte_page))
-#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
-
-
-#else /* CONFIG_PPC_64K_PAGES */
-
-#define pud_populate(mm, pud, pmd)     pud_set(pud, (unsigned long)pmd)
-
-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
-                                      pte_t *pte)
-{
-       pmd_set(pmd, (unsigned long)pte);
-}
-
-#define pmd_populate(mm, pmd, pte_page) \
-       pmd_populate_kernel(mm, pmd, page_address(pte_page))
-
-#endif /* CONFIG_PPC_64K_PAGES */
-
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-       return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
-                               GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pmd_free(pmd_t *pmd)
-{
-       kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
-}
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-                                         unsigned long address)
-{
-       return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM],
-                               GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline struct page *pte_alloc_one(struct mm_struct *mm,
-                                        unsigned long address)
-{
-       return virt_to_page(pte_alloc_one_kernel(mm, address));
-}
-               
-static inline void pte_free_kernel(pte_t *pte)
-{
-       kmem_cache_free(pgtable_cache[PTE_CACHE_NUM], pte);
-}
-
-static inline void pte_free(struct page *ptepage)
-{
-       pte_free_kernel(page_address(ptepage));
-}
-
-#define PGF_CACHENUM_MASK      0x3
-
-typedef struct pgtable_free {
-       unsigned long val;
-} pgtable_free_t;
-
-static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
-                                               unsigned long mask)
-{
-       BUG_ON(cachenum > PGF_CACHENUM_MASK);
-
-       return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
-}
-
-static inline void pgtable_free(pgtable_free_t pgf)
-{
-       void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
-       int cachenum = pgf.val & PGF_CACHENUM_MASK;
-
-       kmem_cache_free(pgtable_cache[cachenum], p);
-}
-
-extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
-
-#define __pte_free_tlb(tlb, ptepage)   \
-       pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
-               PTE_CACHE_NUM, PTE_TABLE_SIZE-1))
-#define __pmd_free_tlb(tlb, pmd)       \
-       pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
-               PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
-#ifndef CONFIG_PPC_64K_PAGES
-#define __pud_free_tlb(tlb, pud)       \
-       pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
-               PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
-#endif /* CONFIG_PPC_64K_PAGES */
-
-#define check_pgt_cache()      do { } while (0)
-
-#endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PGALLOC_H */
index a28fa8bc01da23e06218c0186c63dae61e9457b8..add5481fd7c7ce3436d65b5eee5ec32f245978e2 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef _ASM_POWERPC_PGTABLE_4K_H
+#define _ASM_POWERPC_PGTABLE_4K_H
 /*
  * Entries per page directory level.  The PTE level must use a 64b record
  * for each page table entry.  The PMD and PGD level use a 32b record for
 
 #define pte_iterate_hashed_end() } while(0)
 
-#define pte_pagesize_index(pte)        MMU_PAGE_4K
+#ifdef CONFIG_PPC_HAS_HASH_64K
+#define pte_pagesize_index(mm, addr, pte)      get_slice_psize(mm, addr)
+#else
+#define pte_pagesize_index(mm, addr, pte)      MMU_PAGE_4K
+#endif
 
 /*
  * 4-level page tables related bits
 
 #define remap_4k_pfn(vma, addr, pfn, prot)     \
        remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
+#endif /* _ASM_POWERPC_PGTABLE_4K_H */
index 5e84f070eaf70ef61e960eac97b450d0e0425245..31cbd3d7fce82b24690e4ed4e0fa6a7b84d5ceda 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _ASM_POWERPC_PGTABLE_64K_H
 #define _ASM_POWERPC_PGTABLE_64K_H
-#ifdef __KERNEL__
 
 #include <asm-generic/pgtable-nopud.h>
 
 #define _PAGE_HPTE_SUB0        0x08000000 /* combo only: first sub page */
 #define _PAGE_COMBO    0x10000000 /* this is a combo 4k page */
 #define _PAGE_4K_PFN   0x20000000 /* PFN is for a single 4k page */
+
+/* Note the full page bits must be in the same location as for normal
+ * 4k pages as the same asssembly will be used to insert 64K pages
+ * wether the kernel has CONFIG_PPC_64K_PAGES or not
+ */
 #define _PAGE_F_SECOND  0x00008000 /* full page: hidx bits */
 #define _PAGE_F_GIX     0x00007000 /* full page: hidx bits */
 
@@ -65,8 +69,6 @@
 /* Bits to mask out from a PGD/PUD to get to the PMD page */
 #define PUD_MASKED_BITS                0x1ff
 
-#ifndef __ASSEMBLY__
-
 /* Manipulate "rpte" values */
 #define __real_pte(e,p)        ((real_pte_t) { \
        (e), pte_val(*((p) + PTRS_PER_PTE)) })
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
-#define pte_pagesize_index(pte)        \
+#define pte_pagesize_index(mm, addr, pte)      \
        (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
 #define remap_4k_pfn(vma, addr, pfn, prot)                             \
        remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,                \
                        __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
 
-#endif /*  __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PGTABLE_64K_H */
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
new file mode 100644 (file)
index 0000000..09662a2
--- /dev/null
@@ -0,0 +1,813 @@
+#ifndef _ASM_POWERPC_PGTABLE_PPC32_H
+#define _ASM_POWERPC_PGTABLE_PPC32_H
+
+#include <asm-generic/pgtable-nopmd.h>
+
+#ifndef __ASSEMBLY__
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <asm/processor.h>             /* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/io.h>                    /* For sub-arch specific PPC_PIN_SIZE */
+struct mm_struct;
+
+extern unsigned long va_to_phys(unsigned long address);
+extern pte_t *va_to_pte(unsigned long address);
+extern unsigned long ioremap_bot, ioremap_base;
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The PowerPC MMU uses a hash table containing PTEs, together with
+ * a set of 16 segment registers (on 32-bit implementations), to define
+ * the virtual to physical address mapping.
+ *
+ * We use the hash table as an extended TLB, i.e. a cache of currently
+ * active mappings.  We maintain a two-level page table tree, much
+ * like that used by the i386, for the sake of the Linux memory
+ * management code.  Low-level assembler code in hashtable.S
+ * (procedure hash_page) is responsible for extracting ptes from the
+ * tree and putting them into the hash table when necessary, and
+ * updating the accessed and modified bits in the page table tree.
+ */
+
+/*
+ * The PowerPC MPC8xx uses a TLB with hardware assisted, software tablewalk.
+ * We also use the two level tables, but we can put the real bits in them
+ * needed for the TLB and tablewalk.  These definitions require Mx_CTR.PPM = 0,
+ * Mx_CTR.PPCS = 0, and MD_CTR.TWAM = 1.  The level 2 descriptor has
+ * additional page protection (when Mx_CTR.PPCS = 1) that allows TLB hit
+ * based upon user/super access.  The TLB does not have accessed nor write
+ * protect.  We assume that if the TLB get loaded with an entry it is
+ * accessed, and overload the changed bit for write protect.  We use
+ * two bits in the software pte that are supposed to be set to zero in
+ * the TLB entry (24 and 25) for these indicators.  Although the level 1
+ * descriptor contains the guarded and writethrough/copyback bits, we can
+ * set these at the page level since they get copied from the Mx_TWC
+ * register when the TLB entry is loaded.  We will use bit 27 for guard, since
+ * that is where it exists in the MD_TWC, and bit 26 for writethrough.
+ * These will get masked from the level 2 descriptor at TLB load time, and
+ * copied to the MD_TWC before it gets loaded.
+ * Large page sizes added.  We currently support two sizes, 4K and 8M.
+ * This also allows a TLB hander optimization because we can directly
+ * load the PMD into MD_TWC.  The 8M pages are only used for kernel
+ * mapping of well known areas.  The PMD (PGD) entries contain control
+ * flags in addition to the address, so care must be taken that the
+ * software no longer assumes these are only pointers.
+ */
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully-associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively (see "mmu.h" for definitions).
+ */
+
+/*
+ * The normal case is that PTEs are 32-bits and we have a 1-page
+ * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
+ *
+ * For any >32-bit physical address platform, we can use the following
+ * two level page table layout where the pgdir is 8KB and the MS 13 bits
+ * are an index to the second level table.  The combined pgdir/pmd first
+ * level has 2048 entries and the second level has 512 64-bit PTE entries.
+ * -Matt
+ */
+/* PGDIR_SHIFT determines what a top-level page table entry can map */
+#define PGDIR_SHIFT    (PAGE_SHIFT + PTE_SHIFT)
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK     (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: our page-table tree is two-level, so
+ * we don't really have any PMD directory.
+ */
+#define PTRS_PER_PTE   (1 << PTE_SHIFT)
+#define PTRS_PER_PMD   1
+#define PTRS_PER_PGD   (1 << (32 - PGDIR_SHIFT))
+
+#define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_ADDRESS     0
+
+#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
+               (unsigned long long)pte_val(e))
+#define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 64MB value just means that there will be a 64MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ *
+ * We no longer map larger than phys RAM with the BATs so we don't have
+ * to worry about the VMALLOC_OFFSET causing problems.  We do have to worry
+ * about clashes between our early calls to ioremap() that start growing down
+ * from ioremap_base being run into the VM area allocations (growing upwards
+ * from VMALLOC_START).  For this reason we have ioremap_bot to check when
+ * we actually run into our mappings setup in the early boot with the VM
+ * system.  This really does become a problem for machines with good amounts
+ * of RAM.  -- Cort
+ */
+#define VMALLOC_OFFSET (0x1000000) /* 16M */
+#ifdef PPC_PIN_SIZE
+#define VMALLOC_START (((_ALIGN((long)high_memory, PPC_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
+#else
+#define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
+#endif
+#define VMALLOC_END    ioremap_bot
+
+/*
+ * Bits in a linux-style PTE.  These match the bits in the
+ * (hardware-defined) PowerPC PTE as closely as possible.
+ */
+
+#if defined(CONFIG_40x)
+
+/* There are several potential gotchas here.  The 40x hardware TLBLO
+   field looks like this:
+
+   0  1  2  3  4  ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+   RPN.....................  0  0 EX WR ZSEL.......  W  I  M  G
+
+   Where possible we make the Linux PTE bits match up with this
+
+   - bits 20 and 21 must be cleared, because we use 4k pages (40x can
+     support down to 1k pages), this is done in the TLBMiss exception
+     handler.
+   - We use only zones 0 (for kernel pages) and 1 (for user pages)
+     of the 16 available.  Bit 24-26 of the TLB are cleared in the TLB
+     miss handler.  Bit 27 is PAGE_USER, thus selecting the correct
+     zone.
+   - PRESENT *must* be in the bottom two bits because swap cache
+     entries use the top 30 bits.  Because 40x doesn't support SMP
+     anyway, M is irrelevant so we borrow it for PAGE_PRESENT.  Bit 30
+     is cleared in the TLB miss handler before the TLB entry is loaded.
+   - All other bits of the PTE are loaded into TLBLO without
+     modification, leaving us only the bits 20, 21, 24, 25, 26, 30 for
+     software PTE bits.  We actually use use bits 21, 24, 25, and
+     30 respectively for the software bits: ACCESSED, DIRTY, RW, and
+     PRESENT.
+*/
+
+/* Definitions for 40x embedded chips. */
+#define        _PAGE_GUARDED   0x001   /* G: page is guarded from prefetch */
+#define _PAGE_FILE     0x001   /* when !present: nonlinear file mapping */
+#define _PAGE_PRESENT  0x002   /* software: PTE contains a translation */
+#define        _PAGE_NO_CACHE  0x004   /* I: caching is inhibited */
+#define        _PAGE_WRITETHRU 0x008   /* W: caching is write-through */
+#define        _PAGE_USER      0x010   /* matches one of the zone permission bits */
+#define        _PAGE_RW        0x040   /* software: Writes permitted */
+#define        _PAGE_DIRTY     0x080   /* software: dirty page */
+#define _PAGE_HWWRITE  0x100   /* hardware: Dirty & RW, set in exception */
+#define _PAGE_HWEXEC   0x200   /* hardware: EX permission */
+#define _PAGE_ACCESSED 0x400   /* software: R: page referenced */
+
+#define _PMD_PRESENT   0x400   /* PMD points to page of PTEs */
+#define _PMD_BAD       0x802
+#define _PMD_SIZE      0x0e0   /* size field, != 0 for large-page PMD entry */
+#define _PMD_SIZE_4M   0x0c0
+#define _PMD_SIZE_16M  0x0e0
+#define PMD_PAGE_SIZE(pmdval)  (1024 << (((pmdval) & _PMD_SIZE) >> 4))
+
+#elif defined(CONFIG_44x)
+/*
+ * Definitions for PPC440
+ *
+ * Because of the 3 word TLB entries to support 36-bit addressing,
+ * the attribute are difficult to map in such a fashion that they
+ * are easily loaded during exception processing.  I decided to
+ * organize the entry so the ERPN is the only portion in the
+ * upper word of the PTE and the attribute bits below are packed
+ * in as sensibly as they can be in the area below a 4KB page size
+ * oriented RPN.  This at least makes it easy to load the RPN and
+ * ERPN fields in the TLB. -Matt
+ *
+ * Note that these bits preclude future use of a page size
+ * less than 4KB.
+ *
+ *
+ * PPC 440 core has following TLB attribute fields;
+ *
+ *   TLB1:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   RPN.................................  -  -  -  -  -  - ERPN.......
+ *
+ *   TLB2:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   -  -  -  -  -    - U0 U1 U2 U3 W  I  M  G  E   - UX UW UR SX SW SR
+ *
+ * There are some constrains and options, to decide mapping software bits
+ * into TLB entry.
+ *
+ *   - PRESENT *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - FILE *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - CACHE COHERENT bit (M) has no effect on PPC440 core, because it
+ *     doesn't support SMP. So we can use this as software bit, like
+ *     DIRTY.
+ *
+ * With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used
+ * for memory protection related functions (see PTE structure in
+ * include/asm-ppc/mmu.h).  The _PAGE_XXX definitions in this file map to the
+ * above bits.  Note that the bit values are CPU specific, not architecture
+ * specific.
+ *
+ * The kernel PTE entry holds an arch-dependent swp_entry structure under
+ * certain situations. In other words, in such situations some portion of
+ * the PTE bits are used as a swp_entry. In the PPC implementation, the
+ * 3-24th LSB are shared with swp_entry, however the 0-2nd three LSB still
+ * hold protection values. That means the three protection bits are
+ * reserved for both PTE and SWAP entry at the most significant three
+ * LSBs.
+ *
+ * There are three protection bits available for SWAP entry:
+ *     _PAGE_PRESENT
+ *     _PAGE_FILE
+ *     _PAGE_HASHPTE (if HW has)
+ *
+ * So those three bits have to be inside of 0-2nd LSB of PTE.
+ *
+ */
+
+#define _PAGE_PRESENT  0x00000001              /* S: PTE valid */
+#define        _PAGE_RW        0x00000002              /* S: Write permission */
+#define _PAGE_FILE     0x00000004              /* S: nonlinear file mapping */
+#define _PAGE_ACCESSED 0x00000008              /* S: Page referenced */
+#define _PAGE_HWWRITE  0x00000010              /* H: Dirty & RW */
+#define _PAGE_HWEXEC   0x00000020              /* H: Execute permission */
+#define        _PAGE_USER      0x00000040              /* S: User page */
+#define        _PAGE_ENDIAN    0x00000080              /* H: E bit */
+#define        _PAGE_GUARDED   0x00000100              /* H: G bit */
+#define        _PAGE_DIRTY     0x00000200              /* S: Page dirty */
+#define        _PAGE_NO_CACHE  0x00000400              /* H: I bit */
+#define        _PAGE_WRITETHRU 0x00000800              /* H: W bit */
+
+/* TODO: Add large page lowmem mapping support */
+#define _PMD_PRESENT   0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD       (~PAGE_MASK)
+
+/* ERPN in a PTE never gets cleared, ignore it */
+#define _PTE_NONE_MASK 0xffffffff00000000ULL
+
+#elif defined(CONFIG_FSL_BOOKE)
+/*
+   MMU Assist Register 3:
+
+   32 33 34 35 36  ... 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+   RPN......................  0  0 U0 U1 U2 U3 UX SX UW SW UR SR
+
+   - PRESENT *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+
+   - FILE *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+*/
+
+/* Definitions for FSL Book-E Cores */
+#define _PAGE_PRESENT  0x00001 /* S: PTE contains a translation */
+#define _PAGE_USER     0x00002 /* S: User page (maps to UR) */
+#define _PAGE_FILE     0x00002 /* S: when !present: nonlinear file mapping */
+#define _PAGE_ACCESSED 0x00004 /* S: Page referenced */
+#define _PAGE_HWWRITE  0x00008 /* H: Dirty & RW, set in exception */
+#define _PAGE_RW       0x00010 /* S: Write permission */
+#define _PAGE_HWEXEC   0x00020 /* H: UX permission */
+
+#define _PAGE_ENDIAN   0x00040 /* H: E bit */
+#define _PAGE_GUARDED  0x00080 /* H: G bit */
+#define _PAGE_COHERENT 0x00100 /* H: M bit */
+#define _PAGE_NO_CACHE 0x00200 /* H: I bit */
+#define _PAGE_WRITETHRU        0x00400 /* H: W bit */
+
+#ifdef CONFIG_PTE_64BIT
+#define _PAGE_DIRTY    0x08000 /* S: Page dirty */
+
+/* ERPN in a PTE never gets cleared, ignore it */
+#define _PTE_NONE_MASK 0xffffffffffff0000ULL
+#else
+#define _PAGE_DIRTY    0x00800 /* S: Page dirty */
+#endif
+
+#define _PMD_PRESENT   0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD       (~PAGE_MASK)
+
+#elif defined(CONFIG_8xx)
+/* Definitions for 8xx embedded chips. */
+#define _PAGE_PRESENT  0x0001  /* Page is valid */
+#define _PAGE_FILE     0x0002  /* when !present: nonlinear file mapping */
+#define _PAGE_NO_CACHE 0x0002  /* I: cache inhibit */
+#define _PAGE_SHARED   0x0004  /* No ASID (context) compare */
+
+/* These five software bits must be masked out when the entry is loaded
+ * into the TLB.
+ */
+#define _PAGE_EXEC     0x0008  /* software: i-cache coherency required */
+#define _PAGE_GUARDED  0x0010  /* software: guarded access */
+#define _PAGE_DIRTY    0x0020  /* software: page changed */
+#define _PAGE_RW       0x0040  /* software: user write access allowed */
+#define _PAGE_ACCESSED 0x0080  /* software: page referenced */
+
+/* Setting any bits in the nibble with the follow two controls will
+ * require a TLB exception handler change.  It is assumed unused bits
+ * are always zero.
+ */
+#define _PAGE_HWWRITE  0x0100  /* h/w write enable: never set in Linux PTE */
+#define _PAGE_USER     0x0800  /* One of the PP bits, the other is USER&~RW */
+
+#define _PMD_PRESENT   0x0001
+#define _PMD_BAD       0x0ff0
+#define _PMD_PAGE_MASK 0x000c
+#define _PMD_PAGE_8M   0x000c
+
+/*
+ * The 8xx TLB miss handler allegedly sets _PAGE_ACCESSED in the PTE
+ * for an address even if _PAGE_PRESENT is not set, as a performance
+ * optimization.  This is a bug if you ever want to use swap unless
+ * _PAGE_ACCESSED is 2, which it isn't, or unless you have 8xx-specific
+ * definitions for __swp_entry etc. below, which would be gross.
+ *  -- paulus
+ */
+#define _PTE_NONE_MASK _PAGE_ACCESSED
+
+#else /* CONFIG_6xx */
+/* Definitions for 60x, 740/750, etc. */
+#define _PAGE_PRESENT  0x001   /* software: pte contains a translation */
+#define _PAGE_HASHPTE  0x002   /* hash_page has made an HPTE for this pte */
+#define _PAGE_FILE     0x004   /* when !present: nonlinear file mapping */
+#define _PAGE_USER     0x004   /* usermode access allowed */
+#define _PAGE_GUARDED  0x008   /* G: prohibit speculative access */
+#define _PAGE_COHERENT 0x010   /* M: enforce memory coherence (SMP systems) */
+#define _PAGE_NO_CACHE 0x020   /* I: cache inhibit */
+#define _PAGE_WRITETHRU        0x040   /* W: cache write-through */
+#define _PAGE_DIRTY    0x080   /* C: page changed */
+#define _PAGE_ACCESSED 0x100   /* R: page referenced */
+#define _PAGE_EXEC     0x200   /* software: i-cache coherency required */
+#define _PAGE_RW       0x400   /* software: user write access allowed */
+
+#define _PTE_NONE_MASK _PAGE_HASHPTE
+
+#define _PMD_PRESENT   0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD       (~PAGE_MASK)
+#endif
+
+/*
+ * Some bits are only used on some cpu families...
+ */
+#ifndef _PAGE_HASHPTE
+#define _PAGE_HASHPTE  0
+#endif
+#ifndef _PTE_NONE_MASK
+#define _PTE_NONE_MASK 0
+#endif
+#ifndef _PAGE_SHARED
+#define _PAGE_SHARED   0
+#endif
+#ifndef _PAGE_HWWRITE
+#define _PAGE_HWWRITE  0
+#endif
+#ifndef _PAGE_HWEXEC
+#define _PAGE_HWEXEC   0
+#endif
+#ifndef _PAGE_EXEC
+#define _PAGE_EXEC     0
+#endif
+#ifndef _PMD_PRESENT_MASK
+#define _PMD_PRESENT_MASK      _PMD_PRESENT
+#endif
+#ifndef _PMD_SIZE
+#define _PMD_SIZE      0
+#define PMD_PAGE_SIZE(pmd)     bad_call_to_PMD_PAGE_SIZE()
+#endif
+
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+/*
+ * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
+ * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
+ * to have it in the Linux PTE, and in fact the bit could be reused for
+ * another purpose.  -- paulus.
+ */
+
+#ifdef CONFIG_44x
+#define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
+#else
+#define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED)
+#endif
+#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE)
+#define _PAGE_KERNEL   (_PAGE_BASE | _PAGE_SHARED | _PAGE_WRENABLE)
+
+#ifdef CONFIG_PPC_STD_MMU
+/* On standard PPC MMU, no user access implies kernel read/write access,
+ * so to write-protect kernel memory we must turn on user access */
+#define _PAGE_KERNEL_RO        (_PAGE_BASE | _PAGE_SHARED | _PAGE_USER)
+#else
+#define _PAGE_KERNEL_RO        (_PAGE_BASE | _PAGE_SHARED)
+#endif
+
+#define _PAGE_IO       (_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
+#define _PAGE_RAM      (_PAGE_KERNEL | _PAGE_HWEXEC)
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH)
+/* We want the debuggers to be able to set breakpoints anywhere, so
+ * don't write protect the kernel text */
+#define _PAGE_RAM_TEXT _PAGE_RAM
+#else
+#define _PAGE_RAM_TEXT (_PAGE_KERNEL_RO | _PAGE_HWEXEC)
+#endif
+
+#define PAGE_NONE      __pgprot(_PAGE_BASE)
+#define PAGE_READONLY  __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_READONLY_X        __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_SHARED    __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
+#define PAGE_SHARED_X  __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_COPY      __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X    __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+
+#define PAGE_KERNEL            __pgprot(_PAGE_RAM)
+#define PAGE_KERNEL_NOCACHE    __pgprot(_PAGE_IO)
+
+/*
+ * The PowerPC can only do execute protection on a segment (256MB) basis,
+ * not on a page basis.  So we consider execute permission the same as read.
+ * Also, write permissions imply read permissions.
+ * This is the closest we can get..
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY_X
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY_X
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY_X
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY_X
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY_X
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED_X
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY_X
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED_X
+
+#ifndef __ASSEMBLY__
+/* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a
+ * kernel without large page PMD support */
+extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
+
+/*
+ * Conversions between PTE values and page frame numbers.
+ */
+
+/* in some case we want to additionaly adjust where the pfn is in the pte to
+ * allow room for more flags */
+#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_PTE_64BIT)
+#define PFN_SHIFT_OFFSET       (PAGE_SHIFT + 8)
+#else
+#define PFN_SHIFT_OFFSET       (PAGE_SHIFT)
+#endif
+
+#define pte_pfn(x)             (pte_val(x) >> PFN_SHIFT_OFFSET)
+#define pte_page(x)            pfn_to_page(pte_pfn(x))
+
+#define pfn_pte(pfn, prot)     __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
+                                       pgprot_val(prot))
+#define mk_pte(page, prot)     pfn_pte(page_to_pfn(page), prot)
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[1024];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#endif /* __ASSEMBLY__ */
+
+#define pte_none(pte)          ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
+#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
+#define pte_clear(mm,addr,ptep)        do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
+
+#define pmd_none(pmd)          (!pmd_val(pmd))
+#define        pmd_bad(pmd)            (pmd_val(pmd) & _PMD_BAD)
+#define        pmd_present(pmd)        (pmd_val(pmd) & _PMD_PRESENT_MASK)
+#define        pmd_clear(pmdp)         do { pmd_val(*(pmdp)) = 0; } while (0)
+
+#ifndef __ASSEMBLY__
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
+static inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_EXEC; }
+static inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)          { return pte_val(pte) & _PAGE_FILE; }
+
+static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
+static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+
+static inline pte_t pte_rdprotect(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_USER; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) {
+       pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_exprotect(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_EXEC; return pte; }
+static inline pte_t pte_mkclean(pte_t pte) {
+       pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_mkold(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+
+static inline pte_t pte_mkread(pte_t pte) {
+       pte_val(pte) |= _PAGE_USER; return pte; }
+static inline pte_t pte_mkexec(pte_t pte) {
+       pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) {
+       pte_val(pte) |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) {
+       pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) {
+       pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+       pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+       return pte;
+}
+
+/*
+ * When flushing the tlb entry for a page, we also need to flush the hash
+ * table entry.  flush_hash_pages is assembler (for speed) in hashtable.S.
+ */
+extern int flush_hash_pages(unsigned context, unsigned long va,
+                           unsigned long pmdval, int count);
+
+/* Add an HPTE to the hash table */
+extern void add_hash_page(unsigned context, unsigned long va,
+                         unsigned long pmdval);
+
+/*
+ * Atomic PTE updates.
+ *
+ * pte_update clears and sets bit atomically, and returns
+ * the old pte value.  In the 64-bit PTE case we lock around the
+ * low PTE word since we expect ALL flag bits to be there
+ */
+#ifndef CONFIG_PTE_64BIT
+static inline unsigned long pte_update(pte_t *p, unsigned long clr,
+                                      unsigned long set)
+{
+       unsigned long old, tmp;
+
+       __asm__ __volatile__("\
+1:     lwarx   %0,0,%3\n\
+       andc    %1,%0,%4\n\
+       or      %1,%1,%5\n"
+       PPC405_ERR77(0,%3)
+"      stwcx.  %1,0,%3\n\
+       bne-    1b"
+       : "=&r" (old), "=&r" (tmp), "=m" (*p)
+       : "r" (p), "r" (clr), "r" (set), "m" (*p)
+       : "cc" );
+       return old;
+}
+#else
+static inline unsigned long long pte_update(pte_t *p, unsigned long clr,
+                                      unsigned long set)
+{
+       unsigned long long old;
+       unsigned long tmp;
+
+       __asm__ __volatile__("\
+1:     lwarx   %L0,0,%4\n\
+       lwzx    %0,0,%3\n\
+       andc    %1,%L0,%5\n\
+       or      %1,%1,%6\n"
+       PPC405_ERR77(0,%3)
+"      stwcx.  %1,0,%4\n\
+       bne-    1b"
+       : "=&r" (old), "=&r" (tmp), "=m" (*p)
+       : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
+       : "cc" );
+       return old;
+}
+#endif
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ * On machines which use an MMU hash table we avoid changing the
+ * _PAGE_HASHPTE bit.
+ */
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pte)
+{
+#if _PAGE_HASHPTE != 0
+       pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
+#else
+       *ptep = pte;
+#endif
+}
+
+/*
+ * 2.6 calles this without flushing the TLB entry, this is wrong
+ * for our hash-based implementation, we fix that up here
+ */
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static inline int __ptep_test_and_clear_young(unsigned int context, unsigned long addr, pte_t *ptep)
+{
+       unsigned long old;
+       old = pte_update(ptep, _PAGE_ACCESSED, 0);
+#if _PAGE_HASHPTE != 0
+       if (old & _PAGE_HASHPTE) {
+               unsigned long ptephys = __pa(ptep) & PAGE_MASK;
+               flush_hash_pages(context, addr, ptephys, 1);
+       }
+#endif
+       return (old & _PAGE_ACCESSED) != 0;
+}
+#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
+       __ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
+                                           unsigned long addr, pte_t *ptep)
+{
+       return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
+}
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                                      pte_t *ptep)
+{
+       return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
+}
+
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+                                     pte_t *ptep)
+{
+       pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
+}
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+{
+       unsigned long bits = pte_val(entry) &
+               (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW);
+       pte_update(ptep, 0, bits);
+}
+
+#define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+       do {                                                               \
+               __ptep_set_access_flags(__ptep, __entry, __dirty);         \
+               flush_tlb_page_nohash(__vma, __address);                   \
+       } while(0)
+
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+#define __HAVE_ARCH_PTE_SAME
+#define pte_same(A,B)  (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
+
+/*
+ * Note that on Book E processors, the pmd contains the kernel virtual
+ * (lowmem) address of the pte page.  The physical address is less useful
+ * because everything runs with translation enabled (even the TLB miss
+ * handler).  On everything else the pmd contains the physical address
+ * of the pte page.  -- paulus
+ */
+#ifndef CONFIG_BOOKE
+#define pmd_page_vaddr(pmd)    \
+       ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd)          \
+       (mem_map + (pmd_val(pmd) >> PAGE_SHIFT))
+#else
+#define pmd_page_vaddr(pmd)    \
+       ((unsigned long) (pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd)          \
+       (mem_map + (__pa(pmd_val(pmd)) >> PAGE_SHIFT))
+#endif
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(address)      ((address) >> PGDIR_SHIFT)
+#define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
+
+/* Find an entry in the third-level page table.. */
+#define pte_index(address)             \
+       (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, addr)   \
+       ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
+#define pte_offset_map(dir, addr)              \
+       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
+#define pte_offset_map_nested(dir, addr)       \
+       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
+
+#define pte_unmap(pte)         kunmap_atomic(pte, KM_PTE0)
+#define pte_unmap_nested(pte)  kunmap_atomic(pte, KM_PTE1)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+extern void paging_init(void);
+
+/*
+ * Encode and decode a swap entry.
+ * Note that the bits we use in a PTE for representing a swap entry
+ * must not include the _PAGE_PRESENT bit, the _PAGE_FILE bit, or the
+ *_PAGE_HASHPTE bit (if used).  -- paulus
+ */
+#define __swp_type(entry)              ((entry).val & 0x1f)
+#define __swp_offset(entry)            ((entry).val >> 5)
+#define __swp_entry(type, offset)      ((swp_entry_t) { (type) | ((offset) << 5) })
+#define __pte_to_swp_entry(pte)                ((swp_entry_t) { pte_val(pte) >> 3 })
+#define __swp_entry_to_pte(x)          ((pte_t) { (x).val << 3 })
+
+/* Encode and decode a nonlinear file mapping entry */
+#define PTE_FILE_MAX_BITS      29
+#define pte_to_pgoff(pte)      (pte_val(pte) >> 3)
+#define pgoff_to_pte(off)      ((pte_t) { ((off) << 3) | _PAGE_FILE })
+
+/* CONFIG_APUS */
+/* For virtual address to physical address conversion */
+extern void cache_clear(__u32 addr, int length);
+extern void cache_push(__u32 addr, int length);
+extern int mm_end_of_chunk (unsigned long addr, int len);
+extern unsigned long iopa(unsigned long addr);
+extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
+
+/* Values for nocacheflag and cmode */
+/* These are not used by the APUS kernel_map, but prevents
+   compilation errors. */
+#define        KERNELMAP_FULL_CACHING          0
+#define        KERNELMAP_NOCACHE_SER           1
+#define        KERNELMAP_NOCACHE_NONSER        2
+#define        KERNELMAP_NO_COPYBACK           3
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
+                               int nocacheflag, unsigned long *memavailp );
+
+/*
+ * Set cache mode of (kernel space) address range.
+ */
+extern void kernel_set_cachemode (unsigned long address, unsigned long size,
+                                 unsigned int cmode);
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)  (1)
+
+#ifdef CONFIG_PHYS_64BIT
+extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+                       unsigned long paddr, unsigned long size, pgprot_t prot);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                       unsigned long vaddr,
+                                       unsigned long pfn,
+                                       unsigned long size,
+                                       pgprot_t prot)
+{
+       phys_addr_t paddr64 = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
+       return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
+}
+#else
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
+               remap_pfn_range(vma, vaddr, pfn, size, prot)
+#endif
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init()   do { } while (0)
+
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
+                     pmd_t **pmdp);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_PGTABLE_PPC32_H */
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
new file mode 100644 (file)
index 0000000..704c4e6
--- /dev/null
@@ -0,0 +1,492 @@
+#ifndef _ASM_POWERPC_PGTABLE_PPC64_H_
+#define _ASM_POWERPC_PGTABLE_PPC64_H_
+/*
+ * This file contains the functions and defines necessary to modify and use
+ * the ppc64 hashed page table.
+ */
+
+#ifndef __ASSEMBLY__
+#include <linux/stddef.h>
+#include <asm/processor.h>             /* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+struct mm_struct;
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_PPC_64K_PAGES
+#include <asm/pgtable-64k.h>
+#else
+#include <asm/pgtable-4k.h>
+#endif
+
+#define FIRST_USER_ADDRESS     0
+
+/*
+ * Size of EA range mapped by our pagetables.
+ */
+#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
+                           PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
+#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+
+#if TASK_SIZE_USER64 > PGTABLE_RANGE
+#error TASK_SIZE_USER64 exceeds pagetable range
+#endif
+
+#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#error TASK_SIZE_USER64 exceeds user VSID range
+#endif
+
+/*
+ * Define the address range of the vmalloc VM area.
+ */
+#define VMALLOC_START ASM_CONST(0xD000000000000000)
+#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
+#define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
+
+/*
+ * Define the address range of the imalloc VM area.
+ */
+#define PHBS_IO_BASE   VMALLOC_END
+#define IMALLOC_BASE   (PHBS_IO_BASE + 0x80000000ul)   /* Reserve 2 gigs for PHBs */
+#define IMALLOC_END    (VMALLOC_START + PGTABLE_RANGE)
+
+/*
+ * Region IDs
+ */
+#define REGION_SHIFT           60UL
+#define REGION_MASK            (0xfUL << REGION_SHIFT)
+#define REGION_ID(ea)          (((unsigned long)(ea)) >> REGION_SHIFT)
+
+#define VMALLOC_REGION_ID      (REGION_ID(VMALLOC_START))
+#define KERNEL_REGION_ID       (REGION_ID(PAGE_OFFSET))
+#define USER_REGION_ID         (0UL)
+
+/*
+ * Common bits in a linux-style PTE.  These match the bits in the
+ * (hardware-defined) PowerPC PTE as closely as possible. Additional
+ * bits may be defined in pgtable-*.h
+ */
+#define _PAGE_PRESENT  0x0001 /* software: pte contains a translation */
+#define _PAGE_USER     0x0002 /* matches one of the PP bits */
+#define _PAGE_FILE     0x0002 /* (!present only) software: pte holds file offset */
+#define _PAGE_EXEC     0x0004 /* No execute on POWER4 and newer (we invert) */
+#define _PAGE_GUARDED  0x0008
+#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */
+#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */
+#define _PAGE_WRITETHRU        0x0040 /* W: cache write-through */
+#define _PAGE_DIRTY    0x0080 /* C: page changed */
+#define _PAGE_ACCESSED 0x0100 /* R: page referenced */
+#define _PAGE_RW       0x0200 /* software: user write access allowed */
+#define _PAGE_HASHPTE  0x0400 /* software: pte has an associated HPTE */
+#define _PAGE_BUSY     0x0800 /* software: PTE & hash are busy */
+
+#define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
+
+#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY)
+
+/* __pgprot defined in asm-powerpc/page.h */
+#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+
+#define PAGE_SHARED    __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER)
+#define PAGE_SHARED_X  __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_COPY      __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X    __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_READONLY  __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_READONLY_X        __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_KERNEL    __pgprot(_PAGE_BASE | _PAGE_WRENABLE)
+#define PAGE_KERNEL_CI __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                              _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
+#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC)
+
+#define PAGE_AGP       __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
+#define HAVE_PAGE_AGP
+
+/* PTEIDX nibble */
+#define _PTEIDX_SECONDARY      0x8
+#define _PTEIDX_GROUP_IX       0x7
+
+
+/*
+ * POWER4 and newer have per page execute protection, older chips can only
+ * do this on a segment (256MB) basis.
+ *
+ * Also, write permissions imply read permissions.
+ * This is the closest we can get..
+ *
+ * Note due to the way vm flags are laid out, the bits are XWR
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY_X
+#define __P101 PAGE_READONLY_X
+#define __P110 PAGE_COPY_X
+#define __P111 PAGE_COPY_X
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY_X
+#define __S101 PAGE_READONLY_X
+#define __S110 PAGE_SHARED_X
+#define __S111 PAGE_SHARED_X
+
+#ifndef __ASSEMBLY__
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_HUGETLB_PAGE
+
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
+#endif
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ *
+ * mk_pte takes a (struct page *) as input
+ */
+#define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
+
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
+{
+       pte_t pte;
+
+
+       pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot);
+       return pte;
+}
+
+#define pte_modify(_pte, newprot) \
+  (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
+
+#define pte_none(pte)          ((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0)
+#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
+
+/* pte_clear moved to later in this file */
+
+#define pte_pfn(x)             ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT)))
+#define pte_page(x)            pfn_to_page(pte_pfn(x))
+
+#define PMD_BAD_BITS           (PTE_TABLE_SIZE-1)
+#define PUD_BAD_BITS           (PMD_TABLE_SIZE-1)
+
+#define pmd_set(pmdp, pmdval)  (pmd_val(*(pmdp)) = (pmdval))
+#define pmd_none(pmd)          (!pmd_val(pmd))
+#define        pmd_bad(pmd)            (!is_kernel_addr(pmd_val(pmd)) \
+                                || (pmd_val(pmd) & PMD_BAD_BITS))
+#define        pmd_present(pmd)        (pmd_val(pmd) != 0)
+#define        pmd_clear(pmdp)         (pmd_val(*(pmdp)) = 0)
+#define pmd_page_vaddr(pmd)    (pmd_val(pmd) & ~PMD_MASKED_BITS)
+#define pmd_page(pmd)          virt_to_page(pmd_page_vaddr(pmd))
+
+#define pud_set(pudp, pudval)  (pud_val(*(pudp)) = (pudval))
+#define pud_none(pud)          (!pud_val(pud))
+#define        pud_bad(pud)            (!is_kernel_addr(pud_val(pud)) \
+                                || (pud_val(pud) & PUD_BAD_BITS))
+#define pud_present(pud)       (pud_val(pud) != 0)
+#define pud_clear(pudp)                (pud_val(*(pudp)) = 0)
+#define pud_page_vaddr(pud)    (pud_val(pud) & ~PUD_MASKED_BITS)
+#define pud_page(pud)          virt_to_page(pud_page_vaddr(pud))
+
+#define pgd_set(pgdp, pudp)    ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
+
+/*
+ * Find an entry in a page-table-directory.  We combine the address region
+ * (the high order N bits) and the pgd portion of the address.
+ */
+/* to avoid overflow in free_pgtables we don't use PTRS_PER_PGD here */
+#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x1ff)
+
+#define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
+
+#define pmd_offset(pudp,addr) \
+  (((pmd_t *) pud_page_vaddr(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
+
+#define pte_offset_kernel(dir,addr) \
+  (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+#define pte_offset_map(dir,addr)       pte_offset_kernel((dir), (addr))
+#define pte_offset_map_nested(dir,addr)        pte_offset_kernel((dir), (addr))
+#define pte_unmap(pte)                 do { } while(0)
+#define pte_unmap_nested(pte)          do { } while(0)
+
+/* to find an entry in a kernel page-table-directory */
+/* This now only contains the vmalloc pages */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER;}
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
+static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC;}
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
+
+static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
+static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+
+static inline pte_t pte_rdprotect(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_USER; return pte; }
+static inline pte_t pte_exprotect(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_EXEC; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) {
+       pte_val(pte) &= ~(_PAGE_RW); return pte; }
+static inline pte_t pte_mkclean(pte_t pte) {
+       pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
+static inline pte_t pte_mkold(pte_t pte) {
+       pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkread(pte_t pte) {
+       pte_val(pte) |= _PAGE_USER; return pte; }
+static inline pte_t pte_mkexec(pte_t pte) {
+       pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) {
+       pte_val(pte) |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) {
+       pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) {
+       pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) {
+       return pte; }
+
+/* Atomic PTE updates */
+static inline unsigned long pte_update(struct mm_struct *mm,
+                                      unsigned long addr,
+                                      pte_t *ptep, unsigned long clr,
+                                      int huge)
+{
+       unsigned long old, tmp;
+
+       __asm__ __volatile__(
+       "1:     ldarx   %0,0,%3         # pte_update\n\
+       andi.   %1,%0,%6\n\
+       bne-    1b \n\
+       andc    %1,%0,%4 \n\
+       stdcx.  %1,0,%3 \n\
+       bne-    1b"
+       : "=&r" (old), "=&r" (tmp), "=m" (*ptep)
+       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
+       : "cc" );
+
+       if (old & _PAGE_HASHPTE)
+               hpte_need_flush(mm, addr, ptep, old, huge);
+       return old;
+}
+
+static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
+                                             unsigned long addr, pte_t *ptep)
+{
+       unsigned long old;
+
+               if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
+               return 0;
+       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
+       return (old & _PAGE_ACCESSED) != 0;
+}
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define ptep_test_and_clear_young(__vma, __addr, __ptep)                  \
+({                                                                        \
+       int __r;                                                           \
+       __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
+       __r;                                                               \
+})
+
+/*
+ * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
+ * moment we always flush but we need to fix hpte_update and test if the
+ * optimisation is worth it.
+ */
+static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
+                                             unsigned long addr, pte_t *ptep)
+{
+       unsigned long old;
+
+               if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
+               return 0;
+       old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0);
+       return (old & _PAGE_DIRTY) != 0;
+}
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define ptep_test_and_clear_dirty(__vma, __addr, __ptep)                  \
+({                                                                        \
+       int __r;                                                           \
+       __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
+       __r;                                                               \
+})
+
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+                                     pte_t *ptep)
+{
+       unsigned long old;
+
+               if ((pte_val(*ptep) & _PAGE_RW) == 0)
+                       return;
+       old = pte_update(mm, addr, ptep, _PAGE_RW, 0);
+}
+
+/*
+ * We currently remove entries from the hashtable regardless of whether
+ * the entry was young or dirty. The generic routines only flush if the
+ * entry was young or dirty which is not good enough.
+ *
+ * We should be more intelligent about this but for the moment we override
+ * these functions and force a tlb flush unconditionally
+ */
+#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+#define ptep_clear_flush_young(__vma, __address, __ptep)               \
+({                                                                     \
+       int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
+                                                 __ptep);              \
+       __young;                                                        \
+})
+
+#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+#define ptep_clear_flush_dirty(__vma, __address, __ptep)               \
+({                                                                     \
+       int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
+                                                 __ptep);              \
+       __dirty;                                                        \
+})
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+                                      unsigned long addr, pte_t *ptep)
+{
+       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
+       return __pte(old);
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+                            pte_t * ptep)
+{
+       pte_update(mm, addr, ptep, ~0UL, 0);
+}
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ */
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pte)
+{
+       if (pte_present(*ptep))
+               pte_clear(mm, addr, ptep);
+       pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
+       *ptep = pte;
+}
+
+/* Set the dirty and/or accessed bits atomically in a linux PTE, this
+ * function doesn't need to flush the hash entry
+ */
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+{
+       unsigned long bits = pte_val(entry) &
+               (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
+       unsigned long old, tmp;
+
+       __asm__ __volatile__(
+       "1:     ldarx   %0,0,%4\n\
+               andi.   %1,%0,%6\n\
+               bne-    1b \n\
+               or      %0,%3,%0\n\
+               stdcx.  %0,0,%4\n\
+               bne-    1b"
+       :"=&r" (old), "=&r" (tmp), "=m" (*ptep)
+       :"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
+       :"cc");
+}
+#define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+       do {                                                               \
+               __ptep_set_access_flags(__ptep, __entry, __dirty);         \
+               flush_tlb_page_nohash(__vma, __address);                   \
+       } while(0)
+
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+#define __HAVE_ARCH_PTE_SAME
+#define pte_same(A,B)  (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
+
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+       printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+extern pgd_t swapper_pg_dir[];
+
+extern void paging_init(void);
+
+/* Encode and de-code a swap entry */
+#define __swp_type(entry)      (((entry).val >> 1) & 0x3f)
+#define __swp_offset(entry)    ((entry).val >> 8)
+#define __swp_entry(type, offset) ((swp_entry_t){((type)<< 1)|((offset)<<8)})
+#define __pte_to_swp_entry(pte)        ((swp_entry_t){pte_val(pte) >> PTE_RPN_SHIFT})
+#define __swp_entry_to_pte(x)  ((pte_t) { (x).val << PTE_RPN_SHIFT })
+#define pte_to_pgoff(pte)      (pte_val(pte) >> PTE_RPN_SHIFT)
+#define pgoff_to_pte(off)      ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
+#define PTE_FILE_MAX_BITS      (BITS_PER_LONG - PTE_RPN_SHIFT)
+
+/*
+ * kern_addr_valid is intended to indicate whether an address is a valid
+ * kernel address.  Most 32-bit archs define it as always true (like this)
+ * but most 64-bit archs actually perform a test.  What should we do here?
+ * The only use is in fs/ncpfs/dir.c
+ */
+#define kern_addr_valid(addr)  (1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
+               remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+void pgtable_cache_init(void);
+
+/*
+ * find_linux_pte returns the address of a linux pte for a given
+ * effective address and directory.  If not found, it returns zero.
+ */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
+{
+       pgd_t *pg;
+       pud_t *pu;
+       pmd_t *pm;
+       pte_t *pt = NULL;
+
+       pg = pgdir + pgd_index(ea);
+       if (!pgd_none(*pg)) {
+               pu = pud_offset(pg, ea);
+               if (!pud_none(*pu)) {
+                       pm = pmd_offset(pu, ea);
+                       if (pmd_present(*pm))
+                               pt = pte_offset_kernel(pm, ea);
+               }
+       }
+       return pt;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */
index 19edb6982b81ca1194a34578a7fb3cb1bedfc803..78bf4ae712a67ef4e6b00f8fca0859354ad1c102 100644 (file)
 #define _ASM_POWERPC_PGTABLE_H
 #ifdef __KERNEL__
 
-#ifndef CONFIG_PPC64
-#include <asm-ppc/pgtable.h>
+#if defined(CONFIG_PPC64)
+#  include <asm/pgtable-ppc64.h>
 #else
-
-/*
- * This file contains the functions and defines necessary to modify and use
- * the ppc64 hashed page table.
- */
-
-#ifndef __ASSEMBLY__
-#include <linux/stddef.h>
-#include <asm/processor.h>             /* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-struct mm_struct;
-#endif /* __ASSEMBLY__ */
-
-#ifdef CONFIG_PPC_64K_PAGES
-#include <asm/pgtable-64k.h>
-#else
-#include <asm/pgtable-4k.h>
-#endif
-
-#define FIRST_USER_ADDRESS     0
-
-/*
- * Size of EA range mapped by our pagetables.
- */
-#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
-                           PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
-
-#if TASK_SIZE_USER64 > PGTABLE_RANGE
-#error TASK_SIZE_USER64 exceeds pagetable range
-#endif
-
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
-#error TASK_SIZE_USER64 exceeds user VSID range
+#  include <asm/pgtable-ppc32.h>
 #endif
 
-/*
- * Define the address range of the vmalloc VM area.
- */
-#define VMALLOC_START ASM_CONST(0xD000000000000000)
-#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
-#define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
-
-/*
- * Define the address range of the imalloc VM area.
- */
-#define PHBS_IO_BASE   VMALLOC_END
-#define IMALLOC_BASE   (PHBS_IO_BASE + 0x80000000ul)   /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END    (VMALLOC_START + PGTABLE_RANGE)
-
-/*
- * Region IDs
- */
-#define REGION_SHIFT           60UL
-#define REGION_MASK            (0xfUL << REGION_SHIFT)
-#define REGION_ID(ea)          (((unsigned long)(ea)) >> REGION_SHIFT)
-
-#define VMALLOC_REGION_ID      (REGION_ID(VMALLOC_START))
-#define KERNEL_REGION_ID       (REGION_ID(PAGE_OFFSET))
-#define USER_REGION_ID         (0UL)
-
-/*
- * Common bits in a linux-style PTE.  These match the bits in the
- * (hardware-defined) PowerPC PTE as closely as possible. Additional
- * bits may be defined in pgtable-*.h
- */
-#define _PAGE_PRESENT  0x0001 /* software: pte contains a translation */
-#define _PAGE_USER     0x0002 /* matches one of the PP bits */
-#define _PAGE_FILE     0x0002 /* (!present only) software: pte holds file offset */
-#define _PAGE_EXEC     0x0004 /* No execute on POWER4 and newer (we invert) */
-#define _PAGE_GUARDED  0x0008
-#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */
-#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */
-#define _PAGE_WRITETHRU        0x0040 /* W: cache write-through */
-#define _PAGE_DIRTY    0x0080 /* C: page changed */
-#define _PAGE_ACCESSED 0x0100 /* R: page referenced */
-#define _PAGE_RW       0x0200 /* software: user write access allowed */
-#define _PAGE_HASHPTE  0x0400 /* software: pte has an associated HPTE */
-#define _PAGE_BUSY     0x0800 /* software: PTE & hash are busy */ 
-
-#define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
-
-#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY)
-
-/* __pgprot defined in asm-powerpc/page.h */
-#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-
-#define PAGE_SHARED    __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER)
-#define PAGE_SHARED_X  __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_COPY      __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X    __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY  __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X        __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_KERNEL    __pgprot(_PAGE_BASE | _PAGE_WRENABLE)
-#define PAGE_KERNEL_CI __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
-                              _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
-#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC)
-
-#define PAGE_AGP       __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
-#define HAVE_PAGE_AGP
-
-/* PTEIDX nibble */
-#define _PTEIDX_SECONDARY      0x8
-#define _PTEIDX_GROUP_IX       0x7
-
-
-/*
- * POWER4 and newer have per page execute protection, older chips can only
- * do this on a segment (256MB) basis.
- *
- * Also, write permissions imply read permissions.
- * This is the closest we can get..
- *
- * Note due to the way vm flags are laid out, the bits are XWR
- */
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY_X
-#define __P101 PAGE_READONLY_X
-#define __P110 PAGE_COPY_X
-#define __P111 PAGE_COPY_X
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY_X
-#define __S101 PAGE_READONLY_X
-#define __S110 PAGE_SHARED_X
-#define __S111 PAGE_SHARED_X
-
 #ifndef __ASSEMBLY__
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#endif /* __ASSEMBLY__ */
-
-#ifdef CONFIG_HUGETLB_PAGE
-
-#define HAVE_ARCH_UNMAPPED_AREA
-#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-
-#endif
-
-#ifndef __ASSEMBLY__
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- *
- * mk_pte takes a (struct page *) as input
- */
-#define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
-
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
-{
-       pte_t pte;
-
-
-       pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot);
-       return pte;
-}
-
-#define pte_modify(_pte, newprot) \
-  (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
-
-#define pte_none(pte)          ((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0)
-#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
-
-/* pte_clear moved to later in this file */
-
-#define pte_pfn(x)             ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT)))
-#define pte_page(x)            pfn_to_page(pte_pfn(x))
-
-#define PMD_BAD_BITS           (PTE_TABLE_SIZE-1)
-#define PUD_BAD_BITS           (PMD_TABLE_SIZE-1)
-
-#define pmd_set(pmdp, pmdval)  (pmd_val(*(pmdp)) = (pmdval))
-#define pmd_none(pmd)          (!pmd_val(pmd))
-#define        pmd_bad(pmd)            (!is_kernel_addr(pmd_val(pmd)) \
-                                || (pmd_val(pmd) & PMD_BAD_BITS))
-#define        pmd_present(pmd)        (pmd_val(pmd) != 0)
-#define        pmd_clear(pmdp)         (pmd_val(*(pmdp)) = 0)
-#define pmd_page_vaddr(pmd)    (pmd_val(pmd) & ~PMD_MASKED_BITS)
-#define pmd_page(pmd)          virt_to_page(pmd_page_vaddr(pmd))
-
-#define pud_set(pudp, pudval)  (pud_val(*(pudp)) = (pudval))
-#define pud_none(pud)          (!pud_val(pud))
-#define        pud_bad(pud)            (!is_kernel_addr(pud_val(pud)) \
-                                || (pud_val(pud) & PUD_BAD_BITS))
-#define pud_present(pud)       (pud_val(pud) != 0)
-#define pud_clear(pudp)                (pud_val(*(pudp)) = 0)
-#define pud_page_vaddr(pud)    (pud_val(pud) & ~PUD_MASKED_BITS)
-#define pud_page(pud)          virt_to_page(pud_page_vaddr(pud))
-
-#define pgd_set(pgdp, pudp)    ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
-
-/* 
- * Find an entry in a page-table-directory.  We combine the address region 
- * (the high order N bits) and the pgd portion of the address.
- */
-/* to avoid overflow in free_pgtables we don't use PTRS_PER_PGD here */
-#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x1ff)
-
-#define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
-
-#define pmd_offset(pudp,addr) \
-  (((pmd_t *) pud_page_vaddr(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
-
-#define pte_offset_kernel(dir,addr) \
-  (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-
-#define pte_offset_map(dir,addr)       pte_offset_kernel((dir), (addr))
-#define pte_offset_map_nested(dir,addr)        pte_offset_kernel((dir), (addr))
-#define pte_unmap(pte)                 do { } while(0)
-#define pte_unmap_nested(pte)          do { } while(0)
-
-/* to find an entry in a kernel page-table-directory */
-/* This now only contains the vmalloc pages */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER;}
-static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
-static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC;}
-static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
-static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
-static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
-
-static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
-static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
-
-static inline pte_t pte_rdprotect(pte_t pte) {
-       pte_val(pte) &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-       pte_val(pte) &= ~_PAGE_EXEC; return pte; }
-static inline pte_t pte_wrprotect(pte_t pte) {
-       pte_val(pte) &= ~(_PAGE_RW); return pte; }
-static inline pte_t pte_mkclean(pte_t pte) {
-       pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
-static inline pte_t pte_mkold(pte_t pte) {
-       pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
-       pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-       pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
-static inline pte_t pte_mkwrite(pte_t pte) {
-       pte_val(pte) |= _PAGE_RW; return pte; }
-static inline pte_t pte_mkdirty(pte_t pte) {
-       pte_val(pte) |= _PAGE_DIRTY; return pte; }
-static inline pte_t pte_mkyoung(pte_t pte) {
-       pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkhuge(pte_t pte) {
-       return pte; }
-
-/* Atomic PTE updates */
-static inline unsigned long pte_update(struct mm_struct *mm,
-                                      unsigned long addr,
-                                      pte_t *ptep, unsigned long clr,
-                                      int huge)
-{
-       unsigned long old, tmp;
-
-       __asm__ __volatile__(
-       "1:     ldarx   %0,0,%3         # pte_update\n\
-       andi.   %1,%0,%6\n\
-       bne-    1b \n\
-       andc    %1,%0,%4 \n\
-       stdcx.  %1,0,%3 \n\
-       bne-    1b"
-       : "=&r" (old), "=&r" (tmp), "=m" (*ptep)
-       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
-       : "cc" );
-
-       if (old & _PAGE_HASHPTE)
-               hpte_need_flush(mm, addr, ptep, old, huge);
-       return old;
-}
-
-static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
-                                             unsigned long addr, pte_t *ptep)
-{
-       unsigned long old;
-
-               if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
-               return 0;
-       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
-       return (old & _PAGE_ACCESSED) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define ptep_test_and_clear_young(__vma, __addr, __ptep)                  \
-({                                                                        \
-       int __r;                                                           \
-       __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
-       __r;                                                               \
-})
-
-/*
- * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
- * moment we always flush but we need to fix hpte_update and test if the
- * optimisation is worth it.
- */
-static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
-                                             unsigned long addr, pte_t *ptep)
-{
-       unsigned long old;
-
-               if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
-               return 0;
-       old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0);
-       return (old & _PAGE_DIRTY) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __addr, __ptep)                  \
-({                                                                        \
-       int __r;                                                           \
-       __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
-       __r;                                                               \
-})
-
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
-                                     pte_t *ptep)
-{
-       unsigned long old;
-
-               if ((pte_val(*ptep) & _PAGE_RW) == 0)
-                       return;
-       old = pte_update(mm, addr, ptep, _PAGE_RW, 0);
-}
-
-/*
- * We currently remove entries from the hashtable regardless of whether
- * the entry was young or dirty. The generic routines only flush if the
- * entry was young or dirty which is not good enough.
- *
- * We should be more intelligent about this but for the moment we override
- * these functions and force a tlb flush unconditionally
- */
-#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define ptep_clear_flush_young(__vma, __address, __ptep)               \
-({                                                                     \
-       int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
-                                                 __ptep);              \
-       __young;                                                        \
-})
-
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep)               \
-({                                                                     \
-       int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
-                                                 __ptep);              \
-       __dirty;                                                        \
-})
-
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-                                      unsigned long addr, pte_t *ptep)
-{
-       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
-       return __pte(old);
-}
-
-static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
-                            pte_t * ptep)
-{
-       pte_update(mm, addr, ptep, ~0UL, 0);
-}
-
-/*
- * set_pte stores a linux PTE into the linux page table.
- */
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-                             pte_t *ptep, pte_t pte)
-{
-       if (pte_present(*ptep))
-               pte_clear(mm, addr, ptep);
-       pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
-       *ptep = pte;
-}
-
-/* Set the dirty and/or accessed bits atomically in a linux PTE, this
- * function doesn't need to flush the hash entry
- */
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
-{
-       unsigned long bits = pte_val(entry) &
-               (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
-       unsigned long old, tmp;
-
-       __asm__ __volatile__(
-       "1:     ldarx   %0,0,%4\n\
-               andi.   %1,%0,%6\n\
-               bne-    1b \n\
-               or      %0,%3,%0\n\
-               stdcx.  %0,0,%4\n\
-               bne-    1b"
-       :"=&r" (old), "=&r" (tmp), "=m" (*ptep)
-       :"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
-       :"cc");
-}
-#define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-       do {                                                               \
-               __ptep_set_access_flags(__ptep, __entry, __dirty);         \
-               flush_tlb_page_nohash(__vma, __address);                   \
-       } while(0)
-
-/*
- * Macro to mark a page protection value as "uncacheable".
- */
-#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
-
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
-                                    unsigned long size, pgprot_t vma_prot);
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-
-#define __HAVE_ARCH_PTE_SAME
-#define pte_same(A,B)  (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
-
-#define pte_ERROR(e) \
-       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-#define pmd_ERROR(e) \
-       printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
-#define pgd_ERROR(e) \
-       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-
-extern pgd_t swapper_pg_dir[];
-
-extern void paging_init(void);
-
-/* Encode and de-code a swap entry */
-#define __swp_type(entry)      (((entry).val >> 1) & 0x3f)
-#define __swp_offset(entry)    ((entry).val >> 8)
-#define __swp_entry(type, offset) ((swp_entry_t){((type)<< 1)|((offset)<<8)})
-#define __pte_to_swp_entry(pte)        ((swp_entry_t){pte_val(pte) >> PTE_RPN_SHIFT})
-#define __swp_entry_to_pte(x)  ((pte_t) { (x).val << PTE_RPN_SHIFT })
-#define pte_to_pgoff(pte)      (pte_val(pte) >> PTE_RPN_SHIFT)
-#define pgoff_to_pte(off)      ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
-#define PTE_FILE_MAX_BITS      (BITS_PER_LONG - PTE_RPN_SHIFT)
-
-/*
- * kern_addr_valid is intended to indicate whether an address is a valid
- * kernel address.  Most 32-bit archs define it as always true (like this)
- * but most 64-bit archs actually perform a test.  What should we do here?
- * The only use is in fs/ncpfs/dir.c
- */
-#define kern_addr_valid(addr)  (1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
-               remap_pfn_range(vma, vaddr, pfn, size, prot)
-
-void pgtable_cache_init(void);
-
-/*
- * find_linux_pte returns the address of a linux pte for a given 
- * effective address and directory.  If not found, it returns zero.
- */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
-{
-       pgd_t *pg;
-       pud_t *pu;
-       pmd_t *pm;
-       pte_t *pt = NULL;
-
-       pg = pgdir + pgd_index(ea);
-       if (!pgd_none(*pg)) {
-               pu = pud_offset(pg, ea);
-               if (!pud_none(*pu)) {
-                       pm = pmd_offset(pu, ea);
-                       if (pmd_present(*pm))
-                               pt = pte_offset_kernel(pm, ea);
-               }
-       }
-       return pt;
-}
-
-
 #include <asm-generic/pgtable.h>
-
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PGTABLE_H */
index d3599cc9aa7486464ca914f7cacaa0adf3c06c65..d43d91beba9b3ed2af3a04e8d549bca5731fa8c0 100644 (file)
@@ -146,7 +146,7 @@ struct device_node;
 static inline long pmac_call_feature(int selector, struct device_node* node,
                                        long param, long value)
 {
-       if (!ppc_md.feature_call)
+       if (!ppc_md.feature_call || !machine_is(powermac))
                return -ENODEV;
        return ppc_md.feature_call(selector, node, param, value);
 }
index d74b2965bb82d007b793a36a593123b0c9cb8e2a..6dcd7a811fe1613ed48d2cffffd4559265092fc2 100644 (file)
@@ -64,7 +64,7 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
  * eeh_slot_error_detail -- record and EEH error condition to the log
  * @severity: 1 if temporary, 2 if permanent failure.
  *
- * Obtains the the EEH error details from the RTAS subsystem,
+ * Obtains the EEH error details from the RTAS subsystem,
  * and then logs these details with the RTAS error log system.
  */
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
index ec400f608e166c6e6a98584d274f8790a4d4918d..6845af93ba91d89be5107f086b9e5034b21da553 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/platform_device.h>
 #include <asm/irq.h>
 #include <asm/atomic.h>
-#include <asm/io.h>
 
 /* Definitions used by the flattened device tree */
 #define OF_DT_HEADER           0xd00dfeed      /* marker */
@@ -334,30 +333,17 @@ extern int of_irq_map_one(struct device_node *device, int index,
 struct pci_dev;
 extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
 
-static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
-{
-       int irq = irq_of_parse_and_map(dev, index);
-
-       /* Only dereference the resource if both the
-        * resource and the irq are valid. */
-       if (r && irq != NO_IRQ) {
-               r->start = r->end = irq;
-               r->flags = IORESOURCE_IRQ;
-       }
-
-       return irq;
-}
-
-static inline void __iomem *of_iomap(struct device_node *np, int index)
-{
-       struct resource res;
-
-       if (of_address_to_resource(np, index, &res))
-               return NULL;
-
-       return ioremap(res.start, 1 + res.end - res.start);
-}
+extern int of_irq_to_resource(struct device_node *dev, int index,
+                       struct resource *r);
 
+/**
+ * of_iomap - Maps the memory mapped IO for a given device_node
+ * @device:    the device whose io range will be mapped
+ * @index:     index of the io range
+ *
+ * Returns a pointer to the mapped memory
+ */
+extern void __iomem *of_iomap(struct device_node *device, int index);
 
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
index 821581a8b643c23e63f55cb517a1cc81a255dfc8..13c372df99e84aafa69256c4fa7af52c14989be8 100644 (file)
@@ -167,26 +167,31 @@ enum ps3_cpu_binding {
        PS3_BINDING_CPU_1 = 1,
 };
 
-int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
        unsigned int *virq);
-int ps3_free_io_irq(unsigned int virq);
-int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq);
-int ps3_free_event_irq(unsigned int virq);
+int ps3_virq_destroy(unsigned int virq);
+int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
+       unsigned int *virq);
+int ps3_irq_plug_destroy(unsigned int virq);
+int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_event_receive_port_destroy(unsigned int virq);
 int ps3_send_event_locally(unsigned int virq);
-int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
-       const struct ps3_device_id *did, unsigned int interrupt_id,
+
+int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
        unsigned int *virq);
-int ps3_disconnect_event_irq(const struct ps3_device_id *did,
-       unsigned int interrupt_id, unsigned int virq);
-int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
+int ps3_io_irq_destroy(unsigned int virq);
+int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
        unsigned int *virq);
-int ps3_free_vuart_irq(unsigned int virq);
-int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
+int ps3_vuart_irq_destroy(unsigned int virq);
+int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
        unsigned int class, unsigned int *virq);
-int ps3_free_spe_irq(unsigned int virq);
-int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
+int ps3_spe_irq_destroy(unsigned int virq);
+
+int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
+       const struct ps3_device_id *did, unsigned int interrupt_id,
        unsigned int *virq);
-int ps3_free_irq(unsigned int virq);
+int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
+       unsigned int interrupt_id, unsigned int virq);
 
 /* lv1 result codes */
 
index 01717f266dc9f1ba07b6cf6723eedfcf17830229..d037f50580e23fbf7c6482903e3ddf4ffc68be17 100644 (file)
@@ -83,6 +83,7 @@ extern void __cpu_die(unsigned int cpu);
 
 #else
 /* for UP */
+#define hard_smp_processor_id()                0
 #define smp_setup_cpu_maps()
 
 #endif /* CONFIG_SMP */
index 02e56a6685a24baf9216336bbe2c3f1c6308829e..c48ae185c8744ecc3a6e57a3c93bb852a039c5f4 100644 (file)
@@ -235,6 +235,12 @@ struct spu_priv2_collapsed {
  */
 struct spu_state {
        struct spu_lscsa *lscsa;
+#ifdef CONFIG_SPU_FS_64K_LS
+       int             use_big_pages;
+       /* One struct page per 64k page */
+#define SPU_LSCSA_NUM_BIG_PAGES        (sizeof(struct spu_lscsa) / 0x10000)
+       struct page     *lscsa_pages[SPU_LSCSA_NUM_BIG_PAGES];
+#endif
        struct spu_problem_collapsed prob;
        struct spu_priv1_collapsed priv1;
        struct spu_priv2_collapsed priv2;
@@ -247,12 +253,14 @@ struct spu_state {
        spinlock_t register_lock;
 };
 
-extern void spu_init_csa(struct spu_state *csa);
+extern int spu_init_csa(struct spu_state *csa);
 extern void spu_fini_csa(struct spu_state *csa);
 extern int spu_save(struct spu_state *prev, struct spu *spu);
 extern int spu_restore(struct spu_state *new, struct spu *spu);
 extern int spu_switch(struct spu_state *prev, struct spu_state *new,
                      struct spu *spu);
+extern int spu_alloc_lscsa(struct spu_state *csa);
+extern void spu_free_lscsa(struct spu_state *csa);
 
 #endif /* !__SPU__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/suspend.h b/include/asm-powerpc/suspend.h
new file mode 100644 (file)
index 0000000..cbf2c94
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __ASM_POWERPC_SUSPEND_H
+#define __ASM_POWERPC_SUSPEND_H
+
+static inline int arch_prepare_suspend(void) { return 0; }
+
+void save_processor_state(void);
+void restore_processor_state(void);
+
+#endif /* __ASM_POWERPC_SUSPEND_H */
index d3e0906ff2bc055bf1df7b566ff293e2faf778c6..09621f611dbc8d018d722edc39f45f5945e8844e 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 
 #include <asm/hw_irq.h>
-#include <asm/atomic.h>
 
 /*
  * Memory barrier.
@@ -227,6 +226,29 @@ __xchg_u32(volatile void *p, unsigned long val)
        return prev;
 }
 
+/*
+ * Atomic exchange
+ *
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+static __inline__ unsigned long
+__xchg_u32_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
 #ifdef CONFIG_PPC64
 static __inline__ unsigned long
 __xchg_u64(volatile void *p, unsigned long val)
@@ -246,6 +268,23 @@ __xchg_u64(volatile void *p, unsigned long val)
 
        return prev;
 }
+
+static __inline__ unsigned long
+__xchg_u64_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stdcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
 #endif
 
 /*
@@ -269,13 +308,32 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size)
        return x;
 }
 
+static __inline__ unsigned long
+__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32_local(ptr, x);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __xchg_u64_local(ptr, x);
+#endif
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
 #define xchg(ptr,x)                                                         \
   ({                                                                        \
      __typeof__(*(ptr)) _x_ = (x);                                          \
      (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
   })
 
-#define tas(ptr) (xchg((ptr),1))
+#define xchg_local(ptr,x)                                                   \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg_local((ptr),                               \
+               (unsigned long)_x_, sizeof(*(ptr)));                         \
+  })
 
 /*
  * Compare and exchange - if *p == old, set it to new,
@@ -306,6 +364,28 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
        return prev;
 }
 
+static __inline__ unsigned long
+__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned int prev;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
 #ifdef CONFIG_PPC64
 static __inline__ unsigned long
 __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
@@ -328,6 +408,27 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
 
        return prev;
 }
+
+static __inline__ unsigned long
+__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
 #endif
 
 /* This function doesn't exist, so you'll get a linker error
@@ -350,6 +451,22 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
        return old;
 }
 
+static __inline__ unsigned long
+__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+         unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_local(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64_local(ptr, old, new);
+#endif
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
 #define cmpxchg(ptr,o,n)                                                \
   ({                                                                    \
      __typeof__(*(ptr)) _o_ = (o);                                      \
@@ -358,6 +475,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
                                    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+
+#define cmpxchg_local(ptr,o,n)                                          \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
 #ifdef CONFIG_PPC64
 /*
  * We handle most unaligned accesses in hardware. On the other hand 
index 4e95d153be8445b4ec1f379d712a402422add1ff..f8b60793b7a908f508904619ad2a8a023f6e82a1 100644 (file)
 #define TSI108_PB_ERRCS_ES             (1 << 1)
 #define TSI108_PB_ISR_PBS_RD_ERR       (1 << 8)
 
-#define TSI108_PCI_CFG_BASE_PHYS       (0xfb000000)
 #define TSI108_PCI_CFG_SIZE            (0x01000000)
+
+/*
+ * PHY Configuration Options
+ *
+ * Specify "bcm54xx" in the compatible property of your device tree phy
+ * nodes if your board uses the Broadcom PHYs
+ */
+#define TSI108_PHY_MV88E       0       /* Marvel 88Exxxx PHY */
+#define TSI108_PHY_BCM54XX     1       /* Broardcom BCM54xx PHY */
+
 /* Global variables */
 
 extern u32 tsi108_pci_cfg_base;
@@ -93,6 +102,7 @@ typedef struct {
        u16 phy;                /* phy address */
        u16 irq_num;            /* irq number */
        u8 mac_addr[6];         /* phy mac address */
+       u16 phy_type;   /* type of phy on board */
 } hw_info;
 
 extern u32 get_vir_csrbase(void);
diff --git a/include/asm-powerpc/tsi108_pci.h b/include/asm-powerpc/tsi108_pci.h
new file mode 100644 (file)
index 0000000..a9f92f7
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2007 IBM Corp
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_PPC_TSI108_PCI_H
+#define _ASM_PPC_TSI108_PCI_H
+
+#include <asm/tsi108.h>
+
+/* Register definitions */
+#define TSI108_PCI_P2O_BAR0 (TSI108_PCI_OFFSET + 0x10)
+#define TSI108_PCI_P2O_BAR0_UPPER (TSI108_PCI_OFFSET + 0x14)
+#define TSI108_PCI_P2O_BAR2 (TSI108_PCI_OFFSET + 0x18)
+#define TSI108_PCI_P2O_BAR2_UPPER (TSI108_PCI_OFFSET + 0x1c)
+#define TSI108_PCI_P2O_PAGE_SIZES (TSI108_PCI_OFFSET + 0x4c)
+#define TSI108_PCI_PFAB_BAR0 (TSI108_PCI_OFFSET + 0x204)
+#define TSI108_PCI_PFAB_BAR0_UPPER (TSI108_PCI_OFFSET + 0x208)
+#define TSI108_PCI_PFAB_IO (TSI108_PCI_OFFSET + 0x20c)
+#define TSI108_PCI_PFAB_IO_UPPER (TSI108_PCI_OFFSET + 0x210)
+#define TSI108_PCI_PFAB_MEM32 (TSI108_PCI_OFFSET + 0x214)
+#define TSI108_PCI_PFAB_PFM3 (TSI108_PCI_OFFSET + 0x220)
+#define TSI108_PCI_PFAB_PFM4 (TSI108_PCI_OFFSET + 0x230)
+
+extern int tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary);
+extern void tsi108_pci_int_init(struct device_node *node);
+extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
+extern void tsi108_clear_pci_cfg_error(void);
+
+#endif                         /*  _ASM_PPC_TSI108_PCI_H */
index d03d8557f7069891cc06289024c15cb3bc09178d..ce9d82fb7b68c0cdbf2607f678c73014e0cfc6ae 100644 (file)
@@ -47,6 +47,7 @@ extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
 extern void __init udbg_init_debug_beat(void);
 extern void __init udbg_init_btext(void);
+extern void __init udbg_init_44x_as1(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
index 833a8aff2a80cc7b9f768d701c5adb302beb486e..1ad4eed07fbe0e5ab7c59855663d53c39b778722 100644 (file)
@@ -8,7 +8,7 @@
  *     Macintosh Technology in the Common Hardware Reference Platform
  *     Apple Computer, Inc.
  *
- *     © Copyright 1995 Apple Computer, Inc. All rights reserved.
+ *     Â© Copyright 1995 Apple Computer, Inc. All rights reserved.
  *
  *  It's available online from http://chrp.apple.com/MacTech.pdf.
  *  You can obtain paper copies of this book from computer bookstores or by
diff --git a/include/asm-ppc/kdebug.h b/include/asm-ppc/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index b1fdbf40dba29c9786bdc09148293e49a7573626..bed452d4a5f0b1486990b223f7a1e711ae20ac81 100644 (file)
@@ -827,10 +827,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 /*
  * No page table caches to initialise
  */
index 738943584c017547b765998214cdecb4db235397..d84a3cf4d033682b48dadecd7249b13c8b6419b9 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <linux/kernel.h>
 
-#include <asm/atomic.h>
 #include <asm/hw_irq.h>
 
 /*
@@ -170,7 +169,6 @@ xchg_u32(volatile void *p, unsigned long val)
 extern void __xchg_called_with_bad_pointer(void);
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
index d2d7ad276148970c51c717b210ae94a91dda46f2..04418af08f8511a6eea7c1d0ad09e04b49979e5e 100644 (file)
@@ -8,21 +8,6 @@
 
 struct pt_regs;
 
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-/* Note - you should never unregister because that can race with NMIs.
- * If you really want to do it first unregister - then synchronize_sched
- *  - then free.
- */
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
-
 /*
  * These are only here because kprobes.c wants them to implement a
  * blatant layering violation. Will hopefully go away soon once all
@@ -37,8 +22,6 @@ static inline int unregister_page_fault_notifier(struct notifier_block *nb)
        return 0;
 }
 
-extern struct atomic_notifier_head s390die_chain;
-
 enum die_val {
        DIE_OOPS = 1,
        DIE_BPT,
@@ -54,19 +37,6 @@ enum die_val {
        DIE_NMI_IPI,
 };
 
-static inline int notify_die(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .str = str,
-               .err = err,
-               .trapnr = trap,
-               .signr = sig
-       };
-       return atomic_notifier_call_chain(&s390die_chain, val, &args);
-}
-
 extern void die(const char *, struct pt_regs *, long);
 
 #endif
index 9c35c8ad1afd63ab8b8519a9594cc813f62fa9fd..7592af708b4153975ac3cfc4cc8b1acef19c9c8d 100644 (file)
@@ -34,8 +34,6 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
-#define MAX_NOTE_BYTES 1024
-
 /* Provide a dummy definition to avoid build failures. */
 static inline void crash_setup_regs(struct pt_regs *newregs,
                                        struct pt_regs *oldregs) { }
index 127f72e774197d9bdccb02029b9e01e443cb8c26..74db1dc10a7d60043a182333a5c815a3187a9000 100644 (file)
@@ -120,6 +120,7 @@ extern unsigned long qdio_get_status(int irq);
 #define QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT 0x08 /* no effect on
                                                     adapter interrupts */
 #define QDIO_FLAG_DONT_SIGA 0x10
+#define QDIO_FLAG_PCI_OUT   0x20
 
 extern int do_QDIO(struct ccw_device*, unsigned int flags, 
                   unsigned int queue_number,
index 0a28e6d6ef405f576a63e5012e6bc683ddc2a975..76e424f718c63bb98ca8225b50e02bde5a873353 100644 (file)
@@ -110,6 +110,7 @@ static inline void smp_send_stop(void)
        __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
 }
 
+#define hard_smp_processor_id()                0
 #define smp_cpu_not_running(cpu)       1
 #define smp_setup_cpu_possible_map()   do { } while (0)
 #endif
index 794c36daf06da9e3530ee167a87958cc1672048a..46f925c815aca9918823e4b23607b1e50e833cd4 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
+
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_WARN_ON
 
-#define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
-
 /**
  * _EMIT_BUG_ENTRY
  * %1 - __FILE__
index 4bccd7c032f9c3d2320c8c7735b7fb5a0d02937b..86308aa3973180867a7b30a2f95e43f6137e54c2 100644 (file)
@@ -20,5 +20,6 @@
 #define CPU_HAS_PTEA           0x0020  /* PTEA register */
 #define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
 #define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
+#define CPU_HAS_OP32           0x0100  /* 32-bit instruction support */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */
index 954801b46022ec5fe5bdae0389be708f7d7db5fc..3a66dc458023ecb371e4496664fa9caf67b7cf66 100644 (file)
@@ -26,7 +26,7 @@ enum {
        XMIT_SZ_128BIT,
 };
 
-static unsigned int ts_shift[] __attribute__ ((used)) = {
+static unsigned int ts_shift[] __maybe_unused = {
        [XMIT_SZ_8BIT]          = 0,
        [XMIT_SZ_16BIT]         = 1,
        [XMIT_SZ_32BIT]         = 2,
index 6c90d28331b27d49d094efc4f9348b58435aca3f..71b426a6e482b169d3b532369de5e5207425ab09 100644 (file)
@@ -28,7 +28,7 @@ enum {
 /*
  * The DMA count is defined as the number of bytes to transfer.
  */
-static unsigned int __attribute__ ((used)) ts_shift[] = {
+static unsigned int ts_shift[] __maybe_unused = {
        [XMIT_SZ_8BIT]          = 0,
        [XMIT_SZ_16BIT]         = 1,
        [XMIT_SZ_32BIT]         = 2,
index c135e9cebd9c0c9a74f0479c3e16c1cfd09c38e6..36e26a964765ebcb0bd994d31ffbe742d0d83ef3 100644 (file)
@@ -53,7 +53,7 @@ enum {
 /*
  * The DMA count is defined as the number of bytes to transfer.
  */
-static unsigned int ts_shift[] __attribute__ ((used)) = {
+static unsigned int ts_shift[] __maybe_unused = {
        [XMIT_SZ_64BIT]         = 3,
        [XMIT_SZ_8BIT]          = 0,
        [XMIT_SZ_16BIT]         = 1,
diff --git a/include/asm-sh/dmabrg.h b/include/asm-sh/dmabrg.h
new file mode 100644 (file)
index 0000000..c5edba2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SH7760 DMABRG (USB/Audio) support
+ */
+
+#ifndef _DMABRG_H_
+#define _DMABRG_H_
+
+/* IRQ sources */
+#define DMABRGIRQ_USBDMA       0
+#define DMABRGIRQ_USBDMAERR    1
+#define DMABRGIRQ_A0TXF                2
+#define DMABRGIRQ_A0TXH                3
+#define DMABRGIRQ_A0RXF                4
+#define DMABRGIRQ_A0RXH                5
+#define DMABRGIRQ_A1TXF                6
+#define DMABRGIRQ_A1TXH                7
+#define DMABRGIRQ_A1RXF                8
+#define DMABRGIRQ_A1RXH                9
+
+extern int dmabrg_request_irq(unsigned int, void(*)(void *), void *);
+extern void dmabrg_free_irq(unsigned int);
+
+#endif
index a1089a65bc367ca03958c961878beeb2e412f194..5bdc9d9be3de9cacad4a972338157b890f8fb365 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sh/edosk7705/io.h
+ * include/asm-sh/edosk7705.h
  *
  * Modified version of io_se.h for the EDOSK7705 specific functions.
  *
index ef009baf5a111e1842c01b5f0013b626587b04b5..16578b7c9da12cf3ac7a2100ebaeea7e287fce73 100644 (file)
@@ -3,33 +3,13 @@
 
 #include <linux/notifier.h>
 
-struct pt_regs;
-
-struct die_args {
-       struct pt_regs *regs;
-       int trapnr;
-};
-
-int register_die_notifier(struct notifier_block *nb);
-int unregister_die_notifier(struct notifier_block *nb);
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
-extern struct atomic_notifier_head shdie_chain;
-
 /* Grossly misnamed. */
 enum die_val {
        DIE_TRAP,
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, struct pt_regs *regs,
-                            int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .trapnr = trap,
-       };
+int register_page_fault_notifier(struct notifier_block *nb);
+int unregister_page_fault_notifier(struct notifier_block *nb);
 
-       return atomic_notifier_call_chain(&shdie_chain, val, &args);
-}
 #endif /* __ASM_SH_KDEBUG_H */
index da36a7548601824f1ea4e3d6f5a55a95b046ece7..00f4260ef09b5cbeb0547d7b4daca53ccf407af1 100644 (file)
@@ -26,8 +26,6 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_SH
 
-#define MAX_NOTE_BYTES 1024
-
 static inline void crash_setup_regs(struct pt_regs *newregs,
                                    struct pt_regs *oldregs)
 {
index 888e4529e6fe3c4bb2108f134b8b7674435836c3..18b613c57cf5118a8ea6fc452d0a0230ff4d50bf 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
+#include <linux/quicklist.h>
+#include <asm/page.h>
+
+#define QUICK_PGD 0    /* We preserve special mappings over free */
+#define QUICK_PT 1     /* Other page table pages that are zero on free */
+
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
                                       pte_t *pte)
 {
@@ -13,48 +19,49 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
        set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
 }
 
+static inline void pgd_ctor(void *x)
+{
+       pgd_t *pgd = x;
+
+       memcpy(pgd + USER_PTRS_PER_PGD,
+              swapper_pg_dir + USER_PTRS_PER_PGD,
+              (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+}
+
 /*
  * Allocate and free page tables.
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
-
-       if (pgd) {
-               memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-               memcpy(pgd + USER_PTRS_PER_PGD,
-                      swapper_pg_dir + USER_PTRS_PER_PGD,
-                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-       }
-
-       return pgd;
+       return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-       free_page((unsigned long)pgd);
+       quicklist_free(QUICK_PGD, NULL, pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long address)
 {
-       return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       void *pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       return pg ? virt_to_page(pg) : NULL;
 }
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-       free_page((unsigned long)pte);
+       quicklist_free(QUICK_PT, NULL, pte);
 }
 
 static inline void pte_free(struct page *pte)
 {
-       __free_page(pte);
+       quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
 #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
@@ -66,6 +73,11 @@ static inline void pte_free(struct page *pte)
 
 #define pmd_free(x)                    do { } while (0)
 #define __pmd_free_tlb(tlb,x)          do { } while (0)
-#define check_pgt_cache()              do { } while (0)
+
+static inline void check_pgt_cache(void)
+{
+       quicklist_trim(QUICK_PGD, NULL, 25, 16);
+       quicklist_trim(QUICK_PT, NULL, 25, 16);
+}
 
 #endif /* __ASM_SH_PGALLOC_H */
index 184d7fcaaf107a068f3c5e8967f60a1fd5aaa934..5b523c7e7d99d8b5441d1cd1f979f6faff3aec1a 100644 (file)
@@ -568,10 +568,6 @@ typedef pte_t *pte_addr_t;
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 struct mm_struct;
 
 /*
index 6b5e4ddc073accbdb7133b7831b53303fdccc086..2d712e72c9e5ab9cae0afd1b32a2ab8201e5b792 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sh/snapgear/io.h
+ * include/asm-sh/snapgear.h
  *
  * Modified version of io_se.h for the snapgear-specific functions.
  *
index 127af304865febb1d5605412b5c17bfddc7c9624..82f3e229e62135c2e944e1fbbe5e316744e2c4c1 100644 (file)
@@ -82,16 +82,6 @@ static inline void sched_cacheflush(void)
 }
 #endif
 
-static inline unsigned long tas(volatile int *m)
-{
-       unsigned long retval;
-
-       __asm__ __volatile__ ("tas.b    @%1\n\t"
-                             "movt     %0"
-                             : "=r" (retval): "r" (m): "t", "memory");
-       return retval;
-}
-
 /*
  * A brief note on ctrl_barrier(), the control register write barrier.
  *
@@ -265,6 +255,15 @@ static inline void *set_exception_table_evt(unsigned int evt, void *handler)
        return set_exception_table_vec(evt >> 5, handler);
 }
 
+/*
+ * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
+ */
+#ifdef CONFIG_CPU_SH2A
+extern unsigned int instruction_size(unsigned int insn);
+#else
+#define instruction_size(insn) (2)
+#endif
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */
index 17b5e76a4c3131471599b52bb3aea12ce78aad43..701ba84c7049305dd1e763efe671bfbf15ed9439 100644 (file)
@@ -2,12 +2,14 @@
 #define __ASM_SH_TIMER_H
 
 #include <linux/sysdev.h>
+#include <linux/clocksource.h>
 #include <asm/cpu/timer.h>
 
 struct sys_timer_ops {
        int (*init)(void);
        int (*start)(void);
        int (*stop)(void);
+       cycle_t (*read)(void);
 #ifndef CONFIG_GENERIC_TIME
        unsigned long (*get_offset)(void);
 #endif
@@ -18,29 +20,8 @@ struct sys_timer {
 
        struct sys_device       dev;
        struct sys_timer_ops    *ops;
-
-#ifdef CONFIG_NO_IDLE_HZ
-       struct dyn_tick_timer   *dyn_tick;
-#endif
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-#define DYN_TICK_ENABLED       (1 << 1)
-
-struct dyn_tick_timer {
-       spinlock_t      lock;
-       unsigned int    state;                  /* Current state */
-       int             (*enable)(void);        /* Enables dynamic tick */
-       int             (*disable)(void);       /* Disables dynamic tick */
-       void            (*reprogram)(unsigned long); /* Reprograms the timer */
-       int             (*handler)(int, void *);
-};
-
-void timer_dyn_reprogram(void);
-#else
-#define timer_dyn_reprogram()  do { } while (0)
-#endif
-
 #define TICK_SIZE (tick_nsec / 1000)
 
 extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
@@ -58,5 +39,7 @@ struct sys_timer *get_sys_timer(void);
 
 /* arch/sh/kernel/time.c */
 void handle_timer_tick(void);
+extern unsigned long sh_hpt_frequency;
+extern struct clocksource clocksource_sh;
 
 #endif /* __ASM_SH_TIMER_H */
index 49be50a36b77dc3dc02dad61892100051f030377..af71e379a5eea94097e029e44e555ab5b3c4cd40 100644 (file)
@@ -85,7 +85,7 @@
 #define __NR_sigpending                 73
 #define __NR_sethostname        74
 #define __NR_setrlimit          75
-#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
+#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
 #define __NR_getrusage          77
 #define __NR_gettimeofday       78
 #define __NR_settimeofday       79
 #define __NR_move_pages                317
 #define __NR_getcpu            318
 #define __NR_epoll_pwait       319
+#define __NR_utimensat         320
 
-#define NR_syscalls 320
+#define NR_syscalls 321
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-sh64/kdebug.h b/include/asm-sh64/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 6b97c4cb1d643ca58db1329ea317ad8f5fafcb42..b875482eb592d8dc4ce87b1f1ba83279e8989594 100644 (file)
@@ -485,10 +485,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
index b1598c26fcb088fe06d809540f7f90c3adde171d..5ff94644e8c87f4c47c0a24d5c539a9edcb07231 100644 (file)
@@ -43,8 +43,6 @@ extern struct task_struct *sh64_switch_to(struct task_struct *prev,
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-#define tas(ptr) (xchg((ptr), 1))
-
 extern void __xchg_called_with_bad_pointer(void);
 
 #define mb()   __asm__ __volatile__ ("synco": : :"memory")
index fba92485fdba5fe1ebbaff2569498a4a69eb4b41..404d807673234b630c54a7298b1ea513f9f777ed 100644 (file)
@@ -66,4 +66,8 @@ static inline void sp_enter_debugger(void)
 #define KDEBUG_DUNNO2_OFF   0x8
 #define KDEBUG_TEACH_OFF    0xc
 
+enum die_val {
+       DIE_UNUSED,
+};
+
 #endif /* !(_SPARC_KDEBUG_H) */
index b9da9a600e356339dd146fff14bf54d96e7df3ff..b3f492208fd20168d2615a6bf51ae8a9101f63b3 100644 (file)
@@ -165,6 +165,7 @@ void smp_setup_cpu_possible_map(void);
 
 #else /* SMP */
 
+#define hard_smp_processor_id()                0
 #define smp_setup_cpu_possible_map() do { } while (0)
 
 #endif /* !(SMP) */
index 100c3eaf3c1fe439713ccedab0ea8c0e87459067..8b6d9c9c8b938ab38d2f99d6112adea1ca3c6ee2 100644 (file)
@@ -241,7 +241,6 @@ static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned lon
 }
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 extern void __xchg_called_with_bad_pointer(void);
 
index e43ed1d63a9df15eb9ece97221efa52f60181410..da9bdc5e5526bf287d1ec6c018f1971fa7fe59ea 100644 (file)
 #define __NR_move_pages                307
 #define __NR_getcpu            308
 #define __NR_epoll_pwait       309
+#define __NR_utimensat         310
 
-#define NR_SYSCALLS            310
+#define NR_SYSCALLS            311
 
 #ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
index a7f44408c93bf91ddda8c2d76a57386ed3378e32..854fd3a65acfbfa002aeeae6cc1fef4f7952c284 100644 (file)
@@ -8,7 +8,6 @@ header-y += apb.h
 header-y += asi.h
 header-y += bbc.h
 header-y += bpp.h
-header-y += const.h
 header-y += display7seg.h
 header-y += envctrl.h
 header-y += ipc.h
index 2f0bec26a695df90ec4fee0c07935ec4a3c0f0de..3fb4e1f7f186066d23962ee7c786cd5e7ad93bcd 100644 (file)
@@ -9,6 +9,7 @@
 #define __ARCH_SPARC64_ATOMIC__
 
 #include <linux/types.h>
+#include <asm/system.h>
 
 typedef struct { volatile int counter; } atomic_t;
 typedef struct { volatile __s64 counter; } atomic64_t;
@@ -70,25 +71,47 @@ extern int atomic64_sub_ret(int, atomic64_t *);
 #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
 #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
 
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       for (;;) {                                              \
-               if (unlikely(c == (u)))                         \
-                       break;                                  \
-               old = atomic_cmpxchg((v), c, c + (a));          \
-               if (likely(old == c))                           \
-                       break;                                  \
-               c = old;                                        \
-       }                                                       \
-       likely(c != (u));                                       \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
+#define atomic64_cmpxchg(v, o, n) \
+       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 /* Atomic operations are already serializing */
 #ifdef CONFIG_SMP
 #define smp_mb__before_atomic_dec()    membar_storeload_loadload();
diff --git a/include/asm-sparc64/const.h b/include/asm-sparc64/const.h
deleted file mode 100644 (file)
index 8ad902b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* const.h: Macros for dealing with constants.  */
-
-#ifndef _SPARC64_CONST_H
-#define _SPARC64_CONST_H
-
-/* Some constant macros are used in both assembler and
- * C code.  Therefore we cannot annotate them always with
- * 'UL' and other type specificers unilaterally.  We
- * use the following macros to deal with this.
- */
-
-#ifdef __ASSEMBLY__
-#define _AC(X,Y)       X
-#else
-#define _AC(X,Y)       (X##Y)
-#endif
-
-
-#endif /* !(_SPARC64_CONST_H) */
index 11251bdd00cb46cdda51cd758987588c9d625934..627e3396a5f0c136bf486eada3a6706b76f68486 100644 (file)
@@ -7,19 +7,19 @@
 
 struct pt_regs;
 
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
-extern struct atomic_notifier_head sparc64die_chain;
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation.  Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
 
 extern void bad_trap(struct pt_regs *, long);
 
@@ -31,21 +31,8 @@ enum die_val {
        DIE_DIE,
        DIE_TRAP,
        DIE_TRAP_TL1,
-       DIE_GPF,
        DIE_CALL,
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
-                            long err, int trap, int sig)
-{
-       struct die_args args = { .regs          = regs,
-                                .str           = str,
-                                .err           = err,
-                                .trapnr        = trap,
-                                .signr         = sig };
-
-       return atomic_notifier_call_chain(&sparc64die_chain, val, &args);
-}
-
 #endif
index becc38fa06c5a5c60422c4f4d62efcb1ab4494ce..a331b7b0dff2bd56ef5b6b35d28912838135bee0 100644 (file)
@@ -43,4 +43,5 @@ struct kprobe_ctlblk {
 
 extern int kprobe_exceptions_notify(struct notifier_block *self,
                                    unsigned long val, void *data);
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 #endif /* _SPARC64_KPROBES_H */
index dfde115ac89279a4df0b47006f76b3f15e8a761c..c11c530f74d02877738b3b6edb5d59102a9bf01c 100644 (file)
@@ -1,40 +1 @@
-#ifndef _ARCH_SPARC64_LOCAL_H
-#define _ARCH_SPARC64_LOCAL_H
-
-#include <linux/percpu.h>
-#include <asm/atomic.h>
-
-typedef atomic64_t local_t;
-
-#define LOCAL_INIT(i)  ATOMIC64_INIT(i)
-#define local_read(v)  atomic64_read(v)
-#define local_set(v,i) atomic64_set(v,i)
-
-#define local_inc(v)   atomic64_inc(v)
-#define local_dec(v)   atomic64_dec(v)
-#define local_add(i, v)        atomic64_add(i, v)
-#define local_sub(i, v)        atomic64_sub(i, v)
-
-#define __local_inc(v)         ((v)->counter++)
-#define __local_dec(v)         ((v)->counter--)
-#define __local_add(i,v)       ((v)->counter+=(i))
-#define __local_sub(i,v)       ((v)->counter-=(i))
-
-/* Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
-
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
-
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
-
-#endif /* _ARCH_SPARC64_LOCAL_H */
+#include <asm-generic/local.h>
index e5329c7f5833365d7c59fe29f65ca8d3bd9570e6..79f109840c398dfda74d18d75a2ea1aacffa3c15 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _SPARC64_LSU_H
 #define _SPARC64_LSU_H
 
-#include <asm/const.h>
+#include <linux/const.h>
 
 /* LSU Control Register */
 #define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
index 70af4b6ce136910caa4b72a3aefd43ba56f46705..8abc58f0f9d707b0f79d438b2c238643843539e5 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __MMU_H
 #define __MMU_H
 
+#include <linux/const.h>
 #include <asm/page.h>
-#include <asm/const.h>
 #include <asm/hypervisor.h>
 
 #define CTX_NR_BITS            13
index ff736eafa64d2ecf31576f631b10778582cffde9..7af1077451ffb9d9fd80daf9086109a4ee039482 100644 (file)
@@ -5,7 +5,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm/const.h>
+#include <linux/const.h>
 
 #if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
 #define PAGE_SHIFT   13
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
deleted file mode 100644 (file)
index c008cec..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* pbm.h: UltraSparc PCI controller software state.
- *
- * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef __SPARC64_PBM_H
-#define __SPARC64_PBM_H
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/msi.h>
-
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-#include <asm/iommu.h>
-
-/* The abstraction used here is that there are PCI controllers,
- * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
- * underneath.  Each PCI bus module uses an IOMMU (shared by both
- * PBMs of a controller, or per-PBM), and if a streaming buffer
- * is present, each PCI bus module has it's own. (ie. the IOMMU
- * might be shared between PBMs, the STC is never shared)
- * Furthermore, each PCI bus module controls it's own autonomous
- * PCI bus.
- */
-
-extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask);
-
-#define PCI_STC_FLUSHFLAG_INIT(STC) \
-       (*((STC)->strbuf_flushflag) = 0UL)
-#define PCI_STC_FLUSHFLAG_SET(STC) \
-       (*((STC)->strbuf_flushflag) != 0UL)
-
-/* There can be quite a few ranges and interrupt maps on a PCI
- * segment.  Thus...
- */
-#define PROM_PCIRNG_MAX                64
-#define PROM_PCIIMAP_MAX       64
-
-struct pci_controller_info;
-
-struct pci_pbm_info {
-       /* PCI controller we sit under. */
-       struct pci_controller_info      *parent;
-
-       /* Physical address base of controller registers. */
-       unsigned long                   controller_regs;
-
-       /* Physical address base of PBM registers. */
-       unsigned long                   pbm_regs;
-
-       /* Physical address of DMA sync register, if any.  */
-       unsigned long                   sync_reg;
-
-       /* Opaque 32-bit system bus Port ID. */
-       u32                             portid;
-
-       /* Opaque 32-bit handle used for hypervisor calls.  */
-       u32                             devhandle;
-
-       /* Chipset version information. */
-       int                             chip_type;
-#define PBM_CHIP_TYPE_SABRE            1
-#define PBM_CHIP_TYPE_PSYCHO           2
-#define PBM_CHIP_TYPE_SCHIZO           3
-#define PBM_CHIP_TYPE_SCHIZO_PLUS      4
-#define PBM_CHIP_TYPE_TOMATILLO                5
-       int                             chip_version;
-       int                             chip_revision;
-
-       /* Name used for top-level resources. */
-       char                            *name;
-
-       /* OBP specific information. */
-       struct device_node              *prom_node;
-       u64                             ino_bitmap;
-
-       /* PBM I/O and Memory space resources. */
-       struct resource                 io_space;
-       struct resource                 mem_space;
-
-       /* Base of PCI Config space, can be per-PBM or shared. */
-       unsigned long                   config_space;
-
-       /* State of 66MHz capabilities on this PBM. */
-       int                             is_66mhz_capable;
-       int                             all_devs_66mhz;
-
-#ifdef CONFIG_PCI_MSI
-       /* MSI info.  */
-       u32                             msiq_num;
-       u32                             msiq_ent_count;
-       u32                             msiq_first;
-       u32                             msiq_first_devino;
-       u32                             msi_num;
-       u32                             msi_first;
-       u32                             msi_data_mask;
-       u32                             msix_data_width;
-       u64                             msi32_start;
-       u64                             msi64_start;
-       u32                             msi32_len;
-       u32                             msi64_len;
-       void                            *msi_queues;
-       unsigned long                   *msi_bitmap;
-#endif /* !(CONFIG_PCI_MSI) */
-
-       /* This PBM's streaming buffer. */
-       struct strbuf                   stc;
-
-       /* IOMMU state, potentially shared by both PBM segments. */
-       struct iommu                    *iommu;
-
-       /* Now things for the actual PCI bus probes. */
-       unsigned int                    pci_first_busno;
-       unsigned int                    pci_last_busno;
-       struct pci_bus                  *pci_bus;
-};
-
-struct pci_controller_info {
-       /* List of all PCI controllers. */
-       struct pci_controller_info      *next;
-
-       /* Each controller gets a unique index, used mostly for
-        * error logging purposes.
-        */
-       int                             index;
-
-       /* The PCI bus modules controlled by us. */
-       struct pci_pbm_info             pbm_A;
-       struct pci_pbm_info             pbm_B;
-
-       /* Operations which are controller specific. */
-       void (*scan_bus)(struct pci_controller_info *);
-
-#ifdef CONFIG_PCI_MSI
-       int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
-                            struct msi_desc *entry);
-       void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
-#endif
-
-       /* Now things for the actual PCI bus probes. */
-       struct pci_ops                  *pci_ops;
-       unsigned int                    pci_first_busno;
-       unsigned int                    pci_last_busno;
-};
-
-#endif /* !(__SPARC64_PBM_H) */
index 46705ef47d275fc39dff579129107ba9d638e1e0..9e80ad43b29ccc004cbf952497f5d91711e4ddf1 100644 (file)
 #include <asm-generic/pgtable-nopud.h>
 
 #include <linux/compiler.h>
+#include <linux/const.h>
 #include <asm/types.h>
 #include <asm/spitfire.h>
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/const.h>
 
 /* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
  * The page copy blockops can use 0x2000000 to 0x4000000.
index 49a7924a89abecb0058345c0e83746dc520cd720..f3c45484c63635fef86342942d715ce83ea25c16 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _SPARC64_PSTATE_H
 #define _SPARC64_PSTATE_H
 
-#include <asm/const.h>
+#include <linux/const.h>
 
 /* The V9 PSTATE Register (with SpitFire extensions).
  *
index 2f792c20b53c3124ecf4df43c0b4f21e26abb517..e96137b04a4f6ef75c29ef567acabd1d02101a57 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _SPARC64_SFAFSR_H
 #define _SPARC64_SFAFSR_H
 
-#include <asm/const.h>
+#include <linux/const.h>
 
 /* Spitfire Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
 
index cca54804b72243e216ec4fd051175ec8c8fe735e..869d16fb907bb134dd040dcef05f91806c6b5ff4 100644 (file)
@@ -48,6 +48,7 @@ extern unsigned char boot_cpu_id;
 
 #else
 
+#define hard_smp_processor_id()                0
 #define smp_setup_cpu_possible_map() do { } while (0)
 #define boot_cpu_id    (0)
 
index 32281acb878b3dc82745266ea1c5b6fd1dd87e17..8ba380ec6daa3216de3bd8cfcef6757d93ff1458 100644 (file)
@@ -253,7 +253,6 @@ static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long
 }
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
 
 extern void __xchg_called_with_bad_pointer(void);
 
index e2dcb87e0c6287b117505b075d3f44b8b3b21ed5..fcd627594f4c781452082a4ee79661582b7312e0 100644 (file)
 #define __NR_move_pages                307
 #define __NR_getcpu            308
 #define __NR_epoll_pwait       309
+#define __NR_utimensat         310
 
-#define NR_SYSCALLS            310
+#define NR_SYSCALLS            311
 
 #ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
diff --git a/include/asm-um/cmpxchg.h b/include/asm-um/cmpxchg.h
new file mode 100644 (file)
index 0000000..529376a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_CMPXCHG_H
+#define __UM_CMPXCHG_H
+
+#include "asm/arch/cmpxchg.h"
+
+#endif
diff --git a/include/asm-um/kdebug.h b/include/asm-um/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
diff --git a/include/asm-um/required-features.h b/include/asm-um/required-features.h
new file mode 100644 (file)
index 0000000..dfb967b
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __UM_REQUIRED_FEATURES_H
+#define __UM_REQUIRED_FEATURES_H
+
+/*
+ * Nothing to see, just need something for the i386 and x86_64 asm
+ * headers to include.
+ */
+
+#endif
index ca552261ed1fcee5c3493830d2903e9754bcc3a3..84f8cf29324e8950fd941b38a98fe76eea3a463f 100644 (file)
@@ -24,6 +24,10 @@ extern inline void smp_cpus_done(unsigned int maxcpus)
 
 extern struct task_struct *idle_threads[NR_CPUS];
 
+#else
+
+#define hard_smp_processor_id()                0
+
 #endif
 
 #endif
diff --git a/include/asm-v850/kdebug.h b/include/asm-v850/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index da39916f10b0cc523eb2c0907f8579b5445fdc41..0de2481fd990dcb247e42488be480c8259b40a84 100644 (file)
@@ -76,7 +76,6 @@ static inline int irqs_disabled (void)
 
 #define xchg(ptr, with) \
   ((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr))))
-#define tas(ptr) (xchg ((ptr), 1))
 
 static inline unsigned long __xchg (unsigned long with,
                                    __volatile__ void *ptr, int size)
index 89ad1fc27c8b660f5a1fb022a571ad9868c2bcc8..75a2deffca6808437c4b7c1ec5e08e51a4957a26 100644 (file)
@@ -19,4 +19,3 @@ unifdef-y += mce.h
 unifdef-y += msr.h
 unifdef-y += mtrr.h
 unifdef-y += vsyscall.h
-unifdef-y += const.h
index 706ca4b60000ec2091efa2a45e096a4f5fef0c5e..f2e64634fa48c59a04d70a6d3b2e8e0f55b573cb 100644 (file)
@@ -2,6 +2,7 @@
 #define __ARCH_X86_64_ATOMIC__
 
 #include <asm/alternative.h>
+#include <asm/cmpxchg.h>
 
 /* atomic_t should be 32 bit signed type */
 
@@ -375,8 +376,8 @@ static __inline__ long atomic64_add_return(long i, atomic64_t *v)
        long __i = i;
        __asm__ __volatile__(
                LOCK_PREFIX "xaddq %0, %1;"
-               :"=r"(i)
-               :"m"(v->counter), "0"(i));
+               :"+r" (i), "+m" (v->counter)
+               : : "memory");
        return i + __i;
 }
 
@@ -388,7 +389,10 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
 #define atomic64_inc_return(v)  (atomic64_add_return(1,v))
 #define atomic64_dec_return(v)  (atomic64_sub_return(1,v))
 
-#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
@@ -400,22 +404,49 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
  * Atomically adds @a to @v, so long as it was not @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       for (;;) {                                              \
-               if (unlikely(c == (u)))                         \
-                       break;                                  \
-               old = atomic_cmpxchg((v), c, c + (a));          \
-               if (likely(old == c))                           \
-                       break;                                  \
-               c = old;                                        \
-       }                                                       \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long c, old;
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic64_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
 __asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
diff --git a/include/asm-x86_64/cmpxchg.h b/include/asm-x86_64/cmpxchg.h
new file mode 100644 (file)
index 0000000..09a6b6b
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __ASM_CMPXCHG_H
+#define __ASM_CMPXCHG_H
+
+#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+
+#define __xg(x) ((volatile long *)(x))
+
+static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+{
+       *ptr = val;
+}
+
+#define _set_64bit set_64bit
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ *       but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+               case 1:
+                       __asm__ __volatile__("xchgb %b0,%1"
+                               :"=q" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 2:
+                       __asm__ __volatile__("xchgw %w0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 4:
+                       __asm__ __volatile__("xchgl %k0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 8:
+                       __asm__ __volatile__("xchgq %0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+       }
+       return x;
+}
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 8:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                       unsigned long old, unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__("cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__("cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__("cmpxchgl %k1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 8:
+               __asm__ __volatile__("cmpxchgq %1,%2"
+                                    : "=a"(prev)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+#define cmpxchg_local(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+
+#endif
index 2b0c088e29578434530b45290792b7e66f5355a7..74feae945a26062fd0734dacd5ac28fd11b2c6df 100644 (file)
@@ -5,19 +5,8 @@
 
 struct pt_regs;
 
-struct die_args {
-       struct pt_regs *regs;
-       const char *str;
-       long err;
-       int trapnr;
-       int signr;
-};
-
-extern int register_die_notifier(struct notifier_block *);
-extern int unregister_die_notifier(struct notifier_block *);
 extern int register_page_fault_notifier(struct notifier_block *);
 extern int unregister_page_fault_notifier(struct notifier_block *);
-extern struct atomic_notifier_head die_chain;
 
 /* Grossly misnamed. */
 enum die_val {
@@ -33,22 +22,10 @@ enum die_val {
        DIE_GPF,
        DIE_CALL,
        DIE_NMI_IPI,
+       DIE_NMI_POST,
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .str = str,
-               .err = err,
-               .trapnr = trap,
-               .signr = sig
-       };
-       return atomic_notifier_call_chain(&die_chain, val, &args);
-} 
-
 extern void printk_address(unsigned long address);
 extern void die(const char *,struct pt_regs *,long);
 extern void __die(const char *,struct pt_regs *,long);
index 5fab957e10918425044a760578030632d478ac87..738e581b67f8f41e198bd87e49fdffcd1d1e4ae1 100644 (file)
@@ -48,8 +48,6 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_X86_64
 
-#define MAX_NOTE_BYTES 1024
-
 /*
  * Saving the registers of the cpu on which panic occured in
  * crash_kexec to save a valid sp. The registers of other cpus
index e769e620022530c751a244f1b83e301d683d1d2a..e87492bb0693eeb8d533db17c34067a45a5bd92a 100644 (file)
 #define _ARCH_X8664_LOCAL_H
 
 #include <linux/percpu.h>
+#include <asm/atomic.h>
 
 typedef struct
 {
-       volatile long counter;
+       atomic_long_t a;
 } local_t;
 
-#define LOCAL_INIT(i)  { (i) }
+#define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
 
-#define local_read(v)  ((v)->counter)
-#define local_set(v,i) (((v)->counter) = (i))
+#define local_read(l)  atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set(&(l)->a, (i))
 
-static inline void local_inc(local_t *v)
+static inline void local_inc(local_t *l)
 {
        __asm__ __volatile__(
                "incq %0"
-               :"=m" (v->counter)
-               :"m" (v->counter));
+               :"=m" (l->a.counter)
+               :"m" (l->a.counter));
 }
 
-static inline void local_dec(local_t *v)
+static inline void local_dec(local_t *l)
 {
        __asm__ __volatile__(
                "decq %0"
-               :"=m" (v->counter)
-               :"m" (v->counter));
+               :"=m" (l->a.counter)
+               :"m" (l->a.counter));
 }
 
-static inline void local_add(long i, local_t *v)
+static inline void local_add(long i, local_t *l)
 {
        __asm__ __volatile__(
                "addq %1,%0"
-               :"=m" (v->counter)
-               :"ir" (i), "m" (v->counter));
+               :"=m" (l->a.counter)
+               :"ir" (i), "m" (l->a.counter));
 }
 
-static inline void local_sub(long i, local_t *v)
+static inline void local_sub(long i, local_t *l)
 {
        __asm__ __volatile__(
                "subq %1,%0"
-               :"=m" (v->counter)
-               :"ir" (i), "m" (v->counter));
+               :"=m" (l->a.counter)
+               :"ir" (i), "m" (l->a.counter));
 }
 
+/**
+ * local_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @l: pointer to type local_t
+ *
+ * Atomically subtracts @i from @l and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int local_sub_and_test(long i, local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "subq %2,%0; sete %1"
+               :"=m" (l->a.counter), "=qm" (c)
+               :"ir" (i), "m" (l->a.counter) : "memory");
+       return c;
+}
+
+/**
+ * local_dec_and_test - decrement and test
+ * @l: pointer to type local_t
+ *
+ * Atomically decrements @l by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int local_dec_and_test(local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "decq %0; sete %1"
+               :"=m" (l->a.counter), "=qm" (c)
+               :"m" (l->a.counter) : "memory");
+       return c != 0;
+}
+
+/**
+ * local_inc_and_test - increment and test
+ * @l: pointer to type local_t
+ *
+ * Atomically increments @l by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int local_inc_and_test(local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "incq %0; sete %1"
+               :"=m" (l->a.counter), "=qm" (c)
+               :"m" (l->a.counter) : "memory");
+       return c != 0;
+}
+
+/**
+ * local_add_negative - add and test if negative
+ * @i: integer value to add
+ * @l: pointer to type local_t
+ *
+ * Atomically adds @i to @l and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ int local_add_negative(long i, local_t *l)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               "addq %2,%0; sets %1"
+               :"=m" (l->a.counter), "=qm" (c)
+               :"ir" (i), "m" (l->a.counter) : "memory");
+       return c;
+}
+
+/**
+ * local_add_return - add and return
+ * @i: integer value to add
+ * @l: pointer to type local_t
+ *
+ * Atomically adds @i to @l and returns @i + @l
+ */
+static __inline__ long local_add_return(long i, local_t *l)
+{
+       long __i = i;
+       __asm__ __volatile__(
+               "xaddq %0, %1;"
+               :"+r" (i), "+m" (l->a.counter)
+               : : "memory");
+       return i + __i;
+}
+
+static __inline__ long local_sub_return(long i, local_t *l)
+{
+       return local_add_return(-i,l);
+}
+
+#define local_inc_return(l)  (local_add_return(1,l))
+#define local_dec_return(l)  (local_sub_return(1,l))
+
+#define local_cmpxchg(l, o, n) \
+       (cmpxchg_local(&((l)->a.counter), (o), (n)))
+/* Always has a lock prefix */
+#define local_xchg(l, n) (xchg(&((l)->a.counter), (n)))
+
+/**
+ * atomic_up_add_unless - add unless the number is a given value
+ * @l: pointer of type local_t
+ * @a: the amount to add to l...
+ * @u: ...unless l is equal to u.
+ *
+ * Atomically adds @a to @l, so long as it was not @u.
+ * Returns non-zero if @l was not @u, and zero otherwise.
+ */
+#define local_add_unless(l, a, u)                              \
+({                                                             \
+       long c, old;                                            \
+       c = local_read(l);                                      \
+       for (;;) {                                              \
+               if (unlikely(c == (u)))                         \
+                       break;                                  \
+               old = local_cmpxchg((l), c, c + (a));   \
+               if (likely(old == c))                           \
+                       break;                                  \
+               c = old;                                        \
+       }                                                       \
+       c != (u);                                               \
+})
+#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+
 /* On x86-64 these are better than the atomic variants on SMP kernels
    because they dont use a lock prefix. */
 #define __local_inc(l)         local_inc(l)
@@ -62,27 +196,27 @@ static inline void local_sub(long i, local_t *v)
 
 /* Need to disable preemption for the cpu local counters otherwise we could
    still access a variable of a previous CPU in a non atomic way. */
-#define cpu_local_wrap_v(v)            \
+#define cpu_local_wrap_v(l)            \
        ({ local_t res__;               \
           preempt_disable();           \
-          res__ = (v);                 \
+          res__ = (l);                 \
           preempt_enable();            \
           res__; })
-#define cpu_local_wrap(v)              \
+#define cpu_local_wrap(l)              \
        ({ preempt_disable();           \
-          v;                           \
+          l;                           \
           preempt_enable(); })         \
 
-#define cpu_local_read(v)    cpu_local_wrap_v(local_read(&__get_cpu_var(v)))
-#define cpu_local_set(v, i)  cpu_local_wrap(local_set(&__get_cpu_var(v), (i)))
-#define cpu_local_inc(v)     cpu_local_wrap(local_inc(&__get_cpu_var(v)))
-#define cpu_local_dec(v)     cpu_local_wrap(local_dec(&__get_cpu_var(v)))
-#define cpu_local_add(i, v)  cpu_local_wrap(local_add((i), &__get_cpu_var(v)))
-#define cpu_local_sub(i, v)  cpu_local_wrap(local_sub((i), &__get_cpu_var(v)))
+#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
 
-#define __cpu_local_inc(v)     cpu_local_inc(v)
-#define __cpu_local_dec(v)     cpu_local_dec(v)
-#define __cpu_local_add(i, v)  cpu_local_add((i), (v))
-#define __cpu_local_sub(i, v)  cpu_local_sub((i), (v))
+#define __cpu_local_inc(l)     cpu_local_inc(l)
+#define __cpu_local_dec(l)     cpu_local_dec(l)
+#define __cpu_local_add(i, l)  cpu_local_add((i), (l))
+#define __cpu_local_sub(i, l)  cpu_local_sub((i), (l))
 
-#endif /* _ARCH_I386_LOCAL_H */
+#endif /* _ARCH_X8664_LOCAL_H */
index a524f0325673ef3ed238984eb2ae70a6ebb1eecf..d5c55b80da54fcc01eb550f7b706d4c6b79fabfc 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/msr-index.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/errno.h>
 /*
  * Access to machine-specific registers (available on 586 and better only)
  * Note: the rd* operations modify the parameters directly (without using
@@ -162,6 +163,8 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #ifdef CONFIG_SMP
 void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 #else  /*  CONFIG_SMP  */
 static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 {
@@ -171,6 +174,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        wrmsr(msr_no, l, h);
 }
+static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       return rdmsr_safe(msr_no, l, h);
+}
+static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       return wrmsr_safe(msr_no, l, h);
+}
 #endif  /* CONFIG_SMP */
 #endif /* __ASSEMBLY__ */
 #endif /* X86_64_MSR_H */
index 4d04e2479569e64963f27f4bf5d2f44fe186238b..dee632fa457d2a8fe5e7eb48168521618b0c4fa8 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _X86_64_PAGE_H
 #define _X86_64_PAGE_H
 
-#include <asm/const.h>
+#include <linux/const.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
@@ -79,9 +79,10 @@ extern unsigned long phys_base;
 
 #define __PHYSICAL_START       CONFIG_PHYSICAL_START
 #define __KERNEL_ALIGN         0x200000
+
 #define __START_KERNEL         (__START_KERNEL_map + __PHYSICAL_START)
-#define __START_KERNEL_map     0xffffffff80000000
-#define __PAGE_OFFSET           0xffff810000000000
+#define __START_KERNEL_map     _AC(0xffffffff80000000, UL)
+#define __PAGE_OFFSET           _AC(0xffff810000000000, UL)
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
@@ -93,7 +94,7 @@ extern unsigned long phys_base;
 #define __VIRTUAL_MASK         ((_AC(1,UL) << __VIRTUAL_MASK_SHIFT) - 1)
 
 #define KERNEL_TEXT_SIZE  (40*1024*1024)
-#define KERNEL_TEXT_START 0xffffffff80000000
+#define KERNEL_TEXT_START _AC(0xffffffff80000000, UL)
 #define PAGE_OFFSET            __PAGE_OFFSET
 
 #ifndef __ASSEMBLY__
index da3390faaea64773af638aa12c5fdbc231206423..08b9831f2e14f1efab15d594dd594d2a326cc098 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _X86_64_PGTABLE_H
 #define _X86_64_PGTABLE_H
 
-#include <asm/const.h>
+#include <linux/const.h>
 #ifndef __ASSEMBLY__
 
 /*
@@ -134,11 +134,11 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 #define USER_PTRS_PER_PGD      ((TASK_SIZE-1)/PGDIR_SIZE+1)
 #define FIRST_USER_ADDRESS     0
 
-#define MAXMEM          0x3fffffffffff
-#define VMALLOC_START    0xffffc20000000000
-#define VMALLOC_END      0xffffe1ffffffffff
-#define MODULES_VADDR    0xffffffff88000000
-#define MODULES_END      0xfffffffffff00000
+#define MAXMEM          _AC(0x3fffffffffff, UL)
+#define VMALLOC_START    _AC(0xffffc20000000000, UL)
+#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+#define MODULES_VADDR    _AC(0xffffffff88000000, UL)
+#define MODULES_END      _AC(0xfffffffffff00000, UL)
 #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
 
 #define _PAGE_BIT_PRESENT      0
@@ -411,17 +411,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 extern spinlock_t pgd_lock;
 extern struct list_head pgd_list;
-void vmalloc_sync_all(void);
 
 extern int kern_addr_valid(unsigned long addr); 
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)     (pfn)
-#define GET_IOSPACE(pfn)               0
-#define GET_PFN(pfn)                   (pfn)
-
 #define HAVE_ARCH_UNMAPPED_AREA
 
 #define pgtable_cache_init()   do { } while (0)
index b0496e0d72a68669cf5a5c1204af07bc1bcee334..8ebd765c674a2564cc5dde497a3e60e482ff3427 100644 (file)
  * megabits/second; but this requires the faster clock.
  */
 #define BASE_BAUD ( 1843200 / 16 )
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#define SERIAL_PORT_DFNS                       \
-       /* UART CLK   PORT IRQ     FLAGS        */                      \
-       { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
-       { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },      /* ttyS1 */     \
-       { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },      /* ttyS2 */     \
-       { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },     /* ttyS3 */
index d5704421456b5016dd6b23e2aef538fffb209b45..3f303d2365ed68d9b207b43976bd1c3aa2282e51 100644 (file)
@@ -57,12 +57,6 @@ static inline int num_booting_cpus(void)
 
 #define raw_smp_processor_id() read_pda(cpunumber)
 
-static inline int hard_smp_processor_id(void)
-{
-       /* we don't want to mark this access volatile - bad code generation */
-       return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
-}
-
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
 extern void prefill_possible_map(void);
@@ -71,7 +65,13 @@ extern unsigned __cpuinitdata disabled_cpus;
 
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 
-#endif
+#endif /* CONFIG_SMP */
+
+static inline int hard_smp_processor_id(void)
+{
+       /* we don't want to mark this access volatile - bad code generation */
+       return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
+}
 
 /*
  * Some lowlevel functions might want to know about
index 213b7fe5d998235c5e1d99266c5b358655ac0b41..ead9f9a56234243ab0413b73a048de253f167695 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/kernel.h>
 #include <asm/segment.h>
-#include <asm/alternative.h>
+#include <asm/cmpxchg.h>
 
 #ifdef __KERNEL__
 
@@ -39,7 +39,7 @@
                       [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
                       [ti_flags] "i" (offsetof(struct thread_info, flags)),\
                       [tif_fork] "i" (TIF_FORK),                         \
-                      [thread_info] "i" (offsetof(struct task_struct, thread_info)), \
+                      [thread_info] "i" (offsetof(struct task_struct, stack)), \
                       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))   \
                     : "memory", "cc" __EXTRA_CLOBBER)
     
@@ -124,100 +124,6 @@ static inline void sched_cacheflush(void)
 
 #define nop() __asm__ __volatile__ ("nop")
 
-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
-
-#define tas(ptr) (xchg((ptr),1))
-
-#define __xg(x) ((volatile long *)(x))
-
-static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
-{
-       *ptr = val;
-}
-
-#define _set_64bit set_64bit
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
- * Note 2: xchg has side effect, so that attribute volatile is necessary,
- *       but generally the primitive is invalid, *ptr is output argument. --ANK
- */
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-               case 1:
-                       __asm__ __volatile__("xchgb %b0,%1"
-                               :"=q" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-               case 2:
-                       __asm__ __volatile__("xchgw %w0,%1"
-                               :"=r" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-               case 4:
-                       __asm__ __volatile__("xchgl %k0,%1"
-                               :"=r" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-               case 8:
-                       __asm__ __volatile__("xchgq %0,%1"
-                               :"=r" (x)
-                               :"m" (*__xg(ptr)), "0" (x)
-                               :"memory");
-                       break;
-       }
-       return x;
-}
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 2:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 4:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 8:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
-                                    : "=a"(prev)
-                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       }
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)\
-       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-                                       (unsigned long)(n),sizeof(*(ptr))))
-
 #ifdef CONFIG_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
index 6cfc3bb10c1a48ff49c11e33e117ef94b31a8033..7405756dd41b66434d635a91127c68458cd59bcd 100644 (file)
@@ -160,7 +160,7 @@ struct ktermios {
 #define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
 
-#define IBSHIFT                      /* Shift from CBAUD to CIBAUD */
+#define IBSHIFT          16            /* Shift from CBAUD to CIBAUD */
 
 /* c_lflag bits */
 #define ISIG   0000001
index 74a6c74397f72bee7619075dd1fba64d7d13e136..10bb5a8ed688889a68a99161021e9c0704d760d9 100644 (file)
@@ -162,7 +162,7 @@ static inline struct thread_info *stack_thread_info(void)
 #define TS_COMPAT              0x0002  /* 32bit syscall active */
 #define TS_POLLING             0x0004  /* true if in idle loop and not sleeping */
 
-#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
 #endif /* __KERNEL__ */
 
index 26e23e01c54a677c9a224a5981a6adbb515ae4a0..595703949df39d370dbbc1a17c00363b6548c8c0 100644 (file)
@@ -619,6 +619,8 @@ __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
 #define __NR_move_pages                279
 __SYSCALL(__NR_move_pages, sys_move_pages)
+#define __NR_utimensat         280
+__SYSCALL(__NR_utimensat, sys_utimensat)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
index 5c2672021068670758d9d9d3d4f8ef30abaa5705..b3b23540f14d2c5087e4b8d09d519378e73e726a 100644 (file)
@@ -234,14 +234,21 @@ static inline int atomic_sub_return(int i, atomic_t * v)
  * Atomically adds @a to @v, so long as it was not @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+       c = atomic_read(v);
+       for (;;) {
+               if (unlikely(c == (u)))
+                       break;
+               old = atomic_cmpxchg((v), c, c + (a));
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != (u);
+}
+
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
diff --git a/include/asm-xtensa/kdebug.h b/include/asm-xtensa/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
index 6acb572759a696052553e1c7988da0ffe74df948..b7952c06a2b75286cb263828e51ab3ba561e3722 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-xtensa/platform-iss/hardware.h
+ * include/asm-xtensa/platform-iss/simcall.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
index 4aaed7fe6cfee3964531029a4013a0996888320b..ddc970847ae9e406c3a9da69e04a190c1acc7151 100644 (file)
@@ -183,8 +183,6 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
   return tmp;
 }
 
-#define tas(ptr) (xchg((ptr),1))
-
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 /*
index 9f05279e7dd3fad13c7e8971e7e3c184c15efa37..94cc04a143f28c21fe27775ba1ae4406f9c2e851 100644 (file)
@@ -4,6 +4,7 @@ header-y += hdlc/
 header-y += isdn/
 header-y += nfsd/
 header-y += raid/
+header-y += spi/
 header-y += sunrpc/
 header-y += tc_act/
 header-y += netfilter/
@@ -33,7 +34,6 @@ header-y += atmsvc.h
 header-y += atm_zatm.h
 header-y += auto_fs4.h
 header-y += auxvec.h
-header-y += awe_voice.h
 header-y += ax25.h
 header-y += b1lli.h
 header-y += baycom.h
@@ -46,6 +46,7 @@ header-y += coda_psdev.h
 header-y += coff.h
 header-y += comstats.h
 header-y += consolemap.h
+header-y += const.h
 header-y += cycx_cfm.h
 header-y += dlm_device.h
 header-y += dm-ioctl.h
@@ -91,7 +92,6 @@ header-y += ip_mp_alg.h
 header-y += ipsec.h
 header-y += ipx.h
 header-y += irda.h
-header-y += isdn_divertif.h
 header-y += iso_fs.h
 header-y += ixjuser.h
 header-y += jffs2.h
@@ -121,6 +121,7 @@ header-y += pci_regs.h
 header-y += personality.h
 header-y += pfkeyv2.h
 header-y += pg.h
+header-y += phantom.h
 header-y += pkt_cls.h
 header-y += pkt_sched.h
 header-y += posix_types.h
@@ -140,6 +141,7 @@ header-y += sockios.h
 header-y += som.h
 header-y += sound.h
 header-y += synclink.h
+header-y += taskstats.h
 header-y += telephony.h
 header-y += termios.h
 header-y += ticable.h
@@ -239,6 +241,7 @@ unifdef-y += ipv6.h
 unifdef-y += ipv6_route.h
 unifdef-y += isdn.h
 unifdef-y += isdnif.h
+unifdef-y += isdn_divertif.h
 unifdef-y += isdn_ppp.h
 unifdef-y += isicom.h
 unifdef-y += jbd.h
index a30ef13c9e622c91bfd7706955758e5932fc639e..43dc2ebfaa0e0e973e9ffca58ba66909ea7e46d0 100644 (file)
@@ -226,7 +226,8 @@ int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                __put_ioctx(kioctx);                                    \
 } while (0)
 
-#define in_aio() !is_sync_wait(current->io_wait)
+#define in_aio() (unlikely(!is_sync_wait(current->io_wait)))
+
 /* may be used for debugging */
 #define warn_if_async()                                                        \
 do {                                                                   \
diff --git a/include/linux/awe_voice.h b/include/linux/awe_voice.h
deleted file mode 100644 (file)
index bf33f17..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * include/linux/awe_voice.h
- *
- * Voice information definitions for the low level driver for the 
- * AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.4; Jan. 4, 2000
- *
- * Copyright (C) 1996-2000 Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef AWE_VOICE_H
-#define AWE_VOICE_H
-
-#ifndef SAMPLE_TYPE_AWE32
-#define SAMPLE_TYPE_AWE32      0x20
-#endif
-
-#define _LINUX_PATCHKEY_H_INDIRECT
-#include <linux/patchkey.h>
-#undef _LINUX_PATCHKEY_H_INDIRECT
-
-/*----------------------------------------------------------------
- * patch information record
- *----------------------------------------------------------------*/
-
-/* patch interface header: 16 bytes */
-typedef struct awe_patch_info {
-       short key;                      /* use AWE_PATCH here */
-#define AWE_PATCH      _PATCHKEY(0x07)
-
-       short device_no;                /* synthesizer number */
-       unsigned short sf_id;           /* file id (should be zero) */
-       short optarg;                   /* optional argument */
-       int len;                        /* data length (without this header) */
-
-       short type;                     /* patch operation type */
-#define AWE_LOAD_INFO          0       /* awe_voice_rec */
-#define AWE_LOAD_DATA          1       /* awe_sample_info */
-#define AWE_OPEN_PATCH         2       /* awe_open_parm */
-#define AWE_CLOSE_PATCH                3       /* none */
-#define AWE_UNLOAD_PATCH       4       /* none */
-#define AWE_REPLACE_DATA       5       /* awe_sample_info (optarg=#channels)*/
-#define AWE_MAP_PRESET         6       /* awe_voice_map */
-/*#define AWE_PROBE_INFO       7*/     /* awe_voice_map (pat only) */
-#define AWE_PROBE_DATA         8       /* optarg=sample */
-#define AWE_REMOVE_INFO                9       /* optarg=(bank<<8)|instr */
-#define AWE_LOAD_CHORUS_FX     0x10    /* awe_chorus_fx_rec (optarg=mode) */
-#define AWE_LOAD_REVERB_FX     0x11    /* awe_reverb_fx_rec (optarg=mode) */
-
-       short reserved;                 /* word alignment data */
-
-       /* the actual patch data begins after this */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-       char data[0];
-#endif
-} awe_patch_info;
-
-/*#define AWE_PATCH_INFO_SIZE  16*/
-#define AWE_PATCH_INFO_SIZE    sizeof(awe_patch_info)
-
-
-/*----------------------------------------------------------------
- * open patch
- *----------------------------------------------------------------*/
-
-#define AWE_PATCH_NAME_LEN     32
-
-typedef struct _awe_open_parm {
-       unsigned short type;            /* sample type */
-#define AWE_PAT_TYPE_MISC      0
-#define AWE_PAT_TYPE_GM                1
-#define AWE_PAT_TYPE_GS                2
-#define AWE_PAT_TYPE_MT32      3
-#define AWE_PAT_TYPE_XG                4
-#define AWE_PAT_TYPE_SFX       5
-#define AWE_PAT_TYPE_GUS       6
-#define AWE_PAT_TYPE_MAP       7
-
-#define AWE_PAT_LOCKED         0x100   /* lock the samples */
-#define AWE_PAT_SHARED         0x200   /* sample is shared */
-
-       short reserved;
-       char name[AWE_PATCH_NAME_LEN];
-} awe_open_parm;
-
-/*#define AWE_OPEN_PARM_SIZE   28*/
-#define AWE_OPEN_PARM_SIZE     sizeof(awe_open_parm)
-
-
-/*----------------------------------------------------------------
- * raw voice information record
- *----------------------------------------------------------------*/
-
-/* wave table envelope & effect parameters to control EMU8000 */
-typedef struct _awe_voice_parm {
-       unsigned short moddelay;        /* modulation delay (0x8000) */
-       unsigned short modatkhld;       /* modulation attack & hold time (0x7f7f) */
-       unsigned short moddcysus;       /* modulation decay & sustain (0x7f7f) */
-       unsigned short modrelease;      /* modulation release time (0x807f) */
-       short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
-       unsigned short voldelay;        /* volume delay (0x8000) */
-       unsigned short volatkhld;       /* volume attack & hold time (0x7f7f) */
-       unsigned short voldcysus;       /* volume decay & sustain (0x7f7f) */
-       unsigned short volrelease;      /* volume release time (0x807f) */
-       short volkeyhold, volkeydecay;  /* envelope change per key (not used) */
-       unsigned short lfo1delay;       /* LFO1 delay (0x8000) */
-       unsigned short lfo2delay;       /* LFO2 delay (0x8000) */
-       unsigned short pefe;            /* modulation pitch & cutoff (0x0000) */
-       unsigned short fmmod;           /* LFO1 pitch & cutoff (0x0000) */
-       unsigned short tremfrq;         /* LFO1 volume & freq (0x0000) */
-       unsigned short fm2frq2;         /* LFO2 pitch & freq (0x0000) */
-       unsigned char cutoff;           /* initial cutoff (0xff) */
-       unsigned char filterQ;          /* initial filter Q [0-15] (0x0) */
-       unsigned char chorus;           /* chorus send (0x00) */
-       unsigned char reverb;           /* reverb send (0x00) */
-       unsigned short reserved[4];     /* not used */
-} awe_voice_parm;
-
-typedef struct _awe_voice_parm_block {
-       unsigned short moddelay;        /* modulation delay (0x8000) */
-       unsigned char modatk, modhld;
-       unsigned char moddcy, modsus;
-       unsigned char modrel, moddummy;
-       short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
-       unsigned short voldelay;        /* volume delay (0x8000) */
-       unsigned char volatk, volhld;
-       unsigned char voldcy, volsus;
-       unsigned char volrel, voldummy;
-       short volkeyhold, volkeydecay;  /* envelope change per key (not used) */
-       unsigned short lfo1delay;       /* LFO1 delay (0x8000) */
-       unsigned short lfo2delay;       /* LFO2 delay (0x8000) */
-       unsigned char env1fc, env1pit;
-       unsigned char lfo1fc, lfo1pit;
-       unsigned char lfo1freq, lfo1vol;
-       unsigned char lfo2freq, lfo2pit;
-       unsigned char cutoff;           /* initial cutoff (0xff) */
-       unsigned char filterQ;          /* initial filter Q [0-15] (0x0) */
-       unsigned char chorus;           /* chorus send (0x00) */
-       unsigned char reverb;           /* reverb send (0x00) */
-       unsigned short reserved[4];     /* not used */
-} awe_voice_parm_block;
-
-#define AWE_VOICE_PARM_SIZE    48
-
-
-/* wave table parameters: 92 bytes */
-typedef struct _awe_voice_info {
-       unsigned short sf_id;           /* file id (should be zero) */
-       unsigned short sample;          /* sample id */
-       int start, end;                 /* sample offset correction */
-       int loopstart, loopend;         /* loop offset correction */
-       short rate_offset;              /* sample rate pitch offset */
-       unsigned short mode;            /* sample mode */
-#define AWE_MODE_ROMSOUND              0x8000
-#define AWE_MODE_STEREO                        1
-#define AWE_MODE_LOOPING               2
-#define AWE_MODE_NORELEASE             4       /* obsolete */
-#define AWE_MODE_INIT_PARM             8
-
-       short root;                     /* midi root key */
-       short tune;                     /* pitch tuning (in cents) */
-       signed char low, high;          /* key note range */
-       signed char vellow, velhigh;    /* velocity range */
-       signed char fixkey, fixvel;     /* fixed key, velocity */
-       signed char pan, fixpan;        /* panning, fixed panning */
-       short exclusiveClass;           /* exclusive class (0 = none) */
-       unsigned char amplitude;        /* sample volume (127 max) */
-       unsigned char attenuation;      /* attenuation (0.375dB) */
-       short scaleTuning;              /* pitch scale tuning(%), normally 100 */
-       awe_voice_parm parm;            /* voice envelope parameters */
-       short index;                    /* internal index (set by driver) */
-} awe_voice_info;
-
-/*#define AWE_VOICE_INFO_SIZE  92*/
-#define AWE_VOICE_INFO_SIZE    sizeof(awe_voice_info)
-
-/*----------------------------------------------------------------*/
-
-/* The info entry of awe_voice_rec is changed from 0 to 1
- * for some compilers refusing zero size array.
- * Due to this change, sizeof(awe_voice_rec) becomes different
- * from older versions.
- * Use AWE_VOICE_REC_SIZE instead.
- */
-
-/* instrument info header: 4 bytes */
-typedef struct _awe_voice_rec_hdr {
-       unsigned char bank;             /* midi bank number */
-       unsigned char instr;            /* midi preset number */
-       char nvoices;                   /* number of voices */
-       char write_mode;                /* write mode; normally 0 */
-#define AWE_WR_APPEND          0       /* append anyway */
-#define AWE_WR_EXCLUSIVE       1       /* skip if already exists */
-#define AWE_WR_REPLACE         2       /* replace if already exists */
-} awe_voice_rec_hdr;
-
-/*#define AWE_VOICE_REC_SIZE   4*/
-#define AWE_VOICE_REC_SIZE     sizeof(awe_voice_rec_hdr)
-
-/* the standard patch structure for one sample */
-typedef struct _awe_voice_rec_patch {
-       awe_patch_info          patch;
-       awe_voice_rec_hdr       hdr;
-       awe_voice_info          info;
-} awe_voice_rec_patch;
-
-
-/* obsolete data type */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-#define AWE_INFOARRAY_SIZE     0
-#else
-#define AWE_INFOARRAY_SIZE     1
-#endif
-
-typedef struct _awe_voice_rec {
-       unsigned char bank;             /* midi bank number */
-       unsigned char instr;            /* midi preset number */
-       short nvoices;                  /* number of voices */
-       /* voice information follows here */
-       awe_voice_info info[AWE_INFOARRAY_SIZE];
-} awe_voice_rec;
-
-
-/*----------------------------------------------------------------
- * sample wave information
- *----------------------------------------------------------------*/
-
-/* wave table sample header: 32 bytes */
-typedef struct awe_sample_info {
-       unsigned short sf_id;           /* file id (should be zero) */
-       unsigned short sample;          /* sample id */
-       int start, end;                 /* start & end offset */
-       int loopstart, loopend;         /* loop start & end offset */
-       int size;                       /* size (0 = ROM) */
-       short checksum_flag;            /* use check sum = 1 */
-       unsigned short mode_flags;      /* mode flags */
-#define AWE_SAMPLE_8BITS       1       /* wave data is 8bits */
-#define AWE_SAMPLE_UNSIGNED    2       /* wave data is unsigned */
-#define AWE_SAMPLE_NO_BLANK    4       /* no blank loop is attached */
-#define AWE_SAMPLE_SINGLESHOT  8       /* single-shot w/o loop */
-#define AWE_SAMPLE_BIDIR_LOOP  16      /* bidirectional looping */
-#define AWE_SAMPLE_STEREO_LEFT 32      /* stereo left sound */
-#define AWE_SAMPLE_STEREO_RIGHT        64      /* stereo right sound */
-#define AWE_SAMPLE_REVERSE_LOOP 128    /* reverse looping */
-       unsigned int checksum;          /* check sum */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-       unsigned short data[0];         /* sample data follows here */
-#endif
-} awe_sample_info;
-
-/*#define AWE_SAMPLE_INFO_SIZE 32*/
-#define AWE_SAMPLE_INFO_SIZE   sizeof(awe_sample_info)
-
-
-/*----------------------------------------------------------------
- * voice preset mapping
- *----------------------------------------------------------------*/
-
-typedef struct awe_voice_map {
-       int map_bank, map_instr, map_key;       /* key = -1 means all keys */
-       int src_bank, src_instr, src_key;
-} awe_voice_map;
-
-#define AWE_VOICE_MAP_SIZE     sizeof(awe_voice_map)
-
-
-/*----------------------------------------------------------------
- * awe hardware controls
- *----------------------------------------------------------------*/
-
-#define _AWE_DEBUG_MODE                        0x00
-#define _AWE_REVERB_MODE               0x01
-#define _AWE_CHORUS_MODE               0x02
-#define _AWE_REMOVE_LAST_SAMPLES       0x03
-#define _AWE_INITIALIZE_CHIP           0x04
-#define _AWE_SEND_EFFECT               0x05
-#define _AWE_TERMINATE_CHANNEL         0x06
-#define _AWE_TERMINATE_ALL             0x07
-#define _AWE_INITIAL_VOLUME            0x08
-#define _AWE_INITIAL_ATTEN     _AWE_INITIAL_VOLUME
-#define _AWE_RESET_CHANNEL             0x09
-#define _AWE_CHANNEL_MODE              0x0a
-#define _AWE_DRUM_CHANNELS             0x0b
-#define _AWE_MISC_MODE                 0x0c
-#define _AWE_RELEASE_ALL               0x0d
-#define _AWE_NOTEOFF_ALL               0x0e
-#define _AWE_CHN_PRESSURE              0x0f
-/*#define _AWE_GET_CURRENT_MODE                0x10*/
-#define _AWE_EQUALIZER                 0x11
-/*#define _AWE_GET_MISC_MODE           0x12*/
-/*#define _AWE_GET_FONTINFO            0x13*/
-
-#define _AWE_MODE_FLAG                 0x80
-#define _AWE_COOKED_FLAG               0x40    /* not supported */
-#define _AWE_MODE_VALUE_MASK           0x3F
-
-/*----------------------------------------------------------------*/
-
-#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \
-{((char*)(p))[0] = SEQ_PRIVATE;\
- ((char*)(p))[1] = dev;\
- ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\
- ((char*)(p))[3] = voice;\
- ((unsigned short*)(p))[2] = p1;\
- ((unsigned short*)(p))[3] = p2;}
-
-/* buffered access */
-#define _AWE_CMD(dev, voice, cmd, p1, p2) \
-{_SEQ_NEEDBUF(8);\
- _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\
- _SEQ_ADVBUF(8);}
-
-/* direct access */
-#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \
-{struct seq_event_rec tmp;\
- _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\
- ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);}
-
-/*----------------------------------------------------------------*/
-
-/* set debugging mode */
-#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
-/* set reverb mode; from 0 to 7 */
-#define AWE_REVERB_MODE(dev,p1)        _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
-/* set chorus mode; from 0 to 7 */
-#define AWE_CHORUS_MODE(dev,p1)        _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
-
-/* reset channel */
-#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0)
-#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0)
-
-/* send an effect to all layers */
-#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
-#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value)
-#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0)
-/* send an effect to a layer */
-#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value)
-#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value)
-#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0)
-
-/* terminate sound on the channel/voice */
-#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
-/* terminate all sounds */
-#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
-/* release all sounds (w/o sustain effect) */
-#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0)
-/* note off all sounds (w sustain effect) */
-#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0)
-
-/* set initial attenuation */
-#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
-#define AWE_INITIAL_ATTEN  AWE_INITIAL_VOLUME
-/* relative attenuation */
-#define AWE_SET_ATTEN(dev,atten)  _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1)
-
-/* set channel playing mode; mode=0/1/2 */
-#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0)
-#define AWE_PLAY_INDIRECT      0       /* indirect voice mode (default) */
-#define AWE_PLAY_MULTI         1       /* multi note voice mode */
-#define AWE_PLAY_DIRECT                2       /* direct single voice mode */
-#define AWE_PLAY_MULTI2                3       /* sequencer2 mode; used internally */
-
-/* set drum channel mask; channels is 32bit long value */
-#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16))
-
-/* set bass and treble control; values are from 0 to 11 */
-#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble)
-
-/* remove last loaded samples */
-#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
-/* initialize emu8000 chip */
-#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
-
-/* set miscellaneous modes; meta command */
-#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value)
-/* exclusive sound off; 1=off */
-#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode)
-/* default GUS bank number */
-#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank)
-/* change panning position in realtime; 0=don't 1=do */
-#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode)
-
-/* extended pressure controls; not portable with other sound drivers */
-#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel)
-#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0)
-
-/*----------------------------------------------------------------*/
-
-/* reverb mode parameters */
-#define        AWE_REVERB_ROOM1        0
-#define AWE_REVERB_ROOM2       1
-#define        AWE_REVERB_ROOM3        2
-#define        AWE_REVERB_HALL1        3
-#define        AWE_REVERB_HALL2        4
-#define        AWE_REVERB_PLATE        5
-#define        AWE_REVERB_DELAY        6
-#define        AWE_REVERB_PANNINGDELAY 7
-#define AWE_REVERB_PREDEFINED  8
-/* user can define reverb modes up to 32 */
-#define AWE_REVERB_NUMBERS     32
-
-typedef struct awe_reverb_fx_rec {
-       unsigned short parms[28];
-} awe_reverb_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* chorus mode parameters */
-#define AWE_CHORUS_1           0
-#define        AWE_CHORUS_2            1
-#define        AWE_CHORUS_3            2
-#define        AWE_CHORUS_4            3
-#define        AWE_CHORUS_FEEDBACK     4
-#define        AWE_CHORUS_FLANGER      5
-#define        AWE_CHORUS_SHORTDELAY   6
-#define        AWE_CHORUS_SHORTDELAY2  7
-#define AWE_CHORUS_PREDEFINED  8
-/* user can define chorus modes up to 32 */
-#define AWE_CHORUS_NUMBERS     32
-
-typedef struct awe_chorus_fx_rec {
-       unsigned short feedback;        /* feedback level (0xE600-0xE6FF) */
-       unsigned short delay_offset;    /* delay (0-0x0DA3) [1/44100 sec] */
-       unsigned short lfo_depth;       /* LFO depth (0xBC00-0xBCFF) */
-       unsigned int delay;     /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
-       unsigned int lfo_freq;          /* LFO freq LFO freq (0-0xFFFFFFFF) */
-} awe_chorus_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* misc mode types */
-enum {
-/* 0*/ AWE_MD_EXCLUSIVE_OFF,   /* obsolete */
-/* 1*/ AWE_MD_EXCLUSIVE_ON,    /* obsolete */
-/* 2*/ AWE_MD_VERSION,         /* read only */
-/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* 0/1: exclusive note on (default=1) */
-/* 4*/ AWE_MD_REALTIME_PAN,    /* 0/1: do realtime pan change (default=1) */
-/* 5*/ AWE_MD_GUS_BANK,        /* bank number for GUS patches (default=0) */
-/* 6*/ AWE_MD_KEEP_EFFECT,     /* 0/1: keep effect values, (default=0) */
-/* 7*/ AWE_MD_ZERO_ATTEN,      /* attenuation of max volume (default=32) */
-/* 8*/ AWE_MD_CHN_PRIOR,       /* 0/1: set MIDI channel priority mode (default=1) */
-/* 9*/ AWE_MD_MOD_SENSE,       /* integer: modwheel sensitivity (def=18) */
-/*10*/ AWE_MD_DEF_PRESET,      /* integer: default preset number (def=0) */
-/*11*/ AWE_MD_DEF_BANK,        /* integer: default bank number (def=0) */
-/*12*/ AWE_MD_DEF_DRUM,        /* integer: default drumset number (def=0) */
-/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
-/*14*/ AWE_MD_NEW_VOLUME_CALC, /* 0/1: volume calculation mode (def=1) */
-/*15*/ AWE_MD_CHORUS_MODE,     /* integer: chorus mode (def=2) */
-/*16*/ AWE_MD_REVERB_MODE,     /* integer: chorus mode (def=4) */
-/*17*/ AWE_MD_BASS_LEVEL,      /* integer: bass level (def=5) */
-/*18*/ AWE_MD_TREBLE_LEVEL,    /* integer: treble level (def=9) */
-/*19*/ AWE_MD_DEBUG_MODE,      /* integer: debug level (def=0) */
-/*20*/ AWE_MD_PAN_EXCHANGE,    /* 0/1: exchange panning direction (def=0) */
-       AWE_MD_END,
-};
-
-/*----------------------------------------------------------------*/
-
-/* effect parameters */
-enum {
-
-/* modulation envelope parameters */
-/* 0*/ AWE_FX_ENV1_DELAY,      /* WORD: ENVVAL */
-/* 1*/ AWE_FX_ENV1_ATTACK,     /* BYTE: up ATKHLD */
-/* 2*/ AWE_FX_ENV1_HOLD,       /* BYTE: lw ATKHLD */
-/* 3*/ AWE_FX_ENV1_DECAY,      /* BYTE: lw DCYSUS */
-/* 4*/ AWE_FX_ENV1_RELEASE,    /* BYTE: lw DCYSUS */
-/* 5*/ AWE_FX_ENV1_SUSTAIN,    /* BYTE: up DCYSUS */
-/* 6*/ AWE_FX_ENV1_PITCH,      /* BYTE: up PEFE */
-/* 7*/ AWE_FX_ENV1_CUTOFF,     /* BYTE: lw PEFE */
-
-/* volume envelope parameters */
-/* 8*/ AWE_FX_ENV2_DELAY,      /* WORD: ENVVOL */
-/* 9*/ AWE_FX_ENV2_ATTACK,     /* BYTE: up ATKHLDV */
-/*10*/ AWE_FX_ENV2_HOLD,       /* BYTE: lw ATKHLDV */
-/*11*/ AWE_FX_ENV2_DECAY,      /* BYTE: lw DCYSUSV */
-/*12*/ AWE_FX_ENV2_RELEASE,    /* BYTE: lw DCYSUSV */
-/*13*/ AWE_FX_ENV2_SUSTAIN,    /* BYTE: up DCYSUSV */
-       
-/* LFO1 (tremolo & vibrato) parameters */
-/*14*/ AWE_FX_LFO1_DELAY,      /* WORD: LFO1VAL */
-/*15*/ AWE_FX_LFO1_FREQ,       /* BYTE: lo TREMFRQ */
-/*16*/ AWE_FX_LFO1_VOLUME,     /* BYTE: up TREMFRQ */
-/*17*/ AWE_FX_LFO1_PITCH,      /* BYTE: up FMMOD */
-/*18*/ AWE_FX_LFO1_CUTOFF,     /* BYTE: lo FMMOD */
-
-/* LFO2 (vibrato) parameters */
-/*19*/ AWE_FX_LFO2_DELAY,      /* WORD: LFO2VAL */
-/*20*/ AWE_FX_LFO2_FREQ,       /* BYTE: lo FM2FRQ2 */
-/*21*/ AWE_FX_LFO2_PITCH,      /* BYTE: up FM2FRQ2 */
-
-/* Other overall effect parameters */
-/*22*/ AWE_FX_INIT_PITCH,      /* SHORT: pitch offset */
-/*23*/ AWE_FX_CHORUS,          /* BYTE: chorus effects send (0-255) */
-/*24*/ AWE_FX_REVERB,          /* BYTE: reverb effects send (0-255) */
-/*25*/ AWE_FX_CUTOFF,          /* BYTE: up IFATN */
-/*26*/ AWE_FX_FILTERQ,         /* BYTE: up CCCA */
-
-/* Sample / loop offset changes */
-/*27*/ AWE_FX_SAMPLE_START,    /* SHORT: offset */
-/*28*/ AWE_FX_LOOP_START,      /* SHORT: offset */
-/*29*/ AWE_FX_LOOP_END,        /* SHORT: offset */
-/*30*/ AWE_FX_COARSE_SAMPLE_START,     /* SHORT: upper word offset */
-/*31*/ AWE_FX_COARSE_LOOP_START,       /* SHORT: upper word offset */
-/*32*/ AWE_FX_COARSE_LOOP_END,         /* SHORT: upper word offset */
-/*33*/ AWE_FX_ATTEN,           /* BYTE: lo IFATN */
-
-       AWE_FX_END,
-};
-
-#endif /* AWE_VOICE_H */
index a686eabe22d645e8304af1ab33ab6114783523d9..db5b00a792f519d7d4dde9a2e4824a2c7f948db9 100644 (file)
@@ -854,7 +854,7 @@ static inline void put_dev_sector(Sector p)
 
 struct work_struct;
 int kblockd_schedule_work(struct work_struct *work);
-void kblockd_flush(void);
+void kblockd_flush_work(struct work_struct *work);
 
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
        MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
index e86e4a938373e15a3a8edcbb07802a5c9274bb02..3dc715b025002d90935cac7e204e16a197060b63 100644 (file)
 #define be32_to_cpus __be32_to_cpus
 #define cpu_to_be16s __cpu_to_be16s
 #define be16_to_cpus __be16_to_cpus
-#endif
 
-
-#if defined(__KERNEL__)
 /*
- * Handle ntohl and suches. These have various compatibility
- * issues - like we want to give the prototype even though we
- * also have a macro for them in case some strange program
- * wants to take the address of the thing or something..
- *
- * Note that these used to return a "long" in libc5, even though
- * long is often 64-bit these days.. Thus the casts.
- *
  * They have to be macros in order to do the constant folding
  * correctly - if the argument passed into a inline function
  * it is no longer constant according to gcc..
 #undef htonl
 #undef htons
 
-/*
- * Do the prototypes. Somebody might want to take the
- * address or some such sick thing..
- */
-extern __u32                   ntohl(__be32);
-extern __be32                  htonl(__u32);
-extern __u16                   ntohs(__be16);
-extern __be16                  htons(__u16);
-
-#if defined(__GNUC__) && defined(__OPTIMIZE__)
-
 #define ___htonl(x) __cpu_to_be32(x)
 #define ___htons(x) __cpu_to_be16(x)
 #define ___ntohl(x) __be32_to_cpu(x)
@@ -168,9 +146,6 @@ extern __be16                       htons(__u16);
 #define htons(x) ___htons(x)
 #define ntohs(x) ___ntohs(x)
 
-#endif /* OPTIMIZE */
-
 #endif /* KERNEL */
 
-
 #endif /* _LINUX_BYTEORDER_GENERIC_H */
index 25f7f32883ec8667c4c464c2ff43f36a73aad27c..142134ff164552e22011ebba4e96381dc8f0067a 100644 (file)
  *    separated swab functions from cpu_to_XX,
  *    to clean up support for bizarre-endian architectures.
  *
+ * Trent Piepho <xyzzy@speakeasy.org> 2007114
+ *    make constant-folding work, provide C versions that
+ *    gcc can optimize better, explain different versions
+ *
  * See asm-i386/byteorder.h and suches for examples of how to provide
  * architecture-dependent optimized versions
  *
 
 #include <linux/compiler.h>
 
+/* Functions/macros defined, there are a lot:
+ *
+ * ___swabXX
+ *    Generic C versions of the swab functions.
+ *
+ * ___constant_swabXX
+ *    C versions that gcc can fold into a compile-time constant when
+ *    the argument is a compile-time constant.
+ *
+ * __arch__swabXX[sp]?
+ *    Architecture optimized versions of all the swab functions
+ *    (including the s and p versions).  These can be defined in
+ *    asm-arch/byteorder.h.  Any which are not, are defined here.
+ *    __arch__swabXXs() is defined in terms of __arch__swabXXp(), which
+ *    is defined in terms of __arch__swabXX(), which is in turn defined
+ *    in terms of ___swabXX(x).
+ *    These must be macros.  They may be unsafe for arguments with
+ *    side-effects.
+ *
+ * __fswabXX
+ *    Inline function versions of the __arch__ macros.  These _are_ safe
+ *    if the arguments have side-effects.  Note there are no s and p
+ *    versions of these.
+ *
+ * __swabXX[sb]
+ *    There are the ones you should actually use.  The __swabXX versions
+ *    will be a constant given a constant argument and use the arch
+ *    specific code (if any) for non-constant arguments.  The s and p
+ *    versions always use the arch specific code (constant folding
+ *    doesn't apply).  They are safe to use with arguments with
+ *    side-effects.
+ *
+ * swabXX[sb]
+ *    Nicknames for __swabXX[sb] to use in the kernel.
+ */
+
 /* casts are necessary for constants, because we never know how for sure
  * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
  */
-#define ___swab16(x) \
-({ \
-       __u16 __x = (x); \
-       ((__u16)( \
-               (((__u16)(__x) & (__u16)0x00ffU) << 8) | \
-               (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
-})
 
-#define ___swab32(x) \
-({ \
-       __u32 __x = (x); \
-       ((__u32)( \
-               (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
-               (((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
-               (((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
-               (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
-})
-
-#define ___swab64(x) \
-({ \
-       __u64 __x = (x); \
-       ((__u64)( \
-               (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
-               (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
-               (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
-               (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) <<  8) | \
-               (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >>  8) | \
-               (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
-               (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
-               (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
-})
+static __inline__ __attribute_const__ __u16 ___swab16(__u16 x)
+{
+       return x<<8 | x>>8;
+}
+static __inline__ __attribute_const__ __u32 ___swab32(__u32 x)
+{
+       return x<<24 | x>>24 |
+               (x & (__u32)0x0000ff00UL)<<8 |
+               (x & (__u32)0x00ff0000UL)>>8;
+}
+static __inline__ __attribute_const__ __u64 ___swab64(__u64 x)
+{
+       return x<<56 | x>>56 |
+               (x & (__u64)0x000000000000ff00ULL)<<40 |
+               (x & (__u64)0x0000000000ff0000ULL)<<24 |
+               (x & (__u64)0x00000000ff000000ULL)<< 8 |
+               (x & (__u64)0x000000ff00000000ULL)>> 8 |
+               (x & (__u64)0x0000ff0000000000ULL)>>24 |
+               (x & (__u64)0x00ff000000000000ULL)>>40;
+}
 
 #define ___constant_swab16(x) \
        ((__u16)( \
  * provide defaults when no architecture-specific optimization is detected
  */
 #ifndef __arch__swab16
-#  define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
+#  define __arch__swab16(x) ___swab16(x)
 #endif
 #ifndef __arch__swab32
-#  define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
+#  define __arch__swab32(x) ___swab32(x)
 #endif
 #ifndef __arch__swab64
-#  define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
+#  define __arch__swab64(x) ___swab64(x)
 #endif
 
 #ifndef __arch__swab16p
 #endif
 
 #ifndef __arch__swab16s
-#  define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
+#  define __arch__swab16s(x) ((void)(*(x) = __arch__swab16p(x)))
 #endif
 #ifndef __arch__swab32s
-#  define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
+#  define __arch__swab32s(x) ((void)(*(x) = __arch__swab32p(x)))
 #endif
 #ifndef __arch__swab64s
-#  define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
+#  define __arch__swab64s(x) ((void)(*(x) = __arch__swab64p(x)))
 #endif
 
 
 #if defined(__GNUC__) && defined(__OPTIMIZE__)
 #  define __swab16(x) \
 (__builtin_constant_p((__u16)(x)) ? \
- ___swab16((x)) : \
+ ___constant_swab16((x)) : \
  __fswab16((x)))
 #  define __swab32(x) \
 (__builtin_constant_p((__u32)(x)) ? \
- ___swab32((x)) : \
+ ___constant_swab32((x)) : \
  __fswab32((x)))
 #  define __swab64(x) \
 (__builtin_constant_p((__u64)(x)) ? \
- ___swab64((x)) : \
+ ___constant_swab64((x)) : \
  __fswab64((x)))
 #else
 #  define __swab16(x) __fswab16(x)
index 4ea7e7bcfafe284763f9229ecde3c16efc6d1452..8486e78f7335ccc07db270c312f1af2192c65448 100644 (file)
@@ -54,17 +54,17 @@ enum clock_event_nofitiers {
 /**
  * struct clock_event_device - clock event device descriptor
  * @name:              ptr to clock event name
- * @hints:             usage hints
+ * @features:          features
  * @max_delta_ns:      maximum delta value in ns
  * @min_delta_ns:      minimum delta value in ns
  * @mult:              nanosecond to cycles multiplier
  * @shift:             nanoseconds to cycles divisor (power of two)
  * @rating:            variable to rate clock event devices
- * @irq:               irq number (only for non cpu local devices)
- * @cpumask:           cpumask to indicate for which cpus this device works
- * @set_next_event:    set next event
+ * @irq:               IRQ number (only for non CPU local devices)
+ * @cpumask:           cpumask to indicate for which CPUs this device works
+ * @set_next_event:    set next event function
  * @set_mode:          set mode function
- * @evthandler:                Assigned by the framework to be called by the low
+ * @event_handler:     Assigned by the framework to be called by the low
  *                     level handler of the event source
  * @broadcast:         function to broadcast events
  * @list:              list head for the management code
index daa4940cc0f1fa37c9afd87b4ed759aac8c0a6bf..bf297b03a4e4650cd4c02a9dbe4e55307674411d 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/cache.h>
 #include <linux/timer.h>
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -48,10 +49,14 @@ struct clocksource;
  * @shift:             cycle to nanosecond divisor (power of two)
  * @flags:             flags describing special properties
  * @vread:             vsyscall based read
+ * @resume:            resume function for the clocksource, if necessary
  * @cycle_interval:    Used internally by timekeeping core, please ignore.
  * @xtime_interval:    Used internally by timekeeping core, please ignore.
  */
 struct clocksource {
+       /*
+        * First part of structure is read mostly
+        */
        char *name;
        struct list_head list;
        int rating;
@@ -61,10 +66,18 @@ struct clocksource {
        u32 shift;
        unsigned long flags;
        cycle_t (*vread)(void);
+       void (*resume)(void);
 
        /* timekeeping specific data, ignore */
-       cycle_t cycle_last, cycle_interval;
-       u64 xtime_nsec, xtime_interval;
+       cycle_t cycle_interval;
+       u64     xtime_interval;
+       /*
+        * Second part is written at each timer interrupt
+        * Keep it in a different cache line to dirty no
+        * more than one cache line.
+        */
+       cycle_t cycle_last ____cacheline_aligned_in_smp;
+       u64 xtime_nsec;
        s64 error;
 
 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
@@ -198,6 +211,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c,
 extern int clocksource_register(struct clocksource*);
 extern struct clocksource* clocksource_get_next(void);
 extern void clocksource_change_rating(struct clocksource *cs, int rating);
+extern void clocksource_resume(void);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
index ccd863dd77fae4a654981181ba189f5c4604c155..70a157a130bb4123d21b33b45d4fdf0c2fff1ebb 100644 (file)
@@ -253,5 +253,8 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
                        const compat_sigset_t __user *sigmask,
                        compat_size_t sigsetsize);
 
+asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename,
+                               struct compat_timespec __user *t, int flags);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
deleted file mode 100644 (file)
index c26c3ad..0000000
+++ /dev/null
@@ -1,830 +0,0 @@
-/* List here explicitly which ioctl's are known to have
- * compatible types passed or none at all... Please include
- * only stuff that is compatible on *all architectures*.
- */
-
-COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
-COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
-
-/* Big T */
-COMPATIBLE_IOCTL(TCGETA)
-COMPATIBLE_IOCTL(TCSETA)
-COMPATIBLE_IOCTL(TCSETAW)
-COMPATIBLE_IOCTL(TCSETAF)
-COMPATIBLE_IOCTL(TCSBRK)
-ULONG_IOCTL(TCSBRKP)
-COMPATIBLE_IOCTL(TCXONC)
-COMPATIBLE_IOCTL(TCFLSH)
-COMPATIBLE_IOCTL(TCGETS)
-COMPATIBLE_IOCTL(TCSETS)
-COMPATIBLE_IOCTL(TCSETSW)
-COMPATIBLE_IOCTL(TCSETSF)
-COMPATIBLE_IOCTL(TIOCLINUX)
-COMPATIBLE_IOCTL(TIOCSBRK)
-COMPATIBLE_IOCTL(TIOCCBRK)
-ULONG_IOCTL(TIOCMIWAIT)
-COMPATIBLE_IOCTL(TIOCGICOUNT)
-/* Little t */
-COMPATIBLE_IOCTL(TIOCGETD)
-COMPATIBLE_IOCTL(TIOCSETD)
-COMPATIBLE_IOCTL(TIOCEXCL)
-COMPATIBLE_IOCTL(TIOCNXCL)
-COMPATIBLE_IOCTL(TIOCCONS)
-COMPATIBLE_IOCTL(TIOCGSOFTCAR)
-COMPATIBLE_IOCTL(TIOCSSOFTCAR)
-COMPATIBLE_IOCTL(TIOCSWINSZ)
-COMPATIBLE_IOCTL(TIOCGWINSZ)
-COMPATIBLE_IOCTL(TIOCMGET)
-COMPATIBLE_IOCTL(TIOCMBIC)
-COMPATIBLE_IOCTL(TIOCMBIS)
-COMPATIBLE_IOCTL(TIOCMSET)
-COMPATIBLE_IOCTL(TIOCPKT)
-COMPATIBLE_IOCTL(TIOCNOTTY)
-COMPATIBLE_IOCTL(TIOCSTI)
-COMPATIBLE_IOCTL(TIOCOUTQ)
-COMPATIBLE_IOCTL(TIOCSPGRP)
-COMPATIBLE_IOCTL(TIOCGPGRP)
-ULONG_IOCTL(TIOCSCTTY)
-COMPATIBLE_IOCTL(TIOCGPTN)
-COMPATIBLE_IOCTL(TIOCSPTLCK)
-COMPATIBLE_IOCTL(TIOCSERGETLSR)
-/* Little f */
-COMPATIBLE_IOCTL(FIOCLEX)
-COMPATIBLE_IOCTL(FIONCLEX)
-COMPATIBLE_IOCTL(FIOASYNC)
-COMPATIBLE_IOCTL(FIONBIO)
-COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
-/* 0x00 */
-COMPATIBLE_IOCTL(FIBMAP)
-COMPATIBLE_IOCTL(FIGETBSZ)
-/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
- *         Some need translations, these do not.
- */
-COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
-COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
-COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
-ULONG_IOCTL(HDIO_SET_MULTCOUNT)
-ULONG_IOCTL(HDIO_SET_UNMASKINTR)
-ULONG_IOCTL(HDIO_SET_KEEPSETTINGS)
-ULONG_IOCTL(HDIO_SET_32BIT)
-ULONG_IOCTL(HDIO_SET_NOWERR)
-ULONG_IOCTL(HDIO_SET_DMA)
-ULONG_IOCTL(HDIO_SET_PIO_MODE)
-ULONG_IOCTL(HDIO_SET_NICE)
-ULONG_IOCTL(HDIO_SET_WCACHE)
-ULONG_IOCTL(HDIO_SET_ACOUSTIC)
-ULONG_IOCTL(HDIO_SET_BUSSTATE)
-ULONG_IOCTL(HDIO_SET_ADDRESS)
-COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
-/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
-COMPATIBLE_IOCTL(0x330)
-/* 0x02 -- Floppy ioctls */
-COMPATIBLE_IOCTL(FDMSGON)
-COMPATIBLE_IOCTL(FDMSGOFF)
-COMPATIBLE_IOCTL(FDSETEMSGTRESH)
-COMPATIBLE_IOCTL(FDFLUSH)
-COMPATIBLE_IOCTL(FDWERRORCLR)
-COMPATIBLE_IOCTL(FDSETMAXERRS)
-COMPATIBLE_IOCTL(FDGETMAXERRS)
-COMPATIBLE_IOCTL(FDGETDRVTYP)
-COMPATIBLE_IOCTL(FDEJECT)
-COMPATIBLE_IOCTL(FDCLRPRM)
-COMPATIBLE_IOCTL(FDFMTBEG)
-COMPATIBLE_IOCTL(FDFMTEND)
-COMPATIBLE_IOCTL(FDRESET)
-COMPATIBLE_IOCTL(FDTWADDLE)
-COMPATIBLE_IOCTL(FDFMTTRK)
-COMPATIBLE_IOCTL(FDRAWCMD)
-/* 0x12 */
-#ifdef CONFIG_BLOCK
-COMPATIBLE_IOCTL(BLKRASET)
-COMPATIBLE_IOCTL(BLKROSET)
-COMPATIBLE_IOCTL(BLKROGET)
-COMPATIBLE_IOCTL(BLKRRPART)
-COMPATIBLE_IOCTL(BLKFLSBUF)
-COMPATIBLE_IOCTL(BLKSECTSET)
-COMPATIBLE_IOCTL(BLKSSZGET)
-COMPATIBLE_IOCTL(BLKTRACESTART)
-COMPATIBLE_IOCTL(BLKTRACESTOP)
-COMPATIBLE_IOCTL(BLKTRACESETUP)
-COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
-ULONG_IOCTL(BLKRASET)
-ULONG_IOCTL(BLKFRASET)
-#endif
-/* RAID */
-COMPATIBLE_IOCTL(RAID_VERSION)
-COMPATIBLE_IOCTL(GET_ARRAY_INFO)
-COMPATIBLE_IOCTL(GET_DISK_INFO)
-COMPATIBLE_IOCTL(PRINT_RAID_DEBUG)
-COMPATIBLE_IOCTL(RAID_AUTORUN)
-COMPATIBLE_IOCTL(CLEAR_ARRAY)
-COMPATIBLE_IOCTL(ADD_NEW_DISK)
-ULONG_IOCTL(HOT_REMOVE_DISK)
-COMPATIBLE_IOCTL(SET_ARRAY_INFO)
-COMPATIBLE_IOCTL(SET_DISK_INFO)
-COMPATIBLE_IOCTL(WRITE_RAID_INFO)
-COMPATIBLE_IOCTL(UNPROTECT_ARRAY)
-COMPATIBLE_IOCTL(PROTECT_ARRAY)
-ULONG_IOCTL(HOT_ADD_DISK)
-ULONG_IOCTL(SET_DISK_FAULTY)
-COMPATIBLE_IOCTL(RUN_ARRAY)
-COMPATIBLE_IOCTL(STOP_ARRAY)
-COMPATIBLE_IOCTL(STOP_ARRAY_RO)
-COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
-COMPATIBLE_IOCTL(GET_BITMAP_FILE)
-ULONG_IOCTL(SET_BITMAP_FILE)
-/* DM */
-COMPATIBLE_IOCTL(DM_VERSION_32)
-COMPATIBLE_IOCTL(DM_REMOVE_ALL_32)
-COMPATIBLE_IOCTL(DM_LIST_DEVICES_32)
-COMPATIBLE_IOCTL(DM_DEV_CREATE_32)
-COMPATIBLE_IOCTL(DM_DEV_REMOVE_32)
-COMPATIBLE_IOCTL(DM_DEV_RENAME_32)
-COMPATIBLE_IOCTL(DM_DEV_SUSPEND_32)
-COMPATIBLE_IOCTL(DM_DEV_STATUS_32)
-COMPATIBLE_IOCTL(DM_DEV_WAIT_32)
-COMPATIBLE_IOCTL(DM_TABLE_LOAD_32)
-COMPATIBLE_IOCTL(DM_TABLE_CLEAR_32)
-COMPATIBLE_IOCTL(DM_TABLE_DEPS_32)
-COMPATIBLE_IOCTL(DM_TABLE_STATUS_32)
-COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32)
-COMPATIBLE_IOCTL(DM_TARGET_MSG_32)
-COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32)
-COMPATIBLE_IOCTL(DM_VERSION)
-COMPATIBLE_IOCTL(DM_REMOVE_ALL)
-COMPATIBLE_IOCTL(DM_LIST_DEVICES)
-COMPATIBLE_IOCTL(DM_DEV_CREATE)
-COMPATIBLE_IOCTL(DM_DEV_REMOVE)
-COMPATIBLE_IOCTL(DM_DEV_RENAME)
-COMPATIBLE_IOCTL(DM_DEV_SUSPEND)
-COMPATIBLE_IOCTL(DM_DEV_STATUS)
-COMPATIBLE_IOCTL(DM_DEV_WAIT)
-COMPATIBLE_IOCTL(DM_TABLE_LOAD)
-COMPATIBLE_IOCTL(DM_TABLE_CLEAR)
-COMPATIBLE_IOCTL(DM_TABLE_DEPS)
-COMPATIBLE_IOCTL(DM_TABLE_STATUS)
-COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
-COMPATIBLE_IOCTL(DM_TARGET_MSG)
-COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY)
-/* Big K */
-COMPATIBLE_IOCTL(PIO_FONT)
-COMPATIBLE_IOCTL(GIO_FONT)
-ULONG_IOCTL(KDSIGACCEPT)
-COMPATIBLE_IOCTL(KDGETKEYCODE)
-COMPATIBLE_IOCTL(KDSETKEYCODE)
-ULONG_IOCTL(KIOCSOUND)
-ULONG_IOCTL(KDMKTONE)
-COMPATIBLE_IOCTL(KDGKBTYPE)
-ULONG_IOCTL(KDSETMODE)
-COMPATIBLE_IOCTL(KDGETMODE)
-ULONG_IOCTL(KDSKBMODE)
-COMPATIBLE_IOCTL(KDGKBMODE)
-ULONG_IOCTL(KDSKBMETA)
-COMPATIBLE_IOCTL(KDGKBMETA)
-COMPATIBLE_IOCTL(KDGKBENT)
-COMPATIBLE_IOCTL(KDSKBENT)
-COMPATIBLE_IOCTL(KDGKBSENT)
-COMPATIBLE_IOCTL(KDSKBSENT)
-COMPATIBLE_IOCTL(KDGKBDIACR)
-COMPATIBLE_IOCTL(KDSKBDIACR)
-COMPATIBLE_IOCTL(KDKBDREP)
-COMPATIBLE_IOCTL(KDGKBLED)
-ULONG_IOCTL(KDSKBLED)
-COMPATIBLE_IOCTL(KDGETLED)
-ULONG_IOCTL(KDSETLED)
-COMPATIBLE_IOCTL(GIO_SCRNMAP)
-COMPATIBLE_IOCTL(PIO_SCRNMAP)
-COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
-COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
-COMPATIBLE_IOCTL(PIO_FONTRESET)
-COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
-/* Big S */
-COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
-COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
-COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
-COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
-COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
-COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
-COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
-COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
-/* Big T */
-COMPATIBLE_IOCTL(TUNSETNOCSUM)
-COMPATIBLE_IOCTL(TUNSETDEBUG)
-COMPATIBLE_IOCTL(TUNSETPERSIST)
-COMPATIBLE_IOCTL(TUNSETOWNER)
-/* Big V */
-COMPATIBLE_IOCTL(VT_SETMODE)
-COMPATIBLE_IOCTL(VT_GETMODE)
-COMPATIBLE_IOCTL(VT_GETSTATE)
-COMPATIBLE_IOCTL(VT_OPENQRY)
-ULONG_IOCTL(VT_ACTIVATE)
-ULONG_IOCTL(VT_WAITACTIVE)
-ULONG_IOCTL(VT_RELDISP)
-ULONG_IOCTL(VT_DISALLOCATE)
-COMPATIBLE_IOCTL(VT_RESIZE)
-COMPATIBLE_IOCTL(VT_RESIZEX)
-COMPATIBLE_IOCTL(VT_LOCKSWITCH)
-COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
-COMPATIBLE_IOCTL(VT_GETHIFONTMASK)
-/* Little p (/dev/rtc, /dev/envctrl, etc.) */
-COMPATIBLE_IOCTL(RTC_AIE_ON)
-COMPATIBLE_IOCTL(RTC_AIE_OFF)
-COMPATIBLE_IOCTL(RTC_UIE_ON)
-COMPATIBLE_IOCTL(RTC_UIE_OFF)
-COMPATIBLE_IOCTL(RTC_PIE_ON)
-COMPATIBLE_IOCTL(RTC_PIE_OFF)
-COMPATIBLE_IOCTL(RTC_WIE_ON)
-COMPATIBLE_IOCTL(RTC_WIE_OFF)
-COMPATIBLE_IOCTL(RTC_ALM_SET)
-COMPATIBLE_IOCTL(RTC_ALM_READ)
-COMPATIBLE_IOCTL(RTC_RD_TIME)
-COMPATIBLE_IOCTL(RTC_SET_TIME)
-COMPATIBLE_IOCTL(RTC_WKALM_SET)
-COMPATIBLE_IOCTL(RTC_WKALM_RD)
-/*
- * These two are only for the sbus rtc driver, but
- * hwclock tries them on every rtc device first when
- * running on sparc.  On other architectures the entries
- * are useless but harmless.
- */
-COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
-COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
-/* Little m */
-COMPATIBLE_IOCTL(MTIOCTOP)
-/* Socket level stuff */
-COMPATIBLE_IOCTL(FIOQSIZE)
-COMPATIBLE_IOCTL(FIOSETOWN)
-COMPATIBLE_IOCTL(SIOCSPGRP)
-COMPATIBLE_IOCTL(FIOGETOWN)
-COMPATIBLE_IOCTL(SIOCGPGRP)
-COMPATIBLE_IOCTL(SIOCATMARK)
-COMPATIBLE_IOCTL(SIOCSIFLINK)
-COMPATIBLE_IOCTL(SIOCSIFENCAP)
-COMPATIBLE_IOCTL(SIOCGIFENCAP)
-COMPATIBLE_IOCTL(SIOCSIFNAME)
-COMPATIBLE_IOCTL(SIOCSARP)
-COMPATIBLE_IOCTL(SIOCGARP)
-COMPATIBLE_IOCTL(SIOCDARP)
-COMPATIBLE_IOCTL(SIOCSRARP)
-COMPATIBLE_IOCTL(SIOCGRARP)
-COMPATIBLE_IOCTL(SIOCDRARP)
-COMPATIBLE_IOCTL(SIOCADDDLCI)
-COMPATIBLE_IOCTL(SIOCDELDLCI)
-COMPATIBLE_IOCTL(SIOCGMIIPHY)
-COMPATIBLE_IOCTL(SIOCGMIIREG)
-COMPATIBLE_IOCTL(SIOCSMIIREG)
-COMPATIBLE_IOCTL(SIOCGIFVLAN)
-COMPATIBLE_IOCTL(SIOCSIFVLAN)
-COMPATIBLE_IOCTL(SIOCBRADDBR)
-COMPATIBLE_IOCTL(SIOCBRDELBR)
-/* SG stuff */
-COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
-COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
-COMPATIBLE_IOCTL(SG_EMULATED_HOST)
-ULONG_IOCTL(SG_SET_TRANSFORM)
-COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
-COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
-COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
-COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
-COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
-COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
-COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
-COMPATIBLE_IOCTL(SG_GET_PACK_ID)
-COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
-COMPATIBLE_IOCTL(SG_SET_DEBUG)
-COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
-COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
-COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
-COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
-COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
-COMPATIBLE_IOCTL(SG_SCSI_RESET)
-COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
-COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
-COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
-/* PPP stuff */
-COMPATIBLE_IOCTL(PPPIOCGFLAGS)
-COMPATIBLE_IOCTL(PPPIOCSFLAGS)
-COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCGUNIT)
-COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCGMRU)
-COMPATIBLE_IOCTL(PPPIOCSMRU)
-COMPATIBLE_IOCTL(PPPIOCSMAXCID)
-COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
-/* PPPIOCSCOMPRESS is translated */
-COMPATIBLE_IOCTL(PPPIOCGNPMODE)
-COMPATIBLE_IOCTL(PPPIOCSNPMODE)
-COMPATIBLE_IOCTL(PPPIOCGDEBUG)
-COMPATIBLE_IOCTL(PPPIOCSDEBUG)
-/* PPPIOCSPASS is translated */
-/* PPPIOCSACTIVE is translated */
-/* PPPIOCGIDLE is translated */
-COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
-COMPATIBLE_IOCTL(PPPIOCATTACH)
-COMPATIBLE_IOCTL(PPPIOCDETACH)
-COMPATIBLE_IOCTL(PPPIOCSMRRU)
-COMPATIBLE_IOCTL(PPPIOCCONNECT)
-COMPATIBLE_IOCTL(PPPIOCDISCONN)
-COMPATIBLE_IOCTL(PPPIOCATTCHAN)
-COMPATIBLE_IOCTL(PPPIOCGCHAN)
-/* PPPOX */
-COMPATIBLE_IOCTL(PPPOEIOCSFWD)
-COMPATIBLE_IOCTL(PPPOEIOCDFWD)
-/* LP */
-COMPATIBLE_IOCTL(LPGETSTATUS)
-/* ppdev */
-COMPATIBLE_IOCTL(PPSETMODE)
-COMPATIBLE_IOCTL(PPRSTATUS)
-COMPATIBLE_IOCTL(PPRCONTROL)
-COMPATIBLE_IOCTL(PPWCONTROL)
-COMPATIBLE_IOCTL(PPFCONTROL)
-COMPATIBLE_IOCTL(PPRDATA)
-COMPATIBLE_IOCTL(PPWDATA)
-COMPATIBLE_IOCTL(PPCLAIM)
-COMPATIBLE_IOCTL(PPRELEASE)
-COMPATIBLE_IOCTL(PPYIELD)
-COMPATIBLE_IOCTL(PPEXCL)
-COMPATIBLE_IOCTL(PPDATADIR)
-COMPATIBLE_IOCTL(PPNEGOT)
-COMPATIBLE_IOCTL(PPWCTLONIRQ)
-COMPATIBLE_IOCTL(PPCLRIRQ)
-COMPATIBLE_IOCTL(PPSETPHASE)
-COMPATIBLE_IOCTL(PPGETMODES)
-COMPATIBLE_IOCTL(PPGETMODE)
-COMPATIBLE_IOCTL(PPGETPHASE)
-COMPATIBLE_IOCTL(PPGETFLAGS)
-COMPATIBLE_IOCTL(PPSETFLAGS)
-/* CDROM stuff */
-COMPATIBLE_IOCTL(CDROMPAUSE)
-COMPATIBLE_IOCTL(CDROMRESUME)
-COMPATIBLE_IOCTL(CDROMPLAYMSF)
-COMPATIBLE_IOCTL(CDROMPLAYTRKIND)
-COMPATIBLE_IOCTL(CDROMREADTOCHDR)
-COMPATIBLE_IOCTL(CDROMREADTOCENTRY)
-COMPATIBLE_IOCTL(CDROMSTOP)
-COMPATIBLE_IOCTL(CDROMSTART)
-COMPATIBLE_IOCTL(CDROMEJECT)
-COMPATIBLE_IOCTL(CDROMVOLCTRL)
-COMPATIBLE_IOCTL(CDROMSUBCHNL)
-ULONG_IOCTL(CDROMEJECT_SW)
-COMPATIBLE_IOCTL(CDROMMULTISESSION)
-COMPATIBLE_IOCTL(CDROM_GET_MCN)
-COMPATIBLE_IOCTL(CDROMRESET)
-COMPATIBLE_IOCTL(CDROMVOLREAD)
-COMPATIBLE_IOCTL(CDROMSEEK)
-COMPATIBLE_IOCTL(CDROMPLAYBLK)
-COMPATIBLE_IOCTL(CDROMCLOSETRAY)
-ULONG_IOCTL(CDROM_SET_OPTIONS)
-ULONG_IOCTL(CDROM_CLEAR_OPTIONS)
-ULONG_IOCTL(CDROM_SELECT_SPEED)
-ULONG_IOCTL(CDROM_SELECT_DISC)
-ULONG_IOCTL(CDROM_MEDIA_CHANGED)
-ULONG_IOCTL(CDROM_DRIVE_STATUS)
-COMPATIBLE_IOCTL(CDROM_DISC_STATUS)
-COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
-ULONG_IOCTL(CDROM_LOCKDOOR)
-ULONG_IOCTL(CDROM_DEBUG)
-COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
-/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
- * not take a struct cdrom_read, instead they take a struct cdrom_msf
- * which is compatible.
- */
-COMPATIBLE_IOCTL(CDROMREADMODE2)
-COMPATIBLE_IOCTL(CDROMREADMODE1)
-COMPATIBLE_IOCTL(CDROMREADRAW)
-COMPATIBLE_IOCTL(CDROMREADCOOKED)
-COMPATIBLE_IOCTL(CDROMREADALL)
-/* DVD ioctls */
-COMPATIBLE_IOCTL(DVD_READ_STRUCT)
-COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
-COMPATIBLE_IOCTL(DVD_AUTH)
-/* pktcdvd */
-COMPATIBLE_IOCTL(PACKET_CTRL_CMD)
-/* Big A */
-/* sparc only */
-/* Big Q for sound/OSS */
-COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
-COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE)
-COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS)
-COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD)
-COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL)
-COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND)
-COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME)
-COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID)
-COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL)
-COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE)
-/* Big T for sound/OSS */
-COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE)
-COMPATIBLE_IOCTL(SNDCTL_TMR_START)
-COMPATIBLE_IOCTL(SNDCTL_TMR_STOP)
-COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE)
-COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO)
-COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE)
-COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME)
-COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT)
-/* Little m for sound/OSS */
-COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME)
-COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE)
-COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD)
-/* Big P for sound/OSS */
-COMPATIBLE_IOCTL(SNDCTL_DSP_RESET)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED)
-COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE)
-COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS)
-COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER)
-COMPATIBLE_IOCTL(SNDCTL_DSP_POST)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE)
-COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR)
-/* SNDCTL_DSP_MAPINBUF,  XXX needs translation */
-/* SNDCTL_DSP_MAPOUTBUF,  XXX needs translation */
-COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO)
-COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX)
-COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY)
-COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE)
-COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE)
-COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS)
-COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS)
-COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER)
-/* Big C for sound/OSS */
-COMPATIBLE_IOCTL(SNDCTL_COPR_RESET)
-COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD)
-COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA)
-COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE)
-COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA)
-COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE)
-COMPATIBLE_IOCTL(SNDCTL_COPR_RUN)
-COMPATIBLE_IOCTL(SNDCTL_COPR_HALT)
-COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG)
-COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG)
-/* Big M for sound/OSS */
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO))
-COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR))
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE)
-/* SOUND_MIXER_READ_ENHANCE,  same value as READ_MUTE */
-/* SOUND_MIXER_READ_LOUD,  same value as READ_MUTE */
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS)
-COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2)
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3)
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO))
-COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR))
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE)
-/* SOUND_MIXER_WRITE_ENHANCE,  same value as WRITE_MUTE */
-/* SOUND_MIXER_WRITE_LOUD,  same value as WRITE_MUTE */
-COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC)
-COMPATIBLE_IOCTL(SOUND_MIXER_INFO)
-COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO)
-COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS)
-COMPATIBLE_IOCTL(SOUND_MIXER_AGC)
-COMPATIBLE_IOCTL(SOUND_MIXER_3DSE)
-COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1)
-COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2)
-COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3)
-COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4)
-COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
-COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
-COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
-COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* AUTOFS */
-ULONG_IOCTL(AUTOFS_IOC_READY)
-ULONG_IOCTL(AUTOFS_IOC_FAIL)
-COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
-/* Raw devices */
-COMPATIBLE_IOCTL(RAW_SETBIND)
-COMPATIBLE_IOCTL(RAW_GETBIND)
-/* SMB ioctls which do not need any translations */
-COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
-/* Little a */
-COMPATIBLE_IOCTL(ATMSIGD_CTRL)
-COMPATIBLE_IOCTL(ATMARPD_CTRL)
-COMPATIBLE_IOCTL(ATMLEC_CTRL)
-COMPATIBLE_IOCTL(ATMLEC_MCAST)
-COMPATIBLE_IOCTL(ATMLEC_DATA)
-COMPATIBLE_IOCTL(ATM_SETSC)
-COMPATIBLE_IOCTL(SIOCSIFATMTCP)
-COMPATIBLE_IOCTL(SIOCMKCLIP)
-COMPATIBLE_IOCTL(ATMARP_MKIP)
-COMPATIBLE_IOCTL(ATMARP_SETENTRY)
-COMPATIBLE_IOCTL(ATMARP_ENCAP)
-COMPATIBLE_IOCTL(ATMTCP_CREATE)
-COMPATIBLE_IOCTL(ATMTCP_REMOVE)
-COMPATIBLE_IOCTL(ATMMPC_CTRL)
-COMPATIBLE_IOCTL(ATMMPC_DATA)
-/* Watchdog */
-COMPATIBLE_IOCTL(WDIOC_GETSUPPORT)
-COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
-COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
-COMPATIBLE_IOCTL(WDIOC_GETTEMP)
-COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
-COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
-COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT)
-COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT)
-/* Big R */
-COMPATIBLE_IOCTL(RNDGETENTCNT)
-COMPATIBLE_IOCTL(RNDADDTOENTCNT)
-COMPATIBLE_IOCTL(RNDGETPOOL)
-COMPATIBLE_IOCTL(RNDADDENTROPY)
-COMPATIBLE_IOCTL(RNDZAPENTCNT)
-COMPATIBLE_IOCTL(RNDCLEARPOOL)
-/* Bluetooth */
-COMPATIBLE_IOCTL(HCIDEVUP)
-COMPATIBLE_IOCTL(HCIDEVDOWN)
-COMPATIBLE_IOCTL(HCIDEVRESET)
-COMPATIBLE_IOCTL(HCIDEVRESTAT)
-COMPATIBLE_IOCTL(HCIGETDEVLIST)
-COMPATIBLE_IOCTL(HCIGETDEVINFO)
-COMPATIBLE_IOCTL(HCIGETCONNLIST)
-COMPATIBLE_IOCTL(HCIGETCONNINFO)
-COMPATIBLE_IOCTL(HCISETRAW)
-COMPATIBLE_IOCTL(HCISETSCAN)
-COMPATIBLE_IOCTL(HCISETAUTH)
-COMPATIBLE_IOCTL(HCISETENCRYPT)
-COMPATIBLE_IOCTL(HCISETPTYPE)
-COMPATIBLE_IOCTL(HCISETLINKPOL)
-COMPATIBLE_IOCTL(HCISETLINKMODE)
-COMPATIBLE_IOCTL(HCISETACLMTU)
-COMPATIBLE_IOCTL(HCISETSCOMTU)
-COMPATIBLE_IOCTL(HCIINQUIRY)
-COMPATIBLE_IOCTL(HCIUARTSETPROTO)
-COMPATIBLE_IOCTL(HCIUARTGETPROTO)
-COMPATIBLE_IOCTL(RFCOMMCREATEDEV)
-COMPATIBLE_IOCTL(RFCOMMRELEASEDEV)
-COMPATIBLE_IOCTL(RFCOMMGETDEVLIST)
-COMPATIBLE_IOCTL(RFCOMMGETDEVINFO)
-COMPATIBLE_IOCTL(RFCOMMSTEALDLC)
-COMPATIBLE_IOCTL(BNEPCONNADD)
-COMPATIBLE_IOCTL(BNEPCONNDEL)
-COMPATIBLE_IOCTL(BNEPGETCONNLIST)
-COMPATIBLE_IOCTL(BNEPGETCONNINFO)
-COMPATIBLE_IOCTL(CMTPCONNADD)
-COMPATIBLE_IOCTL(CMTPCONNDEL)
-COMPATIBLE_IOCTL(CMTPGETCONNLIST)
-COMPATIBLE_IOCTL(CMTPGETCONNINFO)
-COMPATIBLE_IOCTL(HIDPCONNADD)
-COMPATIBLE_IOCTL(HIDPCONNDEL)
-COMPATIBLE_IOCTL(HIDPGETCONNLIST)
-COMPATIBLE_IOCTL(HIDPGETCONNINFO)
-/* CAPI */
-COMPATIBLE_IOCTL(CAPI_REGISTER)
-COMPATIBLE_IOCTL(CAPI_GET_MANUFACTURER)
-COMPATIBLE_IOCTL(CAPI_GET_VERSION)
-COMPATIBLE_IOCTL(CAPI_GET_SERIAL)
-COMPATIBLE_IOCTL(CAPI_GET_PROFILE)
-COMPATIBLE_IOCTL(CAPI_MANUFACTURER_CMD)
-COMPATIBLE_IOCTL(CAPI_GET_ERRCODE)
-COMPATIBLE_IOCTL(CAPI_INSTALLED)
-COMPATIBLE_IOCTL(CAPI_GET_FLAGS)
-COMPATIBLE_IOCTL(CAPI_SET_FLAGS)
-COMPATIBLE_IOCTL(CAPI_CLR_FLAGS)
-COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT)
-COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT)
-/* Siemens Gigaset */
-COMPATIBLE_IOCTL(GIGASET_REDIR)
-COMPATIBLE_IOCTL(GIGASET_CONFIG)
-COMPATIBLE_IOCTL(GIGASET_BRKCHARS)
-COMPATIBLE_IOCTL(GIGASET_VERSION)
-/* Misc. */
-COMPATIBLE_IOCTL(0x41545900)           /* ATYIO_CLKR */
-COMPATIBLE_IOCTL(0x41545901)           /* ATYIO_CLKW */
-COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
-COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
-COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
-COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
-/* USB */
-COMPATIBLE_IOCTL(USBDEVFS_RESETEP)
-COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION)
-COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER)
-COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB)
-COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
-COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
-COMPATIBLE_IOCTL(USBDEVFS_RESET)
-COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32)
-COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
-COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
-COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
-/* MTD */
-COMPATIBLE_IOCTL(MEMGETINFO)
-COMPATIBLE_IOCTL(MEMERASE)
-COMPATIBLE_IOCTL(MEMLOCK)
-COMPATIBLE_IOCTL(MEMUNLOCK)
-COMPATIBLE_IOCTL(MEMGETREGIONCOUNT)
-COMPATIBLE_IOCTL(MEMGETREGIONINFO)
-COMPATIBLE_IOCTL(MEMGETBADBLOCK)
-COMPATIBLE_IOCTL(MEMSETBADBLOCK)
-/* NBD */
-ULONG_IOCTL(NBD_SET_SOCK)
-ULONG_IOCTL(NBD_SET_BLKSIZE)
-ULONG_IOCTL(NBD_SET_SIZE)
-COMPATIBLE_IOCTL(NBD_DO_IT)
-COMPATIBLE_IOCTL(NBD_CLEAR_SOCK)
-COMPATIBLE_IOCTL(NBD_CLEAR_QUE)
-COMPATIBLE_IOCTL(NBD_PRINT_DEBUG)
-ULONG_IOCTL(NBD_SET_SIZE_BLOCKS)
-COMPATIBLE_IOCTL(NBD_DISCONNECT)
-/* i2c */
-COMPATIBLE_IOCTL(I2C_SLAVE)
-COMPATIBLE_IOCTL(I2C_SLAVE_FORCE)
-COMPATIBLE_IOCTL(I2C_TENBIT)
-COMPATIBLE_IOCTL(I2C_PEC)
-COMPATIBLE_IOCTL(I2C_RETRIES)
-COMPATIBLE_IOCTL(I2C_TIMEOUT)
-/* wireless */
-COMPATIBLE_IOCTL(SIOCSIWCOMMIT)
-COMPATIBLE_IOCTL(SIOCGIWNAME)
-COMPATIBLE_IOCTL(SIOCSIWNWID)
-COMPATIBLE_IOCTL(SIOCGIWNWID)
-COMPATIBLE_IOCTL(SIOCSIWFREQ)
-COMPATIBLE_IOCTL(SIOCGIWFREQ)
-COMPATIBLE_IOCTL(SIOCSIWMODE)
-COMPATIBLE_IOCTL(SIOCGIWMODE)
-COMPATIBLE_IOCTL(SIOCSIWSENS)
-COMPATIBLE_IOCTL(SIOCGIWSENS)
-COMPATIBLE_IOCTL(SIOCSIWRANGE)
-COMPATIBLE_IOCTL(SIOCSIWPRIV)
-COMPATIBLE_IOCTL(SIOCGIWPRIV)
-COMPATIBLE_IOCTL(SIOCSIWSTATS)
-COMPATIBLE_IOCTL(SIOCGIWSTATS)
-COMPATIBLE_IOCTL(SIOCSIWAP)
-COMPATIBLE_IOCTL(SIOCGIWAP)
-COMPATIBLE_IOCTL(SIOCSIWSCAN)
-COMPATIBLE_IOCTL(SIOCSIWRATE)
-COMPATIBLE_IOCTL(SIOCGIWRATE)
-COMPATIBLE_IOCTL(SIOCSIWRTS)
-COMPATIBLE_IOCTL(SIOCGIWRTS)
-COMPATIBLE_IOCTL(SIOCSIWFRAG)
-COMPATIBLE_IOCTL(SIOCGIWFRAG)
-COMPATIBLE_IOCTL(SIOCSIWTXPOW)
-COMPATIBLE_IOCTL(SIOCGIWTXPOW)
-COMPATIBLE_IOCTL(SIOCSIWRETRY)
-COMPATIBLE_IOCTL(SIOCGIWRETRY)
-COMPATIBLE_IOCTL(SIOCSIWPOWER)
-COMPATIBLE_IOCTL(SIOCGIWPOWER)
-/* hiddev */
-COMPATIBLE_IOCTL(HIDIOCGVERSION)
-COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
-COMPATIBLE_IOCTL(HIDIOCGDEVINFO)
-COMPATIBLE_IOCTL(HIDIOCGSTRING)
-COMPATIBLE_IOCTL(HIDIOCINITREPORT)
-COMPATIBLE_IOCTL(HIDIOCGREPORT)
-COMPATIBLE_IOCTL(HIDIOCSREPORT)
-COMPATIBLE_IOCTL(HIDIOCGREPORTINFO)
-COMPATIBLE_IOCTL(HIDIOCGFIELDINFO)
-COMPATIBLE_IOCTL(HIDIOCGUSAGE)
-COMPATIBLE_IOCTL(HIDIOCSUSAGE)
-COMPATIBLE_IOCTL(HIDIOCGUCODE)
-COMPATIBLE_IOCTL(HIDIOCGFLAG)
-COMPATIBLE_IOCTL(HIDIOCSFLAG)
-COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
-COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
-/* dvb */
-COMPATIBLE_IOCTL(AUDIO_STOP)
-COMPATIBLE_IOCTL(AUDIO_PLAY)
-COMPATIBLE_IOCTL(AUDIO_PAUSE)
-COMPATIBLE_IOCTL(AUDIO_CONTINUE)
-COMPATIBLE_IOCTL(AUDIO_SELECT_SOURCE)
-COMPATIBLE_IOCTL(AUDIO_SET_MUTE)
-COMPATIBLE_IOCTL(AUDIO_SET_AV_SYNC)
-COMPATIBLE_IOCTL(AUDIO_SET_BYPASS_MODE)
-COMPATIBLE_IOCTL(AUDIO_CHANNEL_SELECT)
-COMPATIBLE_IOCTL(AUDIO_GET_STATUS)
-COMPATIBLE_IOCTL(AUDIO_GET_CAPABILITIES)
-COMPATIBLE_IOCTL(AUDIO_CLEAR_BUFFER)
-COMPATIBLE_IOCTL(AUDIO_SET_ID)
-COMPATIBLE_IOCTL(AUDIO_SET_MIXER)
-COMPATIBLE_IOCTL(AUDIO_SET_STREAMTYPE)
-COMPATIBLE_IOCTL(AUDIO_SET_EXT_ID)
-COMPATIBLE_IOCTL(AUDIO_SET_ATTRIBUTES)
-COMPATIBLE_IOCTL(AUDIO_SET_KARAOKE)
-COMPATIBLE_IOCTL(DMX_START)
-COMPATIBLE_IOCTL(DMX_STOP)
-COMPATIBLE_IOCTL(DMX_SET_FILTER)
-COMPATIBLE_IOCTL(DMX_SET_PES_FILTER)
-COMPATIBLE_IOCTL(DMX_SET_BUFFER_SIZE)
-COMPATIBLE_IOCTL(DMX_GET_PES_PIDS)
-COMPATIBLE_IOCTL(DMX_GET_CAPS)
-COMPATIBLE_IOCTL(DMX_SET_SOURCE)
-COMPATIBLE_IOCTL(DMX_GET_STC)
-COMPATIBLE_IOCTL(FE_GET_INFO)
-COMPATIBLE_IOCTL(FE_DISEQC_RESET_OVERLOAD)
-COMPATIBLE_IOCTL(FE_DISEQC_SEND_MASTER_CMD)
-COMPATIBLE_IOCTL(FE_DISEQC_RECV_SLAVE_REPLY)
-COMPATIBLE_IOCTL(FE_DISEQC_SEND_BURST)
-COMPATIBLE_IOCTL(FE_SET_TONE)
-COMPATIBLE_IOCTL(FE_SET_VOLTAGE)
-COMPATIBLE_IOCTL(FE_ENABLE_HIGH_LNB_VOLTAGE)
-COMPATIBLE_IOCTL(FE_READ_STATUS)
-COMPATIBLE_IOCTL(FE_READ_BER)
-COMPATIBLE_IOCTL(FE_READ_SIGNAL_STRENGTH)
-COMPATIBLE_IOCTL(FE_READ_SNR)
-COMPATIBLE_IOCTL(FE_READ_UNCORRECTED_BLOCKS)
-COMPATIBLE_IOCTL(FE_SET_FRONTEND)
-COMPATIBLE_IOCTL(FE_GET_FRONTEND)
-COMPATIBLE_IOCTL(FE_GET_EVENT)
-COMPATIBLE_IOCTL(FE_DISHNETWORK_SEND_LEGACY_CMD)
-COMPATIBLE_IOCTL(VIDEO_STOP)
-COMPATIBLE_IOCTL(VIDEO_PLAY)
-COMPATIBLE_IOCTL(VIDEO_FREEZE)
-COMPATIBLE_IOCTL(VIDEO_CONTINUE)
-COMPATIBLE_IOCTL(VIDEO_SELECT_SOURCE)
-COMPATIBLE_IOCTL(VIDEO_SET_BLANK)
-COMPATIBLE_IOCTL(VIDEO_GET_STATUS)
-COMPATIBLE_IOCTL(VIDEO_SET_DISPLAY_FORMAT)
-COMPATIBLE_IOCTL(VIDEO_FAST_FORWARD)
-COMPATIBLE_IOCTL(VIDEO_SLOWMOTION)
-COMPATIBLE_IOCTL(VIDEO_GET_CAPABILITIES)
-COMPATIBLE_IOCTL(VIDEO_CLEAR_BUFFER)
-COMPATIBLE_IOCTL(VIDEO_SET_ID)
-COMPATIBLE_IOCTL(VIDEO_SET_STREAMTYPE)
-COMPATIBLE_IOCTL(VIDEO_SET_FORMAT)
-COMPATIBLE_IOCTL(VIDEO_SET_SYSTEM)
-COMPATIBLE_IOCTL(VIDEO_SET_HIGHLIGHT)
-COMPATIBLE_IOCTL(VIDEO_SET_SPU)
-COMPATIBLE_IOCTL(VIDEO_GET_NAVI)
-COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
-COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
-COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
index a9f794716a8105f62f7a85e16dd7b240c94d535a..03ec2311fb29c9ce4d252e2e9b41b8eea19e8e18 100644 (file)
@@ -40,3 +40,4 @@
 #define  noinline                      __attribute__((noinline))
 #define __attribute_pure__             __attribute__((pure))
 #define __attribute_const__            __attribute__((__const__))
+#define __maybe_unused                 __attribute__((unused))
index ecd621fd27d2415376ea1d123b353edfd2ee7843..a9e2863c2dbf058a97b62ccf18af83bf8a1145c2 100644 (file)
@@ -4,9 +4,11 @@
 #include <linux/compiler-gcc.h>
 
 #if __GNUC_MINOR__ >= 3
-# define __attribute_used__    __attribute__((__used__))
+# define __used                        __attribute__((__used__))
+# define __attribute_used__    __used                          /* deprecated */
 #else
-# define __attribute_used__    __attribute__((__unused__))
+# define __used                        __attribute__((__unused__))
+# define __attribute_used__    __used                          /* deprecated */
 #endif
 
 #if __GNUC_MINOR__ >= 4
index fd0cc7c4a636e77dbf5a502b31b85f760cb088e9..a03e9398a6c2ba0d986405f8bec84f7f0141b786 100644 (file)
@@ -12,7 +12,8 @@
 # define __inline              __inline        __attribute__((always_inline))
 #endif
 
-#define __attribute_used__     __attribute__((__used__))
+#define __used                 __attribute__((__used__))
+#define __attribute_used__     __used                  /* deprecated */
 #define __must_check           __attribute__((warn_unused_result))
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
 #define __always_inline                inline __attribute__((always_inline))
index 3b6949b417451d16145d9117c3ad72fa8cb654b6..498c35920762e2e4a10ff61b1e01f9d27298e7dc 100644 (file)
@@ -108,15 +108,30 @@ extern void __chk_io_ptr(const void __iomem *);
  * Allow us to avoid 'defined but not used' warnings on functions and data,
  * as well as force them to be emitted to the assembly file.
  *
- * As of gcc 3.3, static functions that are not marked with attribute((used))
- * may be elided from the assembly file.  As of gcc 3.3, static data not so
+ * As of gcc 3.4, static functions that are not marked with attribute((used))
+ * may be elided from the assembly file.  As of gcc 3.4, static data not so
  * marked will not be elided, but this may change in a future gcc version.
  *
+ * NOTE: Because distributions shipped with a backported unit-at-a-time
+ * compiler in gcc 3.3, we must define __used to be __attribute__((used))
+ * for gcc >=3.3 instead of 3.4.
+ *
  * In prior versions of gcc, such functions and data would be emitted, but
  * would be warned about except with attribute((unused)).
+ *
+ * Mark functions that are referenced only in inline assembly as __used so
+ * the code is emitted even though it appears to be unreferenced.
  */
 #ifndef __attribute_used__
-# define __attribute_used__    /* unimplemented */
+# define __attribute_used__    /* deprecated */
+#endif
+
+#ifndef __used
+# define __used                        /* unimplemented */
+#endif
+
+#ifndef __maybe_unused
+# define __maybe_unused                /* unimplemented */
 #endif
 
 /*
index de25ee3b79196b1daa7d95ccb871f32652eb1a8a..62ef6e11d0d25cb49fc5c33951a89c8d2e8b62b3 100644 (file)
@@ -51,7 +51,7 @@ struct consw {
        int     (*con_scrolldelta)(struct vc_data *, int);
        int     (*con_set_origin)(struct vc_data *);
        void    (*con_save_screen)(struct vc_data *);
-       u8      (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8);
+       u8      (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8, u8);
        void    (*con_invert_region)(struct vc_data *, u16 *, int);
        u16    *(*con_screen_pos)(struct vc_data *, int);
        unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
@@ -92,9 +92,8 @@ void give_up_console(const struct consw *sw);
 #define CON_BOOT       (8)
 #define CON_ANYTIME    (16) /* Safe to call when cpu is offline */
 
-struct console
-{
-       char    name[8];
+struct console {
+       char    name[16];
        void    (*write)(struct console *, const char *, unsigned);
        int     (*read)(struct console *, char *, unsigned);
        struct tty_driver *(*device)(struct console *, int *);
index a86162b26c0dde5a349a81129e67b74f1506d821..a461f76fb004e874f38ec245c6a6834b333a5004 100644 (file)
@@ -37,6 +37,7 @@ struct vc_data {
        unsigned char   vc_color;               /* Foreground & background */
        unsigned char   vc_s_color;             /* Saved foreground & background */
        unsigned char   vc_ulcolor;             /* Color for underline mode */
+       unsigned char   vc_itcolor;
        unsigned char   vc_halfcolor;           /* Color for half intensity mode */
        /* cursor */
        unsigned int    vc_cursor_type;
@@ -71,10 +72,12 @@ struct vc_data {
        unsigned int    vc_deccolm      : 1;    /* 80/132 Column Mode */
        /* attribute flags */
        unsigned int    vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
+       unsigned int    vc_italic:1;
        unsigned int    vc_underline    : 1;
        unsigned int    vc_blink        : 1;
        unsigned int    vc_reverse      : 1;
        unsigned int    vc_s_intensity  : 2;    /* saved rendition */
+       unsigned int    vc_s_italic:1;
        unsigned int    vc_s_underline  : 1;
        unsigned int    vc_s_blink      : 1;
        unsigned int    vc_s_reverse    : 1;
similarity index 70%
rename from include/asm-x86_64/const.h
rename to include/linux/const.h
index 54fb08f3db9b117479e8d0c315e61f5b7218d4a7..07b300bfe34b01f27d424b7f5c63f43130582f7d 100644 (file)
@@ -1,11 +1,11 @@
 /* const.h: Macros for dealing with constants.  */
 
-#ifndef _X86_64_CONST_H
-#define _X86_64_CONST_H
+#ifndef _LINUX_CONST_H
+#define _LINUX_CONST_H
 
 /* Some constant macros are used in both assembler and
  * C code.  Therefore we cannot annotate them always with
- * 'UL' and other type specificers unilaterally.  We
+ * 'UL' and other type specifiers unilaterally.  We
  * use the following macros to deal with this.
  */
 
@@ -16,5 +16,4 @@
 #define _AC(X,Y)       __AC(X,Y)
 #endif
 
-
-#endif /* !(_X86_64_CONST_H) */
+#endif /* !(_LINUX_CONST_H) */
index c22b0dfcbcd27ba13ab0fee7e15b80d9f1cfb480..3b2df2523f1d79d4ce0d0c2f35e1c0a83df7bd65 100644 (file)
@@ -41,6 +41,9 @@ extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr);
 extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs);
 extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs);
 
+extern struct sysdev_attribute attr_sched_mc_power_savings;
+extern struct sysdev_attribute attr_sched_smt_power_savings;
+extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls);
 
 #ifdef CONFIG_HOTPLUG_CPU
 extern void unregister_cpu(struct cpu *cpu);
index 46d8254c1a792a59d52471723b761482399af3bf..72aa00cc4b2db49e4d036955d6a72d16f6a1b224 100644 (file)
@@ -67,6 +67,8 @@
 #ifndef _LINUX_CYCLADES_H
 #define _LINUX_CYCLADES_H
 
+#include <linux/types.h>
+
 struct cyclades_monitor {
         unsigned long           int_count;
         unsigned long           char_count;
@@ -108,7 +110,6 @@ struct cyclades_idle_stats {
 #define CYZSETPOLLCYCLE                0x43590e
 #define CYZGETPOLLCYCLE                0x43590f
 #define CYGETCD1400VER         0x435910
-#define CYGETCARDINFO          0x435911
 #define        CYSETWAIT               0x435912
 #define        CYGETWAIT               0x435913
 
@@ -149,14 +150,12 @@ struct CYZ_BOOT_CTRL {
  *     architectures and compilers.
  */
 
-#if defined(__alpha__)
-typedef unsigned long  ucdouble;       /* 64 bits, unsigned */
-typedef unsigned int   uclong;         /* 32 bits, unsigned */
-#else
-typedef unsigned long  uclong;         /* 32 bits, unsigned */
-#endif
-typedef unsigned short ucshort;        /* 16 bits, unsigned */
-typedef unsigned char  ucchar;         /* 8 bits, unsigned */
+#include <asm/types.h>
+
+typedef __u64  ucdouble;               /* 64 bits, unsigned */
+typedef __u32  uclong;                 /* 32 bits, unsigned */
+typedef __u16  ucshort;                /* 16 bits, unsigned */
+typedef __u8   ucchar;                 /* 8 bits, unsigned */
 
 /*
  *     Memory Window Sizes
@@ -174,24 +173,24 @@ typedef unsigned char     ucchar;         /* 8 bits, unsigned */
  */
 
 struct CUSTOM_REG {
-       uclong  fpga_id;                /* FPGA Identification Register */
-       uclong  fpga_version;           /* FPGA Version Number Register */
-       uclong  cpu_start;              /* CPU start Register (write) */
-       uclong  cpu_stop;               /* CPU stop Register (write) */
-       uclong  misc_reg;               /* Miscelaneous Register */
-       uclong  idt_mode;               /* IDT mode Register */
-       uclong  uart_irq_status;        /* UART IRQ status Register */
-       uclong  clear_timer0_irq;       /* Clear timer interrupt Register */
-       uclong  clear_timer1_irq;       /* Clear timer interrupt Register */
-       uclong  clear_timer2_irq;       /* Clear timer interrupt Register */
-       uclong  test_register;          /* Test Register */
-       uclong  test_count;             /* Test Count Register */
-       uclong  timer_select;           /* Timer select register */
-       uclong  pr_uart_irq_status;     /* Prioritized UART IRQ stat Reg */
-       uclong  ram_wait_state;         /* RAM wait-state Register */
-       uclong  uart_wait_state;        /* UART wait-state Register */
-       uclong  timer_wait_state;       /* timer wait-state Register */
-       uclong  ack_wait_state;         /* ACK wait State Register */
+       __u32   fpga_id;                /* FPGA Identification Register */
+       __u32   fpga_version;           /* FPGA Version Number Register */
+       __u32   cpu_start;              /* CPU start Register (write) */
+       __u32   cpu_stop;               /* CPU stop Register (write) */
+       __u32   misc_reg;               /* Miscelaneous Register */
+       __u32   idt_mode;               /* IDT mode Register */
+       __u32   uart_irq_status;        /* UART IRQ status Register */
+       __u32   clear_timer0_irq;       /* Clear timer interrupt Register */
+       __u32   clear_timer1_irq;       /* Clear timer interrupt Register */
+       __u32   clear_timer2_irq;       /* Clear timer interrupt Register */
+       __u32   test_register;          /* Test Register */
+       __u32   test_count;             /* Test Count Register */
+       __u32   timer_select;           /* Timer select register */
+       __u32   pr_uart_irq_status;     /* Prioritized UART IRQ stat Reg */
+       __u32   ram_wait_state;         /* RAM wait-state Register */
+       __u32   uart_wait_state;        /* UART wait-state Register */
+       __u32   timer_wait_state;       /* timer wait-state Register */
+       __u32   ack_wait_state;         /* ACK wait State Register */
 };
 
 /*
@@ -201,34 +200,34 @@ struct    CUSTOM_REG {
  */
 
 struct RUNTIME_9060 {
-       uclong  loc_addr_range; /* 00h - Local Address Range */
-       uclong  loc_addr_base;  /* 04h - Local Address Base */
-       uclong  loc_arbitr;     /* 08h - Local Arbitration */
-       uclong  endian_descr;   /* 0Ch - Big/Little Endian Descriptor */
-       uclong  loc_rom_range;  /* 10h - Local ROM Range */
-       uclong  loc_rom_base;   /* 14h - Local ROM Base */
-       uclong  loc_bus_descr;  /* 18h - Local Bus descriptor */
-       uclong  loc_range_mst;  /* 1Ch - Local Range for Master to PCI */
-       uclong  loc_base_mst;   /* 20h - Local Base for Master PCI */
-       uclong  loc_range_io;   /* 24h - Local Range for Master IO */
-       uclong  pci_base_mst;   /* 28h - PCI Base for Master PCI */
-       uclong  pci_conf_io;    /* 2Ch - PCI configuration for Master IO */
-       uclong  filler1;        /* 30h */
-       uclong  filler2;        /* 34h */
-       uclong  filler3;        /* 38h */
-       uclong  filler4;        /* 3Ch */
-       uclong  mail_box_0;     /* 40h - Mail Box 0 */
-       uclong  mail_box_1;     /* 44h - Mail Box 1 */
-       uclong  mail_box_2;     /* 48h - Mail Box 2 */
-       uclong  mail_box_3;     /* 4Ch - Mail Box 3 */
-       uclong  filler5;        /* 50h */
-       uclong  filler6;        /* 54h */
-       uclong  filler7;        /* 58h */
-       uclong  filler8;        /* 5Ch */
-       uclong  pci_doorbell;   /* 60h - PCI to Local Doorbell */
-       uclong  loc_doorbell;   /* 64h - Local to PCI Doorbell */
-       uclong  intr_ctrl_stat; /* 68h - Interrupt Control/Status */
-       uclong  init_ctrl;      /* 6Ch - EEPROM control, Init Control, etc */
+       __u32   loc_addr_range; /* 00h - Local Address Range */
+       __u32   loc_addr_base;  /* 04h - Local Address Base */
+       __u32   loc_arbitr;     /* 08h - Local Arbitration */
+       __u32   endian_descr;   /* 0Ch - Big/Little Endian Descriptor */
+       __u32   loc_rom_range;  /* 10h - Local ROM Range */
+       __u32   loc_rom_base;   /* 14h - Local ROM Base */
+       __u32   loc_bus_descr;  /* 18h - Local Bus descriptor */
+       __u32   loc_range_mst;  /* 1Ch - Local Range for Master to PCI */
+       __u32   loc_base_mst;   /* 20h - Local Base for Master PCI */
+       __u32   loc_range_io;   /* 24h - Local Range for Master IO */
+       __u32   pci_base_mst;   /* 28h - PCI Base for Master PCI */
+       __u32   pci_conf_io;    /* 2Ch - PCI configuration for Master IO */
+       __u32   filler1;        /* 30h */
+       __u32   filler2;        /* 34h */
+       __u32   filler3;        /* 38h */
+       __u32   filler4;        /* 3Ch */
+       __u32   mail_box_0;     /* 40h - Mail Box 0 */
+       __u32   mail_box_1;     /* 44h - Mail Box 1 */
+       __u32   mail_box_2;     /* 48h - Mail Box 2 */
+       __u32   mail_box_3;     /* 4Ch - Mail Box 3 */
+       __u32   filler5;        /* 50h */
+       __u32   filler6;        /* 54h */
+       __u32   filler7;        /* 58h */
+       __u32   filler8;        /* 5Ch */
+       __u32   pci_doorbell;   /* 60h - PCI to Local Doorbell */
+       __u32   loc_doorbell;   /* 64h - Local to PCI Doorbell */
+       __u32   intr_ctrl_stat; /* 68h - Interrupt Control/Status */
+       __u32   init_ctrl;      /* 6Ch - EEPROM control, Init Control, etc */
 };
 
 /* Values for the Local Base Address re-map register */
@@ -270,8 +269,8 @@ struct RUNTIME_9060 {
 #define        ZF_TINACT       ZF_TINACT_DEF
 
 struct FIRM_ID {
-       uclong  signature;              /* ZFIRM/U signature */
-       uclong  zfwctrl_addr;           /* pointer to ZFW_CTRL structure */
+       __u32   signature;              /* ZFIRM/U signature */
+       __u32   zfwctrl_addr;           /* pointer to ZFW_CTRL structure */
 };
 
 /* Op. System id */
@@ -408,24 +407,24 @@ struct    FIRM_ID {
  */
 
 struct CH_CTRL {
-       uclong  op_mode;        /* operation mode */
-       uclong  intr_enable;    /* interrupt masking */
-       uclong  sw_flow;        /* SW flow control */
-       uclong  flow_status;    /* output flow status */
-       uclong  comm_baud;      /* baud rate  - numerically specified */
-       uclong  comm_parity;    /* parity */
-       uclong  comm_data_l;    /* data length/stop */
-       uclong  comm_flags;     /* other flags */
-       uclong  hw_flow;        /* HW flow control */
-       uclong  rs_control;     /* RS-232 outputs */
-       uclong  rs_status;      /* RS-232 inputs */
-       uclong  flow_xon;       /* xon char */
-       uclong  flow_xoff;      /* xoff char */
-       uclong  hw_overflow;    /* hw overflow counter */
-       uclong  sw_overflow;    /* sw overflow counter */
-       uclong  comm_error;     /* frame/parity error counter */
-       uclong ichar;
-       uclong filler[7];
+       __u32   op_mode;        /* operation mode */
+       __u32   intr_enable;    /* interrupt masking */
+       __u32   sw_flow;        /* SW flow control */
+       __u32   flow_status;    /* output flow status */
+       __u32   comm_baud;      /* baud rate  - numerically specified */
+       __u32   comm_parity;    /* parity */
+       __u32   comm_data_l;    /* data length/stop */
+       __u32   comm_flags;     /* other flags */
+       __u32   hw_flow;        /* HW flow control */
+       __u32   rs_control;     /* RS-232 outputs */
+       __u32   rs_status;      /* RS-232 inputs */
+       __u32   flow_xon;       /* xon char */
+       __u32   flow_xoff;      /* xoff char */
+       __u32   hw_overflow;    /* hw overflow counter */
+       __u32   sw_overflow;    /* sw overflow counter */
+       __u32   comm_error;     /* frame/parity error counter */
+       __u32 ichar;
+       __u32 filler[7];
 };
 
 
@@ -435,18 +434,18 @@ struct CH_CTRL {
  */
 
 struct BUF_CTRL        {
-       uclong  flag_dma;       /* buffers are in Host memory */
-       uclong  tx_bufaddr;     /* address of the tx buffer */
-       uclong  tx_bufsize;     /* tx buffer size */
-       uclong  tx_threshold;   /* tx low water mark */
-       uclong  tx_get;         /* tail index tx buf */
-       uclong  tx_put;         /* head index tx buf */
-       uclong  rx_bufaddr;     /* address of the rx buffer */
-       uclong  rx_bufsize;     /* rx buffer size */
-       uclong  rx_threshold;   /* rx high water mark */
-       uclong  rx_get;         /* tail index rx buf */
-       uclong  rx_put;         /* head index rx buf */
-       uclong  filler[5];      /* filler to align structures */
+       __u32   flag_dma;       /* buffers are in Host memory */
+       __u32   tx_bufaddr;     /* address of the tx buffer */
+       __u32   tx_bufsize;     /* tx buffer size */
+       __u32   tx_threshold;   /* tx low water mark */
+       __u32   tx_get;         /* tail index tx buf */
+       __u32   tx_put;         /* head index tx buf */
+       __u32   rx_bufaddr;     /* address of the rx buffer */
+       __u32   rx_bufsize;     /* rx buffer size */
+       __u32   rx_threshold;   /* rx high water mark */
+       __u32   rx_get;         /* tail index rx buf */
+       __u32   rx_put;         /* head index rx buf */
+       __u32   filler[5];      /* filler to align structures */
 };
 
 /*
@@ -457,27 +456,27 @@ struct    BUF_CTRL        {
 struct BOARD_CTRL {
 
        /* static info provided by the on-board CPU */
-       uclong  n_channel;      /* number of channels */
-       uclong  fw_version;     /* firmware version */
+       __u32   n_channel;      /* number of channels */
+       __u32   fw_version;     /* firmware version */
 
        /* static info provided by the driver */
-       uclong  op_system;      /* op_system id */
-       uclong  dr_version;     /* driver version */
+       __u32   op_system;      /* op_system id */
+       __u32   dr_version;     /* driver version */
 
        /* board control area */
-       uclong  inactivity;     /* inactivity control */
+       __u32   inactivity;     /* inactivity control */
 
        /* host to FW commands */
-       uclong  hcmd_channel;   /* channel number */
-       uclong  hcmd_param;     /* pointer to parameters */
+       __u32   hcmd_channel;   /* channel number */
+       __u32   hcmd_param;     /* pointer to parameters */
 
        /* FW to Host commands */
-       uclong  fwcmd_channel;  /* channel number */
-       uclong  fwcmd_param;    /* pointer to parameters */
-       uclong  zf_int_queue_addr; /* offset for INT_QUEUE structure */
+       __u32   fwcmd_channel;  /* channel number */
+       __u32   fwcmd_param;    /* pointer to parameters */
+       __u32   zf_int_queue_addr; /* offset for INT_QUEUE structure */
 
        /* filler so the structures are aligned */
-       uclong  filler[6];
+       __u32   filler[6];
 };
 
 /* Host Interrupt Queue */
@@ -506,11 +505,10 @@ struct ZFW_CTRL {
 /****************** ****************** *******************/
 #endif
 
+#ifdef __KERNEL__
+
 /* Per card data structure */
-struct resource;
 struct cyclades_card {
-    unsigned long base_phys;
-    unsigned long ctl_phys;
     void __iomem *base_addr;
     void __iomem *ctl_addr;
     int irq;
@@ -519,33 +517,18 @@ struct cyclades_card {
     int nports;                /* Number of ports in the card */
     int bus_index;     /* address shift - 0 for ISA, 1 for PCI */
     int        intr_enabled;   /* FW Interrupt flag - 0 disabled, 1 enabled */
-    struct pci_dev *pdev;
-#ifdef __KERNEL__
     spinlock_t card_lock;
-#else
-    unsigned long filler;
-#endif
+    struct cyclades_port *ports;
 };
 
-struct cyclades_chip {
-  int filler;
-};
-
-
-#ifdef __KERNEL__
-
 /***************************************
  * Memory access functions/macros      *
  * (required to support Alpha systems) *
  ***************************************/
 
-#define cy_writeb(port,val)     {writeb((val),(port)); mb();}
-#define cy_writew(port,val)     {writew((val),(port)); mb();}
-#define cy_writel(port,val)     {writel((val),(port)); mb();}
-
-#define cy_readb(port)  readb(port)
-#define cy_readw(port)  readw(port)
-#define cy_readl(port)  readl(port)
+#define cy_writeb(port,val)     do { writeb((val), (port)); mb(); } while (0)
+#define cy_writew(port,val)     do { writew((val), (port)); mb(); } while (0)
+#define cy_writel(port,val)     do { writel((val), (port)); mb(); } while (0)
 
 /*
  * Statistics counters
@@ -567,7 +550,7 @@ struct cyclades_icount {
 
 struct cyclades_port {
        int                     magic;
-       int                     card;
+       struct cyclades_card    *card;
        int                     line;
        int                     flags;          /* defined in tty.h */
        int                     type;           /* UART type */
@@ -587,7 +570,6 @@ struct cyclades_port {
        int                     close_delay;
        unsigned short          closing_wait;
        unsigned long           event;
-       unsigned long           last_active;
        int                     count;  /* # of fd on device */
        int                     breakon;
        int                     breakoff;
@@ -598,7 +580,6 @@ struct cyclades_port {
        int                     xmit_cnt;
         int                     default_threshold;
         int                     default_timeout;
-       unsigned long           jiffies[3];
        unsigned long           rflush_count;
        struct cyclades_monitor mon;
        struct cyclades_idle_stats      idle_stats;
@@ -606,7 +587,7 @@ struct cyclades_port {
        struct work_struct      tqueue;
        wait_queue_head_t       open_wait;
        wait_queue_head_t       close_wait;
-       wait_queue_head_t       shutdown_wait;
+       struct completion       shutdown_wait;
        wait_queue_head_t       delta_msr_wait;
        int throttle;
 };
index 63f64a9a5bf7b207b674be433d1c3b218ff39813..aab53df4fafa338e46b96919d61e77ed2b20ff78 100644 (file)
@@ -133,6 +133,7 @@ struct dentry_operations {
        int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
+       char *(*d_dname)(struct dentry *, char *, int);
 };
 
 /* the dentry parameter passed to d_hash and d_compare is the parent
@@ -293,6 +294,11 @@ extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *);
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
 
+/*
+ * helper function for dentry_operations.d_dname() members
+ */
+extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+
 extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
   
 /* Allocation counts.. */
index 6579068134d121384dd7c6bd7fafd4251d57fc16..2e1a2988b7e15a35240c63a5f56928f2145c2ea2 100644 (file)
@@ -412,12 +412,13 @@ struct device {
        struct klist_node       knode_parent;           /* node in sibling list */
        struct klist_node       knode_driver;
        struct klist_node       knode_bus;
-       struct device   parent;
+       struct device           *parent;
 
        struct kobject kobj;
        char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
        struct device_type      *type;
        unsigned                is_registered:1;
+       unsigned                uevent_suppress:1;
        struct device_attribute uevent_attr;
        struct device_attribute *devt_attr;
 
@@ -458,7 +459,6 @@ struct device {
        struct class            *class;
        dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
        struct attribute_group  **groups;       /* optional groups */
-       int                     uevent_suppress;
 
        void    (*release)(struct device * dev);
 };
diff --git a/include/linux/display.h b/include/linux/display.h
new file mode 100644 (file)
index 0000000..3bf70d6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2006 James Simmons <jsimmons@infradead.org>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#ifndef _LINUX_DISPLAY_H
+#define _LINUX_DISPLAY_H
+
+#include <linux/device.h>
+
+struct display_device;
+
+/* This structure defines all the properties of a Display. */
+struct display_driver {
+       int  (*set_contrast)(struct display_device *, unsigned int);
+       int  (*get_contrast)(struct display_device *);
+       void (*suspend)(struct display_device *, pm_message_t state);
+       void (*resume)(struct display_device *);
+       int  (*probe)(struct display_device *, void *);
+       int  (*remove)(struct display_device *);
+       int  max_contrast;
+};
+
+struct display_device {
+       struct module *owner;                   /* Owner module */
+       struct display_driver *driver;
+       struct device *parent;                  /* This is the parent */
+       struct device *dev;                     /* This is this display device */
+       struct mutex lock;
+       void *priv_data;
+       char type[16];
+       char *name;
+       int idx;
+};
+
+extern struct display_device *display_device_register(struct display_driver *driver,
+                                       struct device *dev, void *devdata);
+extern void display_device_unregister(struct display_device *dev);
+
+extern int probe_edid(struct display_device *dev, void *devdata);
+
+#define to_display_device(obj) container_of(obj, struct display_device, class_dev)
+
+#endif
diff --git a/include/linux/ds1wm.h b/include/linux/ds1wm.h
new file mode 100644 (file)
index 0000000..31f6e3c
--- /dev/null
@@ -0,0 +1,11 @@
+/* platform data for the DS1WM driver */
+
+struct ds1wm_platform_data {
+       int bus_shift;      /* number of shifts needed to calculate the
+                            * offset between DS1WM registers;
+                            * e.g. on h5xxx and h2200 this is 2
+                            * (registers aligned to 4-byte boundaries),
+                            * while on hx4700 this is 1 */
+       void (*enable)(struct platform_device *pdev);
+       void (*disable)(struct platform_device *pdev);
+};
index f8ebd7c1ddb3f40019fd2c14902c58ff14de23e3..0b9579a4cd424d03d95a6ba4a397ee22f4e23b3d 100644 (file)
@@ -213,7 +213,6 @@ typedef struct {
 } efi_config_table_t;
 
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
-#define EFI_SYSTEM_TABLE_REVISION  ((1 << 16) | 00)
 
 typedef struct {
        efi_table_hdr_t hdr;
index 4eb18ac510aeb2e2be36b980da99751224f28e59..ece49a804fe18485bfdc5e1e4672c0a7f9bf0002 100644 (file)
@@ -824,6 +824,7 @@ extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
 extern void ext3_truncate (struct inode *);
 extern void ext3_set_inode_flags(struct inode *);
+extern void ext3_get_inode_flags(struct ext3_inode_info *);
 extern void ext3_set_aops(struct inode *inode);
 
 /* ioctl.c */
index 4395e5206746b33be79bd57bef264da8a74bcd0a..7894dd0f3b77544a8006ff1d4471554f460be093 100644 (file)
@@ -54,7 +54,7 @@ struct ext3_block_alloc_info {
        /*
         * Was i_next_alloc_goal in ext3_inode_info
         * is the *physical* companion to i_next_alloc_block.
-        * it the the physical block number of the block which was most-recentl
+        * it the physical block number of the block which was most-recentl
         * allocated to this file.  This give us the goal (target) for the next
         * allocation when we detect linearly ascending requests.
         */
index bb42379cb7fdf91dde212e257df8d63ed06426f2..d5b177e5b3958338d13bfc46a9d8fcc1e338a9ee 100644 (file)
@@ -52,7 +52,7 @@ struct ext4_block_alloc_info {
        /*
         * Was i_next_alloc_goal in ext4_inode_info
         * is the *physical* companion to i_next_alloc_block.
-        * it the the physical block number of the block which was most-recentl
+        * it the physical block number of the block which was most-recentl
         * allocated to this file.  This give us the goal (target) for the next
         * allocation when we detect linearly ascending requests.
         */
index be913ec871692e58fc9dfe798aa4ad0154629bd5..c654d0e9ce3313d6f345eeac6ebd72279240d238 100644 (file)
@@ -4,6 +4,8 @@
 #include <asm/types.h>
 #include <linux/i2c.h>
 
+struct dentry;
+
 /* Definitions of frame buffers                                                */
 
 #define FB_MAJOR               29
@@ -525,12 +527,20 @@ struct fb_cursor_user {
 #define FB_EVENT_MODE_CHANGE_ALL       0x0B
 /*     A software display blank change occured */
 #define FB_EVENT_CONBLANK               0x0C
+/*      Get drawing requirements        */
+#define FB_EVENT_GET_REQ                0x0D
 
 struct fb_event {
        struct fb_info *info;
        void *data;
 };
 
+struct fb_blit_caps {
+       u32 x;
+       u32 y;
+       u32 len;
+       u32 flags;
+};
 
 extern int fb_register_client(struct notifier_block *nb);
 extern int fb_unregister_client(struct notifier_block *nb);
@@ -556,11 +566,25 @@ struct fb_pixmap {
        u32 scan_align;         /* alignment per scanline               */
        u32 access_align;       /* alignment per read/write (bits)      */
        u32 flags;              /* see FB_PIXMAP_*                      */
+       u32 blit_x;             /* supported bit block dimensions (1-32)*/
+       u32 blit_y;             /* Format: blit_x = 1 << (width - 1)    */
+                               /*         blit_y = 1 << (height - 1)   */
+                               /* if 0, will be set to 0xffffffff (all)*/
        /* access methods */
        void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size);
        void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size);
 };
 
+#ifdef CONFIG_FB_DEFERRED_IO
+struct fb_deferred_io {
+       /* delay between mkwrite and deferred handler */
+       unsigned long delay;
+       struct mutex lock; /* mutex that protects the page list */
+       struct list_head pagelist; /* list of touched pages */
+       /* callback */
+       void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
+};
+#endif
 
 /*
  * Frame buffer operations
@@ -579,8 +603,10 @@ struct fb_ops {
        /* For framebuffers with strange non linear layouts or that do not
         * work with normal memory mapped access
         */
-       ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
-       ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+       ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
+                          size_t count, loff_t *ppos);
+       ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
+                           size_t count, loff_t *ppos);
 
        /* checks var and eventually tweaks it to something supported,
         * DO NOT MODIFY PAR */
@@ -634,10 +660,13 @@ struct fb_ops {
 
        /* restore saved state */
        void (*fb_restore_state)(struct fb_info *info);
+
+       /* get capability given var */
+       void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
+                           struct fb_var_screeninfo *var);
 };
 
 #ifdef CONFIG_FB_TILEBLITTING
-
 #define FB_TILE_CURSOR_NONE        0
 #define FB_TILE_CURSOR_UNDERLINE   1
 #define FB_TILE_CURSOR_LOWER_THIRD 2
@@ -709,6 +738,8 @@ struct fb_tile_ops {
        /* cursor */
        void (*fb_tilecursor)(struct fb_info *info,
                              struct fb_tilecursor *cursor);
+       /* get maximum length of the tile map */
+       int (*fb_get_tilemax)(struct fb_info *info);
 };
 #endif /* CONFIG_FB_TILEBLITTING */
 
@@ -778,6 +809,10 @@ struct fb_info {
        struct mutex bl_curve_mutex;    
        u8 bl_curve[FB_BACKLIGHT_LEVELS];
 #endif
+#ifdef CONFIG_FB_DEFERRED_IO
+       struct delayed_work deferred_work;
+       struct fb_deferred_io *fbdefio;
+#endif
 
        struct fb_ops *fbops;
        struct device *device;          /* This is the parent */
@@ -833,7 +868,7 @@ struct fb_info {
 #define fb_writeq sbus_writeq
 #define fb_memset sbus_memset_io
 
-#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__)
+#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__) || defined(__avr32__)
 
 #define fb_readb __raw_readb
 #define fb_readw __raw_readw
@@ -879,6 +914,16 @@ extern int fb_blank(struct fb_info *info, int blank);
 extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); 
 extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); 
 extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
+/*
+ * Drawing operations where framebuffer is in system RAM
+ */
+extern void sys_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+extern void sys_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+extern void sys_imageblit(struct fb_info *info, const struct fb_image *image);
+extern ssize_t fb_sys_read(struct fb_info *info, char __user *buf,
+                          size_t count, loff_t *ppos);
+extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
+                           size_t count, loff_t *ppos);
 
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
@@ -913,6 +958,12 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
        }
 }
 
+/* drivers/video/fb_defio.c */
+extern void fb_deferred_io_init(struct fb_info *info);
+extern void fb_deferred_io_cleanup(struct fb_info *info);
+extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry,
+                               int datasync);
+
 /* drivers/video/fbsysfs.c */
 extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
 extern void framebuffer_release(struct fb_info *info);
index 53b129f07f6f294a896ce4bcc62133641f79d9ef..40a24ab41b36b883eaea6abfcecb82db66de31e2 100644 (file)
@@ -49,7 +49,8 @@ extern const struct font_desc *find_font(const char *name);
 
 /* Get the default font for a specific screen size */
 
-extern const struct font_desc *get_default_font(int xres, int yres);
+extern const struct font_desc *get_default_font(int xres, int yres,
+                                               u32 font_w, u32 font_h);
 
 /* Max. length for the name of a predefined font */
 #define MAX_FONT_NAME  32
index bc6d27cecaacac36313f848c8f28ab3ad8e21425..7cf0c54a46a7fff64365b3184ea492d572dac9b0 100644 (file)
@@ -30,6 +30,7 @@
 #define SEEK_SET       0       /* seek relative to beginning of file */
 #define SEEK_CUR       1       /* seek relative to current file position */
 #define SEEK_END       2       /* seek relative to end of file */
+#define SEEK_MAX       SEEK_END
 
 /* And dynamically-tunable limits and defaults: */
 struct files_stat_struct {
@@ -91,6 +92,7 @@ extern int dir_notify_enable;
 /* public flags for file_system_type */
 #define FS_REQUIRES_DEV 1 
 #define FS_BINARY_MOUNTDATA 2
+#define FS_HAS_SUBTYPE 4
 #define FS_REVAL_DOT   16384   /* Check the paths ".", ".." for staleness */
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move()
                                         * during rename() internally.
@@ -847,11 +849,6 @@ extern int fcntl_getlease(struct file *filp);
 /* fs/sync.c */
 extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
                        loff_t endbyte, unsigned int flags);
-static inline int do_sync_file_range(struct file *file, loff_t offset,
-                       loff_t endbyte, unsigned int flags)
-{
-       return do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
-}
 
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
@@ -960,6 +957,12 @@ struct super_block {
        /* Granularity of c/m/atime in ns.
           Cannot be worse than a second */
        u32                s_time_gran;
+
+       /*
+        * Filesystem subtype.  If non-empty the filesystem type field
+        * in /proc/mounts will be "type.subtype"
+        */
+       char *s_subtype;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
@@ -1735,6 +1738,8 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor
 extern void do_generic_mapping_read(struct address_space *mapping,
                                    struct file_ra_state *, struct file *,
                                    loff_t *, read_descriptor_t *, read_actor_t);
+extern int generic_segment_checks(const struct iovec *iov,
+               unsigned long *nr_segs, size_t *count, int access_flags);
 
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
index 3f153b4e156c4e9be16c70570276c02d3aecba8c..899fc7f20edd1b761023a58cbb883b12ba3e36ef 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/sched.h>
 
+union ktime;
+
 /* Second argument to futex syscall */
 
 
 #define FUTEX_LOCK_PI          6
 #define FUTEX_UNLOCK_PI                7
 #define FUTEX_TRYLOCK_PI       8
+#define FUTEX_CMP_REQUEUE_PI   9
+
+#define FUTEX_PRIVATE_FLAG     128
+#define FUTEX_CMD_MASK         ~FUTEX_PRIVATE_FLAG
+
+#define FUTEX_WAIT_PRIVATE     (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_PRIVATE     (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_REQUEUE_PRIVATE  (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_OP_PRIVATE  (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
+#define FUTEX_LOCK_PI_PRIVATE  (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_UNLOCK_PI_PRIVATE        (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
 
 /*
  * Support for robust futexes: the kernel cleans up held futexes at
@@ -82,10 +97,15 @@ struct robust_list_head {
  */
 #define FUTEX_OWNER_DIED       0x40000000
 
+/*
+ * Some processes have been requeued on this PI-futex
+ */
+#define FUTEX_WAITER_REQUEUED  0x20000000
+
 /*
  * The rest of the robust-futex field is for the TID:
  */
-#define FUTEX_TID_MASK         0x3fffffff
+#define FUTEX_TID_MASK         0x0fffffff
 
 /*
  * This limit protects against a deliberately circular list.
@@ -94,12 +114,53 @@ struct robust_list_head {
 #define ROBUST_LIST_LIMIT      2048
 
 #ifdef __KERNEL__
-long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
+long do_futex(u32 __user *uaddr, int op, u32 val, union ktime *timeout,
              u32 __user *uaddr2, u32 val2, u32 val3);
 
 extern int
 handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi);
 
+/*
+ * Futexes are matched on equal values of this key.
+ * The key type depends on whether it's a shared or private mapping.
+ * Don't rearrange members without looking at hash_futex().
+ *
+ * offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
+ * We use the two low order bits of offset to tell what is the kind of key :
+ *  00 : Private process futex (PTHREAD_PROCESS_PRIVATE)
+ *       (no reference on an inode or mm)
+ *  01 : Shared futex (PTHREAD_PROCESS_SHARED)
+ *     mapped on a file (reference on the underlying inode)
+ *  10 : Shared futex (PTHREAD_PROCESS_SHARED)
+ *       (but private mapping on an mm, and reference taken on it)
+*/
+
+#define FUT_OFF_INODE    1 /* We set bit 0 if key has a reference on inode */
+#define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */
+
+union futex_key {
+       u32 __user *uaddr;
+       struct {
+               unsigned long pgoff;
+               struct inode *inode;
+               int offset;
+       } shared;
+       struct {
+               unsigned long address;
+               struct mm_struct *mm;
+               int offset;
+       } private;
+       struct {
+               unsigned long word;
+               void *ptr;
+               int offset;
+       } both;
+};
+int get_futex_key(u32 __user *uaddr, struct rw_semaphore *shared,
+                 union futex_key *key);
+void get_futex_key_refs(union futex_key *key);
+void drop_futex_key_refs(union futex_key *key);
+
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
 extern void exit_pi_state_list(struct task_struct *curr);
index 80764f40be7531ff7c287f23ccba18b34e5515a8..886f5faa08cb6f1ff8c84ff2da04e9144d01c9df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * fs/generic_acl.c
+ * include/linux/generic_acl.h
  *
  * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
  *
index 2c65da7cabb2a25acc1c42c067a3770872f29141..f589559cf0709586d1f126f92ebbbbca9cefa53b 100644 (file)
@@ -413,6 +413,7 @@ char *disk_name (struct gendisk *hd, int part, char *buf);
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
 extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
 extern void delete_partition(struct gendisk *, int);
+extern void printk_all_partitions(void);
 
 extern struct gendisk *alloc_disk_node(int minors, int node_id);
 extern struct gendisk *alloc_disk(int minors);
index 97a36c3d96e2cb1d9981f1aa4a9b350138d268a0..0d2ef0b082a626853b7651914094cabf88672434 100644 (file)
@@ -176,10 +176,6 @@ extern void FASTCALL(free_cold_page(struct page *page));
 #define free_page(addr) free_pages((addr),0)
 
 void page_alloc_init(void);
-#ifdef CONFIG_NUMA
-void drain_node_pages(int node);
-#else
-static inline void drain_node_pages(int node) { };
-#endif
+void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp);
 
 #endif /* __LINUX_GFP_H */
index a515eb0afdfb660a56eedd0c8928b8281fe0b5b7..98e2cce996a4c1867543ffa03d83c66c3c8846de 100644 (file)
@@ -94,17 +94,26 @@ static inline void clear_highpage(struct page *page)
 
 /*
  * Same but also flushes aliased cache contents to RAM.
+ *
+ * This must be a macro because KM_USER0 and friends aren't defined if
+ * !CONFIG_HIGHMEM
  */
-static inline void memclear_highpage_flush(struct page *page, unsigned int offset, unsigned int size)
+#define zero_user_page(page, offset, size, km_type)            \
+       do {                                                    \
+               void *kaddr;                                    \
+                                                               \
+               BUG_ON((offset) + (size) > PAGE_SIZE);          \
+                                                               \
+               kaddr = kmap_atomic(page, km_type);             \
+               memset((char *)kaddr + (offset), 0, (size));    \
+               flush_dcache_page(page);                        \
+               kunmap_atomic(kaddr, (km_type));                \
+       } while (0)
+
+static inline void __deprecated memclear_highpage_flush(struct page *page,
+                       unsigned int offset, unsigned int size)
 {
-       void *kaddr;
-
-       BUG_ON(offset + size > PAGE_SIZE);
-
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset((char *)kaddr + offset, 0, size);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
+       zero_user_page(page, offset, size, KM_USER0);
 }
 
 #ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
index 9ee0f800592f030bd56592ec2de113e5c8deb214..111334f5b92238664037059bed8f1fe431875337 100644 (file)
@@ -18,7 +18,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
 /* ------------------------------------------------------------------------- */
 
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
 #ifndef _LINUX_I2C_ALGO_BIT_H
index 994eb86f882c1f4fa3ce682b523ce7e81f64ae9d..77afbb60fd1185fb76699eacd9a8ba6fd5f7f919 100644 (file)
@@ -19,7 +19,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
 /* ------------------------------------------------------------------------- */
 
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
 #ifndef _LINUX_I2C_ALGO_PCF_H
index dbbdbd1bec7768137cbcb4564d404561a9846733..8bc32bb2fce20a23e04b9327b1912a59f5e97252 100644 (file)
@@ -77,7 +77,8 @@ extern char *saved_command_line;
 extern unsigned int reset_devices;
 
 /* used by init/main.c */
-extern void setup_arch(char **);
+void setup_arch(char **);
+void prepare_namespace(void);
 
 #endif
   
index a2d95ff50e9bd71eb741d5ef9a293574245ab244..45170b2fa2535ce7748a7caa157e8783a0ea3c65 100644 (file)
@@ -95,7 +95,7 @@ extern struct group_info init_groups;
 #define INIT_TASK(tsk) \
 {                                                                      \
        .state          = 0,                                            \
-       .thread_info    = &init_thread_info,                            \
+       .stack          = &init_thread_info,                            \
        .usage          = ATOMIC_INIT(2),                               \
        .flags          = 0,                                            \
        .lock_depth     = -1,                                           \
@@ -138,7 +138,7 @@ extern struct group_info init_groups;
        .journal_info   = NULL,                                         \
        .cpu_timers     = INIT_CPU_TIMERS(tsk.cpu_timers),              \
        .fs_excl        = ATOMIC_INIT(0),                               \
-       .pi_lock        = SPIN_LOCK_UNLOCKED,                           \
+       .pi_lock        = __SPIN_LOCK_UNLOCKED(tsk.pi_lock),            \
        INIT_TRACE_IRQFLAGS                                             \
        INIT_LOCKDEP                                                    \
 }
index 0319f665dd3f565158548c8ec20b6a281482e42a..f7b01b9a35b3a353789bf6ec2160c8d79d989f4e 100644 (file)
@@ -44,6 +44,9 @@
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
  * IRQF_PERCPU - Interrupt is per cpu
  * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
+ * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
+ *                registered first in an shared interrupt is considered for
+ *                performance reasons)
  */
 #define IRQF_DISABLED          0x00000020
 #define IRQF_SAMPLE_RANDOM     0x00000040
 #define IRQF_TIMER             0x00000200
 #define IRQF_PERCPU            0x00000400
 #define IRQF_NOBALANCING       0x00000800
+#define IRQF_IRQPOLL           0x00001000
 
 /*
- * Migration helpers. Scheduled for removal in 1/2007
+ * Migration helpers. Scheduled for removal in 9/2007
  * Do not use for new code !
  */
-#define SA_INTERRUPT           IRQF_DISABLED
-#define SA_SAMPLE_RANDOM       IRQF_SAMPLE_RANDOM
-#define SA_SHIRQ               IRQF_SHARED
-#define SA_PROBEIRQ            IRQF_PROBE_SHARED
-#define SA_PERCPU              IRQF_PERCPU
-
-#define SA_TRIGGER_LOW         IRQF_TRIGGER_LOW
-#define SA_TRIGGER_HIGH                IRQF_TRIGGER_HIGH
-#define SA_TRIGGER_FALLING     IRQF_TRIGGER_FALLING
-#define SA_TRIGGER_RISING      IRQF_TRIGGER_RISING
-#define SA_TRIGGER_MASK                IRQF_TRIGGER_MASK
+static inline
+unsigned long __deprecated deprecated_irq_flag(unsigned long flag)
+{
+       return flag;
+}
+
+#define SA_INTERRUPT           deprecated_irq_flag(IRQF_DISABLED)
+#define SA_SAMPLE_RANDOM       deprecated_irq_flag(IRQF_SAMPLE_RANDOM)
+#define SA_SHIRQ               deprecated_irq_flag(IRQF_SHARED)
+#define SA_PROBEIRQ            deprecated_irq_flag(IRQF_PROBE_SHARED)
+#define SA_PERCPU              deprecated_irq_flag(IRQF_PERCPU)
+
+#define SA_TRIGGER_LOW         deprecated_irq_flag(IRQF_TRIGGER_LOW)
+#define SA_TRIGGER_HIGH                deprecated_irq_flag(IRQF_TRIGGER_HIGH)
+#define SA_TRIGGER_FALLING     deprecated_irq_flag(IRQF_TRIGGER_FALLING)
+#define SA_TRIGGER_RISING      deprecated_irq_flag(IRQF_TRIGGER_RISING)
+#define SA_TRIGGER_MASK                deprecated_irq_flag(IRQF_TRIGGER_MASK)
 
 typedef irqreturn_t (*irq_handler_t)(int, void *);
 
@@ -83,11 +93,11 @@ struct irqaction {
 };
 
 extern irqreturn_t no_action(int cpl, void *dev_id);
-extern int request_irq(unsigned int, irq_handler_t handler,
+extern int __must_check request_irq(unsigned int, irq_handler_t handler,
                       unsigned long, const char *, void *);
 extern void free_irq(unsigned int, void *);
 
-extern int devm_request_irq(struct device *dev, unsigned int irq,
+extern int __must_check devm_request_irq(struct device *dev, unsigned int irq,
                            irq_handler_t handler, unsigned long irqflags,
                            const char *devname, void *dev_id);
 extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
diff --git a/include/linux/ioctl32.h b/include/linux/ioctl32.h
deleted file mode 100644 (file)
index 948809d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef IOCTL32_H
-#define IOCTL32_H 1
-
-#include <linux/compiler.h>    /* for __deprecated */
-
-struct file;
-
-typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
-                                       unsigned long, struct file *);
-
-struct ioctl_trans {
-       unsigned long cmd;
-       ioctl_trans_handler_t handler;
-       struct ioctl_trans *next;
-};
-
-#endif
index 6da6772c19ff77254df762d50058574a663f822f..1980867a64a4cb3e84ab57f5ee93cd66fefb8419 100644 (file)
@@ -92,16 +92,19 @@ extern struct ipc_namespace init_ipc_ns;
 
 #ifdef CONFIG_SYSVIPC
 #define INIT_IPC_NS(ns)                .ns             = &init_ipc_ns,
-extern int copy_ipcs(unsigned long flags, struct task_struct *tsk);
+extern struct ipc_namespace *copy_ipcs(unsigned long flags,
+                                               struct ipc_namespace *ns);
 #else
 #define INIT_IPC_NS(ns)
-static inline int copy_ipcs(unsigned long flags, struct task_struct *tsk)
-{ return 0; }
+static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
+                                               struct ipc_namespace *ns)
+{
+       return ns;
+}
 #endif
 
 #ifdef CONFIG_IPC_NS
 extern void free_ipc_ns(struct kref *kref);
-extern int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns);
 #endif
 
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
index 09d8f105a5a82d0c0fde07b23bd80c63ff489f47..945ba3110874fcf96bc428aa142d611524536896 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index a6899402b5220233c53fe926655d788b2dce7f1c..1695054e8c63909a62b8e12d16fe5ca1c8cc625c 100644 (file)
@@ -147,8 +147,6 @@ struct irq_chip {
  * @dir:               /proc/irq/ procfs entry
  * @affinity_entry:    /proc/irq/smp_affinity procfs entry on SMP
  * @name:              flow handler name for /proc/interrupts output
- *
- * Pad this out to 32 bytes for cache and indexing reasons.
  */
 struct irq_desc {
        irq_flow_handler_t      handle_irq;
@@ -175,7 +173,7 @@ struct irq_desc {
        struct proc_dir_entry   *dir;
 #endif
        const char              *name;
-} ____cacheline_aligned;
+} ____cacheline_internodealigned_in_smp;
 
 extern struct irq_desc irq_desc[NR_IRQS];
 
index 63bd9cf821a763953cd94243d385a74e8672ee5c..5a52f2c94f3f68530466c349024220c255068b4d 100644 (file)
@@ -187,7 +187,6 @@ typedef struct {
 #define        CDEBUG_SIZE     1024
 #define        CDEBUG_GSIZE    4096
 
-_cdebbuf *cdebbuf_alloc(void);
 void cdebbuf_free(_cdebbuf *cdb);
 int cdebug_init(void);
 void cdebug_exit(void);
index 0e7e44ce830120aba22eaa1d6cadf7bb31082029..07821ca5955f42872e5b2748272cc7bf73bc2c4c 100644 (file)
 #define DIVERT_REL_ERR  0x04  /* module not registered */
 #define DIVERT_REG_NAME isdn_register_divert
 
+#ifdef __KERNEL__
+#include <linux/isdnif.h>
+#include <linux/types.h>
+
 /***************************************************************/
 /* structure exchanging data between isdn hl and divert module */
 /***************************************************************/ 
@@ -40,3 +44,4 @@ typedef struct
 /* function register */
 /*********************/
 extern int DIVERT_REG_NAME(isdn_divert_if *);
+#endif
index 3e3b92dabe3bb08783df230036c2f2069a784317..12178d2c882be4461714df1c9147c5ae0852d4cc 100644 (file)
@@ -30,6 +30,9 @@ extern int sprint_symbol(char *buffer, unsigned long address);
 /* Look up a kernel symbol and print it to the kernel messages. */
 extern void __print_symbol(const char *fmt, unsigned long address);
 
+int lookup_symbol_name(unsigned long addr, char *symname);
+int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
+
 #else /* !CONFIG_KALLSYMS */
 
 static inline unsigned long kallsyms_lookup_name(const char *name)
@@ -58,6 +61,16 @@ static inline int sprint_symbol(char *buffer, unsigned long addr)
        return 0;
 }
 
+static inline int lookup_symbol_name(unsigned long addr, char *symname)
+{
+       return -ERANGE;
+}
+
+static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name)
+{
+       return -ERANGE;
+}
+
 /* Stupid that this does nothing, but I didn't create this mess. */
 #define __print_symbol(fmt, addr)
 #endif /*CONFIG_KALLSYMS*/
diff --git a/include/linux/kdebug.h b/include/linux/kdebug.h
new file mode 100644 (file)
index 0000000..5db38d6
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LINUX_KDEBUG_H
+#define _LINUX_KDEBUG_H
+
+#include <asm/kdebug.h>
+
+struct die_args {
+       struct pt_regs *regs;
+       const char *str;
+       long err;
+       int trapnr;
+       int signr;
+};
+
+int register_die_notifier(struct notifier_block *nb);
+int unregister_die_notifier(struct notifier_block *nb);
+
+int notify_die(enum die_val val, const char *str,
+              struct pt_regs *regs, long err, int trap, int sig);
+
+#endif /* _LINUX_KDEBUG_H */
index 696e5ec63f77b83fdb81cf35299783633637736a..8c2c7fcd58ceab1937e8d20f4ac0da0c0940b404 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/linkage.h>
 #include <linux/compat.h>
 #include <linux/ioport.h>
+#include <linux/elfcore.h>
+#include <linux/elf.h>
 #include <asm/kexec.h>
 
 /* Verify architecture specific macros are defined */
 #error KEXEC_ARCH not defined
 #endif
 
+#define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
+#define KEXEC_CORE_NOTE_NAME "CORE"
+#define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
+#define KEXEC_CORE_NOTE_DESC_BYTES ALIGN(sizeof(struct elf_prstatus), 4)
+/*
+ * The per-cpu notes area is a list of notes terminated by a "NULL"
+ * note header.  For kdump, the code in vmcore.c runs in the context
+ * of the second kernel to combine them into one note.
+ */
+#define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) +               \
+                           KEXEC_CORE_NOTE_NAME_BYTES +                \
+                           KEXEC_CORE_NOTE_DESC_BYTES )
+
 /*
  * This structure is used to hold the arguments that are used when loading
  * kernel binaries.
@@ -136,7 +151,7 @@ extern struct kimage *kexec_crash_image;
 /* Location of a reserved region to hold the crash kernel.
  */
 extern struct resource crashk_res;
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
 extern note_buf_t *crash_notes;
 
 
index 769be39b96810414ebdec4fec05d94e997eba5eb..23adf6075ae435a1c421fe7991e30b2bd64ebc27 100644 (file)
@@ -78,7 +78,7 @@ struct kprobe {
        kprobe_opcode_t *addr;
 
        /* Allow user to indicate symbol name of the probe point */
-       char *symbol_name;
+       const char *symbol_name;
 
        /* Offset into the symbol */
        unsigned int offset;
@@ -123,12 +123,18 @@ DECLARE_PER_CPU(struct kprobe *, current_kprobe);
 DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 #ifdef ARCH_SUPPORTS_KRETPROBES
-extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
+extern void arch_prepare_kretprobe(struct kretprobe_instance *ri,
+                                  struct pt_regs *regs);
+extern int arch_trampoline_kprobe(struct kprobe *p);
 #else /* ARCH_SUPPORTS_KRETPROBES */
 static inline void arch_prepare_kretprobe(struct kretprobe *rp,
                                        struct pt_regs *regs)
 {
 }
+static inline int arch_trampoline_kprobe(struct kprobe *p)
+{
+       return 0;
+}
 #endif /* ARCH_SUPPORTS_KRETPROBES */
 /*
  * Function-return probe -
@@ -157,6 +163,16 @@ struct kretprobe_instance {
        struct task_struct *task;
 };
 
+static inline void kretprobe_assert(struct kretprobe_instance *ri,
+       unsigned long orig_ret_address, unsigned long trampoline_address)
+{
+       if (!orig_ret_address || (orig_ret_address == trampoline_address)) {
+               printk("kretprobe BUG!: Processing kretprobe %p @ %p\n",
+                               ri->rp, ri->rp->kp.addr);
+               BUG();
+       }
+}
+
 extern spinlock_t kretprobe_lock;
 extern struct mutex kprobe_mutex;
 extern int arch_prepare_kprobe(struct kprobe *p);
@@ -199,8 +215,6 @@ void jprobe_return(void);
 int register_kretprobe(struct kretprobe *rp);
 void unregister_kretprobe(struct kretprobe *rp);
 
-struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
-void add_rp_inst(struct kretprobe_instance *ri);
 void kprobe_flush_task(struct task_struct *tk);
 void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
 #else /* CONFIG_KPROBES */
index 1c65e7a9f186cceee83a1e5e199db44b4260daf2..00dd957e245b43839db5e0972e74ff541e4dafd1 100644 (file)
@@ -30,4 +30,7 @@ void kthread_bind(struct task_struct *k, unsigned int cpu);
 int kthread_stop(struct task_struct *k);
 int kthread_should_stop(void);
 
+int kthreadd(void *unused);
+extern struct task_struct *kthreadd_task;
+
 #endif /* _LINUX_KTHREAD_H */
index 81bb9c7a4eb3fec22b97ea1c2c1cd17e5baffd23..c762954bda148fa18ab13f6d1f71aab26d2e3441 100644 (file)
@@ -43,7 +43,7 @@
  * plain scalar nanosecond based representation can be selected by the
  * config switch CONFIG_KTIME_SCALAR.
  */
-typedef union {
+union ktime {
        s64     tv64;
 #if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
        struct {
@@ -54,7 +54,9 @@ typedef union {
 # endif
        } tv;
 #endif
-} ktime_t;
+};
+
+typedef union ktime ktime_t;           /* Kill this */
 
 #define KTIME_MAX                      ((s64)~((u64)1 << 63))
 #if (BITS_PER_LONG == 64)
index d8cfc72ea9c110937161c910813a5f59d447b3b6..7906d750aa77481ab34bd5d1c80a9f9db27d38a4 100644 (file)
@@ -296,18 +296,8 @@ enum {
 
        /* how hard are we gonna try to probe/recover devices */
        ATA_PROBE_MAX_TRIES     = 3,
-       ATA_EH_RESET_TRIES      = 3,
        ATA_EH_DEV_TRIES        = 3,
 
-       /* Drive spinup time (time from power-on to the first D2H FIS)
-        * in msecs - 8s currently.  Failing to get ready in this time
-        * isn't critical.  It will result in reset failure for
-        * controllers which can't wait for the first D2H FIS.  libata
-        * will retry, so it just has to be long enough to spin up
-        * most devices.
-        */
-       ATA_SPINUP_WAIT         = 8000,
-
        /* Horkage types. May be set by libata or controller on drives
           (some horkage may be drive/controller pair dependant */
 
@@ -348,8 +338,9 @@ struct ata_queued_cmd;
 
 /* typedefs */
 typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
-typedef int (*ata_prereset_fn_t)(struct ata_port *ap);
-typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes);
+typedef int (*ata_prereset_fn_t)(struct ata_port *ap, unsigned long deadline);
+typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes,
+                             unsigned long deadline);
 typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
 
 struct ata_ioports {
@@ -494,7 +485,6 @@ struct ata_eh_info {
        unsigned int            dev_action[ATA_MAX_DEVICES]; /* dev EH action */
        unsigned int            flags;          /* ATA_EHI_* flags */
 
-       unsigned long           hotplug_timestamp;
        unsigned int            probe_mask;
 
        char                    desc[ATA_EH_DESC_LEN];
@@ -688,13 +678,17 @@ extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
 extern void ata_bus_reset(struct ata_port *ap);
 extern int sata_set_spd(struct ata_port *ap);
-extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param);
-extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param);
-extern int ata_std_prereset(struct ata_port *ap);
-extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
-extern int sata_port_hardreset(struct ata_port *ap,
-                              const unsigned long *timing);
-extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
+extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param,
+                            unsigned long deadline);
+extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param,
+                          unsigned long deadline);
+extern int ata_std_prereset(struct ata_port *ap, unsigned long deadline);
+extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
+                            unsigned long deadline);
+extern int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing,
+                              unsigned long deadline);
+extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
+                             unsigned long deadline);
 extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
 extern void ata_port_disable(struct ata_port *);
 extern void ata_std_ports(struct ata_ioports *ioaddr);
@@ -750,6 +744,7 @@ extern void ata_host_resume(struct ata_host *host);
 extern int ata_ratelimit(void);
 extern int ata_busy_sleep(struct ata_port *ap,
                          unsigned long timeout_pat, unsigned long timeout);
+extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
 extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
                                void *data, unsigned long delay);
 extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
@@ -919,12 +914,7 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
 
 static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi)
 {
-       if (ehi->flags & ATA_EHI_HOTPLUGGED)
-               return;
-
        ehi->flags |= ATA_EHI_HOTPLUGGED | ATA_EHI_RESUME_LINK;
-       ehi->hotplug_timestamp = jiffies;
-
        ehi->action |= ATA_EH_SOFTRESET;
        ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
 }
index f9d71eab05eecc9a7d3891d346b86aa58d24233b..9202703be2a43d15f371a62090ba68ae9ae525e0 100644 (file)
@@ -425,6 +425,17 @@ static inline void list_splice_init_rcu(struct list_head *list,
 #define list_entry(ptr, type, member) \
        container_of(ptr, type, member)
 
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+       list_entry((ptr)->next, type, member)
+
 /**
  * list_for_each       -       iterate over a list
  * @pos:       the &struct list_head to use as a loop cursor.
index 191a595055f0063db70032a2074d8addb5eb0ad9..0b99b31f017b75f4f06dfa22b7d77af90a70e2ef 100644 (file)
@@ -64,6 +64,8 @@ struct loop_device {
        wait_queue_head_t       lo_event;
 
        request_queue_t         *lo_queue;
+       struct gendisk          *lo_disk;
+       struct list_head        lo_list;
 };
 
 #endif /* __KERNEL__ */
index bdc01127dced03198620b72441d3b38a49eb3a16..580b3f4956ee260b551850d157f1f1b3992a5429 100644 (file)
@@ -22,8 +22,15 @@ extern spinlock_t rtc_lock;          /* serialize CMOS RAM access */
 /* Some RTCs extend the mc146818 register set to support alarms of more
  * than 24 hours in the future; or dates that include a century code.
  * This platform_data structure can pass this information to the driver.
+ *
+ * Also, some platforms need suspend()/resume() hooks to kick in special
+ * handling of wake alarms, e.g. activating ACPI BIOS hooks or setting up
+ * a separate wakeup alarm used by some almost-clone chips.
  */
 struct cmos_rtc_board_info {
+       void    (*wake_on)(struct device *dev);
+       void    (*wake_off)(struct device *dev);
+
        u8      rtc_day_alarm;          /* zero, or register index */
        u8      rtc_mon_alarm;          /* zero, or register index */
        u8      rtc_century;            /* zero, or register index */
index 5cff2923092bfca0aaa9cd050f1855befbec03ad..37972704617f959c7abcd01d51c57684a72a6753 100644 (file)
@@ -94,6 +94,7 @@ struct mca_bus {
 struct mca_driver {
        const short             *id_table;
        void                    *driver_data;
+       int                     integrated_id;
        struct device_driver    driver;
 };
 #define to_mca_driver(mdriver) container_of(mdriver, struct mca_driver, driver)
@@ -125,6 +126,7 @@ extern enum MCA_AdapterStatus mca_device_status(struct mca_device *mca_dev);
 extern struct bus_type mca_bus_type;
 
 extern int mca_register_driver(struct mca_driver *drv);
+extern int mca_register_driver_integrated(struct mca_driver *, int);
 extern void mca_unregister_driver(struct mca_driver *drv);
 
 /* WARNING: only called by the boot time device setup */
index 11ec45e9a13271630c02881fdacc1ff321aebe70..39fd9c8ddd4b27b2adcf14659e5b4477a3ba8194 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
  *
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  *
  * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
  *
index 2f1544e83042af69d45862f216781de0fe22d9fe..d09b1345a3a14fcf7f5115a2d6efc092e25bd8ed 100644 (file)
@@ -83,6 +83,9 @@ struct per_cpu_pages {
 
 struct per_cpu_pageset {
        struct per_cpu_pages pcp[2];    /* 0: hot.  1: cold */
+#ifdef CONFIG_NUMA
+       s8 expire;
+#endif
 #ifdef CONFIG_SMP
        s8 stat_threshold;
        s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];
index 4af0b1fc282afbd9c8206d9e859f53b65bd29271..1fa4d9813b318043d8f291b231ad15431818b5db 100644 (file)
@@ -14,10 +14,9 @@ struct mnt_namespace {
        int event;
 };
 
-extern int copy_mnt_ns(int, struct task_struct *);
-extern void __put_mnt_ns(struct mnt_namespace *ns);
-extern struct mnt_namespace *dup_mnt_ns(struct task_struct *,
+extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
                struct fs_struct *);
+extern void __put_mnt_ns(struct mnt_namespace *ns);
 
 static inline void put_mnt_ns(struct mnt_namespace *ns)
 {
index f0b0faf42d5d7c99b376a5873387f75695d088f2..792d483c9af732feef2b0845190373d1e7535124 100644 (file)
@@ -356,6 +356,9 @@ struct module
           keeping pointers to this stuff */
        char *args;
 };
+#ifndef MODULE_ARCH_INIT
+#define MODULE_ARCH_INIT {}
+#endif
 
 /* FIXME: It'd be nice to isolate modules during init, too, so they
    aren't used before they (may) fail.  But presently too much code
@@ -370,16 +373,14 @@ struct module *module_text_address(unsigned long addr);
 struct module *__module_text_address(unsigned long addr);
 int is_module_address(unsigned long addr);
 
-/* Returns module and fills in value, defined and namebuf, or NULL if
+/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
    symnum out of range. */
-struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
-                               char *type, char *name, size_t namelen);
+int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+                       char *name, char *module_name, int *exported);
 
 /* Look for this name: can be of form module:name. */
 unsigned long module_kallsyms_lookup_name(const char *name);
 
-int is_exported(const char *name, const struct module *mod);
-
 extern void __module_put_and_exit(struct module *mod, long code)
        __attribute__((noreturn));
 #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
@@ -456,6 +457,8 @@ const char *module_address_lookup(unsigned long addr,
                                  unsigned long *symbolsize,
                                  unsigned long *offset,
                                  char **modname);
+int lookup_module_symbol_name(unsigned long addr, char *symname);
+int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
 
 /* For extable.c to search modules' exception tables. */
 const struct exception_table_entry *search_module_extables(unsigned long addr);
@@ -527,20 +530,24 @@ static inline const char *module_address_lookup(unsigned long addr,
        return NULL;
 }
 
-static inline struct module *module_get_kallsym(unsigned int symnum,
-                                               unsigned long *value,
-                                               char *type, char *name,
-                                               size_t namelen)
+static inline int lookup_module_symbol_name(unsigned long addr, char *symname)
 {
-       return NULL;
+       return -ERANGE;
 }
 
-static inline unsigned long module_kallsyms_lookup_name(const char *name)
+static inline int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name)
 {
-       return 0;
+       return -ERANGE;
 }
 
-static inline int is_exported(const char *name, const struct module *mod)
+static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
+                                       char *type, char *name,
+                                       char *module_name, int *exported)
+{
+       return -ERANGE;
+}
+
+static inline unsigned long module_kallsyms_lookup_name(const char *name)
 {
        return 0;
 }
index dab69afee2fa457b3d6feaf8bda7d3701d71c4ca..6d3047d8c91c877b9243a5093557ef77c5e61774 100644 (file)
@@ -33,7 +33,7 @@ struct mnt_namespace;
 
 #define MNT_SHARED     0x1000  /* if the vfsmount is a shared mount */
 #define MNT_UNBINDABLE 0x2000  /* if the vfsmount is a unbindable mount */
-#define MNT_PNODE_MASK 0x3000  /* propogation flag mask */
+#define MNT_PNODE_MASK 0x3000  /* propagation flag mask */
 
 struct vfsmount {
        struct list_head mnt_hash;
index fa253fa73aa328e2dd21a507b03debcc77fc4b47..0e09c005dda87d435ced705a25e852b7f5cca2de 100644 (file)
@@ -205,7 +205,8 @@ struct fat_mount_options {
                 numtail:1,       /* Does first alias have a numeric '~1' type tail? */
                 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
                 flush:1,         /* write things quickly */
-                nocase:1;        /* Does this need case conversion? 0=need case conversion*/
+                nocase:1,        /* Does this need case conversion? 0=need case conversion*/
+                usefree:1;       /* Use free_clusters for FAT32 */
 };
 
 #define FAT_HASH_BITS  8
index 45d482ce8397cf2920ac44919121bf3cb334100a..fd64ccfbce02874fd2600b79dc02d84767bde7ae 100644 (file)
@@ -9,10 +9,6 @@
 #ifndef __MTD_MTD_H__
 #define __MTD_MTD_H__
 
-#ifndef __KERNEL__
-#error This is a kernel header. Perhaps include mtd-user.h instead?
-#endif
-
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/uio.h>
@@ -137,9 +133,6 @@ struct mtd_info {
        int numeraseregions;
        struct mtd_erase_region_info *eraseregions;
 
-       /* This really shouldn't be here. It can go away in 2.5 */
-       u_int32_t bank_size;
-
        int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
 
        /* This stuff for eXecute-In-Place */
index cf197ad62da6cd8801102946609ad1bd3fd5549b..d2365c8dcacc86ebf872a2124b3dc16201c09877 100644 (file)
@@ -560,6 +560,7 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @chip_delay:                R/B delay value in us
  * @options:           Option flags, e.g. 16bit buswidth
  * @ecclayout:         ecc layout info structure
+ * @part_probe_types:  NULL-terminated array of probe types
  * @priv:              hardware controller specific settings
  */
 struct platform_nand_chip {
@@ -570,6 +571,7 @@ struct platform_nand_chip {
        struct nand_ecclayout   *ecclayout;
        int                     chip_delay;
        unsigned int            options;
+       const char              **part_probe_types;
        void                    *priv;
 };
 
@@ -578,6 +580,8 @@ struct platform_nand_chip {
  * @hwcontrol:         platform specific hardware control structure
  * @dev_ready:         platform specific function to read ready/busy pin
  * @select_chip:       platform specific chip select function
+ * @cmd_ctrl:          platform specific function for controlling
+ *                     ALE/CLE/nCE. Also used to write command and address
  * @priv:              private data to transport driver specific settings
  *
  * All fields are optional and depend on the hardware driver requirements
@@ -586,9 +590,21 @@ struct platform_nand_ctrl {
        void            (*hwcontrol)(struct mtd_info *mtd, int cmd);
        int             (*dev_ready)(struct mtd_info *mtd);
        void            (*select_chip)(struct mtd_info *mtd, int chip);
+       void            (*cmd_ctrl)(struct mtd_info *mtd, int dat,
+                                   unsigned int ctrl);
        void            *priv;
 };
 
+/**
+ * struct platform_nand_data - container structure for platform-specific data
+ * @chip:              chip level chip structure
+ * @ctrl:              controller level device structure
+ */
+struct platform_nand_data {
+       struct platform_nand_chip       chip;
+       struct platform_nand_ctrl       ctrl;
+};
+
 /* Some helpers to access the data structures */
 static inline
 struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
index b81bc2adaeff138095b0db333948f5c03db8d610..0d50ea3df6896ebcf9a60f216a0d72ba9bd14de8 100644 (file)
@@ -121,11 +121,12 @@ static inline int fastcall mutex_is_locked(struct mutex *lock)
  * Also see Documentation/mutex-design.txt.
  */
 extern void fastcall mutex_lock(struct mutex *lock);
-extern int fastcall mutex_lock_interruptible(struct mutex *lock);
+extern int __must_check fastcall mutex_lock_interruptible(struct mutex *lock);
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
-extern int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass);
+extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock,
+                                       unsigned int subclass);
 #else
 # define mutex_lock_nested(lock, subclass) mutex_lock(lock)
 # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock)
index 409b6e02f337cdf757ecfbf90fb009a6632aa611..c9c05a78e9bb32438f866b9d99564cf87ff02287 100644 (file)
@@ -44,7 +44,6 @@
 #define NFS4_ACL_MAX 170
 
 struct nfs4_acl *nfs4_acl_new(int);
-void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 int nfs4_acl_get_whotype(char *, u32);
 int nfs4_acl_write_who(int who, char *p);
 int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
index c95d5e642548428cbdbff5ad0f6462f6ee75f4d8..52b4378311c86393e04038d17eb1f9466f980bc5 100644 (file)
@@ -82,7 +82,7 @@ struct nfs_server {
        struct rpc_clnt *       client_acl;     /* ACL RPC client handle */
        struct nfs_iostats *    io_stats;       /* I/O statistics */
        struct backing_dev_info backing_dev_info;
-       atomic_t                writeback;      /* number of writeback pages */
+       atomic_long_t           writeback;      /* number of writeback pages */
        int                     flags;          /* various flags */
        unsigned int            caps;           /* server capabilities */
        unsigned int            rsize;          /* read size */
index 10a43ed0527eb0215acba9078786105fb1f8b8de..9431101bf8769508db8dc6263927049d1cfdb9df 100644 (file)
@@ -112,32 +112,40 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
 
 #ifdef __KERNEL__
 
-extern int atomic_notifier_chain_register(struct atomic_notifier_head *,
-               struct notifier_block *);
-extern int blocking_notifier_chain_register(struct blocking_notifier_head *,
-               struct notifier_block *);
-extern int raw_notifier_chain_register(struct raw_notifier_head *,
-               struct notifier_block *);
-extern int srcu_notifier_chain_register(struct srcu_notifier_head *,
-               struct notifier_block *);
-
-extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *,
-               struct notifier_block *);
-extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *,
-               struct notifier_block *);
-extern int raw_notifier_chain_unregister(struct raw_notifier_head *,
-               struct notifier_block *);
-extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *,
-               struct notifier_block *);
-
-extern int atomic_notifier_call_chain(struct atomic_notifier_head *,
+extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+               struct notifier_block *nb);
+extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+               struct notifier_block *nb);
+extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
+               struct notifier_block *nb);
+extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
+               struct notifier_block *nb);
+
+extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+               struct notifier_block *nb);
+extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+               struct notifier_block *nb);
+extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
+               struct notifier_block *nb);
+extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
+               struct notifier_block *nb);
+
+extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
                unsigned long val, void *v);
-extern int blocking_notifier_call_chain(struct blocking_notifier_head *,
+extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+       unsigned long val, void *v, int nr_to_call, int *nr_calls);
+extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
                unsigned long val, void *v);
-extern int raw_notifier_call_chain(struct raw_notifier_head *,
+extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+       unsigned long val, void *v, int nr_to_call, int *nr_calls);
+extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
                unsigned long val, void *v);
-extern int srcu_notifier_call_chain(struct srcu_notifier_head *,
+extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,
+       unsigned long val, void *v, int nr_to_call, int *nr_calls);
+extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
                unsigned long val, void *v);
+extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+       unsigned long val, void *v, int nr_to_call, int *nr_calls);
 
 #define NOTIFY_DONE            0x0000          /* Don't care */
 #define NOTIFY_OK              0x0001          /* Suits me */
@@ -186,6 +194,20 @@ extern int srcu_notifier_call_chain(struct srcu_notifier_head *,
 #define CPU_DOWN_PREPARE       0x0005 /* CPU (unsigned)v going down */
 #define CPU_DOWN_FAILED                0x0006 /* CPU (unsigned)v NOT going down */
 #define CPU_DEAD               0x0007 /* CPU (unsigned)v dead */
+#define CPU_LOCK_ACQUIRE       0x0008 /* Acquire all hotcpu locks */
+#define CPU_LOCK_RELEASE       0x0009 /* Release all hotcpu locks */
+
+/* Used for CPU hotplug events occuring while tasks are frozen due to a suspend
+ * operation in progress
+ */
+#define CPU_TASKS_FROZEN       0x0010
+
+#define CPU_ONLINE_FROZEN      (CPU_ONLINE | CPU_TASKS_FROZEN)
+#define CPU_UP_PREPARE_FROZEN  (CPU_UP_PREPARE | CPU_TASKS_FROZEN)
+#define CPU_UP_CANCELED_FROZEN (CPU_UP_CANCELED | CPU_TASKS_FROZEN)
+#define CPU_DOWN_PREPARE_FROZEN        (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
+#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
+#define CPU_DEAD_FROZEN                (CPU_DEAD | CPU_TASKS_FROZEN)
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_NOTIFIER_H */
index 0b9f0dc30d6114a1f5177a7fde829d2199137172..189e0dc993ab6ab84a577d1ee0635946ec077072 100644 (file)
@@ -31,10 +31,11 @@ struct nsproxy {
 };
 extern struct nsproxy init_nsproxy;
 
-struct nsproxy *dup_namespaces(struct nsproxy *orig);
 int copy_namespaces(int flags, struct task_struct *tsk);
 void get_task_namespaces(struct task_struct *tsk);
 void free_nsproxy(struct nsproxy *ns);
+int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
+       struct fs_struct *);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
index b4def5e083ed4fec215505accf4ec4f32f88c7ac..8a83537d69785117201334798bd02cc077cac06b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/compiler.h>
 #include <asm/uaccess.h>
 #include <linux/gfp.h>
+#include <linux/bitops.h>
 
 /*
  * Bits in mapping->flags.  The lower __GFP_BITS_SHIFT bits are the page
 #define        AS_EIO          (__GFP_BITS_SHIFT + 0)  /* IO error on async write */
 #define AS_ENOSPC      (__GFP_BITS_SHIFT + 1)  /* ENOSPC on async write */
 
+static inline void mapping_set_error(struct address_space *mapping, int error)
+{
+       if (error) {
+               if (error == -ENOSPC)
+                       set_bit(AS_ENOSPC, &mapping->flags);
+               else
+                       set_bit(AS_EIO, &mapping->flags);
+       }
+}
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
        return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
index 80682aaa8f183c741aa0d079eb44ec3de3aa84d7..9cdd6943e01b8145c7d105d7d89b17c63d40c604 100644 (file)
@@ -279,6 +279,10 @@ struct parport {
        int dma;
        int muxport;            /* which muxport (if any) this is */
        int portnum;            /* which physical parallel port (not mux) */
+       struct device *dev;     /* Physical device associated with IO/DMA.
+                                * This may unfortulately be null if the
+                                * port has a legacy driver.
+                                */
 
        struct parport *physport;
                                /* If this is a non-default mux
@@ -289,7 +293,7 @@ struct parport {
                                   following structure members are
                                   meaningless: devices, cad, muxsel,
                                   waithead, waittail, flags, pdir,
-                                  ieee1284, *_lock.
+                                  dev, ieee1284, *_lock.
 
                                   It this is a default mux parport, or
                                   there is no mux involved, this points to
@@ -302,7 +306,7 @@ struct parport {
 
        struct pardevice *waithead;
        struct pardevice *waittail;
-       
+
        struct list_head list;
        unsigned int flags;
 
index 1cc0f6b1a49a97d901b079f0daea1ffbd35e16e6..ea8c6d84996dc64cfd52004a68c02e4480a1e8d6 100644 (file)
@@ -38,7 +38,6 @@ struct parport_pc_private {
        /* buffer suitable for DMA, if DMA enabled */
        char *dma_buf;
        dma_addr_t dma_handle;
-       struct pci_dev *dev;
        struct list_head list;
        struct parport *port;
 };
@@ -232,7 +231,7 @@ extern int parport_pc_claim_resources(struct parport *p);
 extern struct parport *parport_pc_probe_port (unsigned long base,
                                              unsigned long base_hi,
                                              int irq, int dma,
-                                             struct pci_dev *dev);
+                                             struct device *dev);
 extern void parport_pc_unregister_port (struct parport *p);
 
 #endif
diff --git a/include/linux/phantom.h b/include/linux/phantom.h
new file mode 100644 (file)
index 0000000..d3ebbfa
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (C) 2005-2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ */
+
+#ifndef __PHANTOM_H
+#define __PHANTOM_H
+
+#include <asm/types.h>
+
+/* PHN_(G/S)ET_REG param */
+struct phm_reg {
+       __u32 reg;
+       __u32 value;
+};
+
+/* PHN_(G/S)ET_REGS param */
+struct phm_regs {
+       __u32 count;
+       __u32 mask;
+       __u32 values[8];
+};
+
+#define PH_IOC_MAGIC           'p'
+#define PHN_GET_REG            _IOWR(PH_IOC_MAGIC, 0, struct phm_reg *)
+#define PHN_SET_REG            _IOW (PH_IOC_MAGIC, 1, struct phm_reg *)
+#define PHN_GET_REGS           _IOWR(PH_IOC_MAGIC, 2, struct phm_regs *)
+#define PHN_SET_REGS           _IOW (PH_IOC_MAGIC, 3, struct phm_regs *)
+#define PH_IOC_MAXNR           3
+
+#define PHN_CONTROL            0x6     /* control byte in iaddr space */
+#define PHN_CTL_AMP            0x1     /*   switch after torques change */
+#define PHN_CTL_BUT            0x2     /*   is button switched */
+#define PHN_CTL_IRQ            0x10    /*   is irq enabled */
+
+#define PHN_ZERO_FORCE         2048    /* zero torque on motor */
+
+#endif
index 2833806d42c635de975f76c3c078dd113c01b8e3..169c6c24209b471e63a61c48ef4d16cd9ad95717 100644 (file)
@@ -29,7 +29,7 @@ static inline void get_pid_ns(struct pid_namespace *ns)
        kref_get(&ns->kref);
 }
 
-extern int copy_pid_ns(int flags, struct task_struct *tsk);
+extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
 extern void free_pid_ns(struct kref *kref);
 
 static inline void put_pid_ns(struct pid_namespace *ns)
index 6e8fa3049e5d097fc5f96400350240e5224ca48e..87545e0f0b5814bdf6dc115165851b062a3df8b6 100644 (file)
@@ -107,26 +107,11 @@ typedef int __bitwise suspend_state_t;
 #define PM_SUSPEND_ON          ((__force suspend_state_t) 0)
 #define PM_SUSPEND_STANDBY     ((__force suspend_state_t) 1)
 #define PM_SUSPEND_MEM         ((__force suspend_state_t) 3)
-#define PM_SUSPEND_DISK                ((__force suspend_state_t) 4)
-#define PM_SUSPEND_MAX         ((__force suspend_state_t) 5)
-
-typedef int __bitwise suspend_disk_method_t;
-
-/* invalid must be 0 so struct pm_ops initialisers can leave it out */
-#define PM_DISK_INVALID                ((__force suspend_disk_method_t) 0)
-#define        PM_DISK_PLATFORM        ((__force suspend_disk_method_t) 1)
-#define        PM_DISK_SHUTDOWN        ((__force suspend_disk_method_t) 2)
-#define        PM_DISK_REBOOT          ((__force suspend_disk_method_t) 3)
-#define        PM_DISK_TEST            ((__force suspend_disk_method_t) 4)
-#define        PM_DISK_TESTPROC        ((__force suspend_disk_method_t) 5)
-#define        PM_DISK_MAX             ((__force suspend_disk_method_t) 6)
+#define PM_SUSPEND_MAX         ((__force suspend_state_t) 4)
 
 /**
  * struct pm_ops - Callbacks for managing platform dependent suspend states.
  * @valid: Callback to determine whether the given state can be entered.
- *     If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
- *     always valid and never passed to this call. If not assigned,
- *     no suspend states are valid.
  *     Valid states are advertised in /sys/power/state but can still
  *     be rejected by prepare or enter if the conditions aren't right.
  *     There is a %pm_valid_only_mem function available that can be assigned
@@ -140,24 +125,12 @@ typedef int __bitwise suspend_disk_method_t;
  *
  * @finish: Called when the system has left the given state and all devices
  *     are resumed. The return value is ignored.
- *
- * @pm_disk_mode: The generic code always allows one of the shutdown methods
- *     %PM_DISK_SHUTDOWN, %PM_DISK_REBOOT, %PM_DISK_TEST and
- *     %PM_DISK_TESTPROC. If this variable is set, the mode it is set
- *     to is allowed in addition to those modes and is also made default.
- *     When this mode is sent selected, the @prepare call will be called
- *     before suspending to disk (if present), the @enter call should be
- *     present and will be called after all state has been saved and the
- *     machine is ready to be powered off; the @finish callback is called
- *     after state has been restored. All these calls are called with
- *     %PM_SUSPEND_DISK as the state.
  */
 struct pm_ops {
        int (*valid)(suspend_state_t state);
        int (*prepare)(suspend_state_t state);
        int (*enter)(suspend_state_t state);
        int (*finish)(suspend_state_t state);
-       suspend_disk_method_t pm_disk_mode;
 };
 
 /**
@@ -276,8 +249,6 @@ extern void device_power_up(void);
 extern void device_resume(void);
 
 #ifdef CONFIG_PM
-extern suspend_disk_method_t pm_disk_mode;
-
 extern int device_suspend(pm_message_t state);
 extern int device_prepare_suspend(pm_message_t state);
 
index b0952e532ed52a0e05cfb768bc7a479ce6d2ba34..37ca57392addbfe69f0707d8b493653b4ccaa6ca 100644 (file)
@@ -225,4 +225,12 @@ extern unsigned int pmu_power_flags;
 /* Backlight */
 extern void pmu_backlight_init(void);
 
+/* some code needs to know if the PMU was suspended for hibernation */
+#ifdef CONFIG_PM
+extern int pmu_sys_suspended;
+#else
+/* if power management is not configured it can't be suspended */
+#define pmu_sys_suspended      0
+#endif
+
 #endif /* __KERNEL__ */
index 9a5226f0f169789c5040d68b5a888de8484829ff..2a1897e6f9372a08a81054bd3d67cb8a43fe59c0 100644 (file)
@@ -177,6 +177,7 @@ static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data
 
 struct pnp_dev {
        struct device dev;              /* Driver Model device interface */
+       u64 dma_mask;
        unsigned char number;           /* used as an index, must be unique */
        int status;
 
@@ -363,6 +364,7 @@ int pnp_add_device(struct pnp_dev *dev);
 int pnp_device_attach(struct pnp_dev *pnp_dev);
 void pnp_device_detach(struct pnp_dev *pnp_dev);
 extern struct list_head pnp_global;
+extern int pnp_platform_devices;
 
 /* multidevice card support */
 int pnp_add_card(struct pnp_card *card);
@@ -410,6 +412,7 @@ static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
 static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
+#define pnp_platform_devices 0
 
 /* multidevice card support */
 static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
index 95f518b176840109023da0a9aa51c5b4b38bb557..d93c300a3449ba81bf38f9aec6c95eb5942cb9ab 100644 (file)
@@ -15,8 +15,8 @@
  * Magic nums for obj red zoning.
  * Placed in the first word before and the first word after an obj.
  */
-#define        RED_INACTIVE    0x5A2CF071UL    /* when obj is inactive */
-#define        RED_ACTIVE      0x170FC2A5UL    /* when obj is active */
+#define        RED_INACTIVE    0x09F911029D74E35BULL   /* when obj is inactive */
+#define        RED_ACTIVE      0xD84156C5635688C0ULL   /* when obj is active */
 
 #define SLUB_RED_INACTIVE      0xbb
 #define SLUB_RED_ACTIVE                0xcc
index f4f7a63cae1f858f3779adf9b607d526b3fa038b..3469f96bc8b2d0e11543d57246f4c4ae75f64115 100644 (file)
@@ -106,6 +106,9 @@ int task_statm(struct mm_struct *, int *, int *, int *, int *);
 char *task_mem(struct mm_struct *, char *);
 void clear_refs_smap(struct mm_struct *mm);
 
+struct proc_dir_entry *de_get(struct proc_dir_entry *de);
+void de_put(struct proc_dir_entry *de);
+
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                                                struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
index 77db80a953d61ba400890c4a5b128606c5ec6a28..62439828395e3f3faa424f3305844713f02aca60 100644 (file)
@@ -44,8 +44,6 @@
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef __u64 qsize_t;          /* Type in which we store sizes */
 
-extern spinlock_t dq_data_lock;
-
 /* Size of blocks in which are counted size limits */
 #define QUOTABLOCK_BITS 10
 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
@@ -139,6 +137,8 @@ struct if_dqinfo {
 #include <linux/dqblk_v1.h>
 #include <linux/dqblk_v2.h>
 
+extern spinlock_t dq_data_lock;
+
 /* Maximal numbers of writes for quota operation (insert/delete/update)
  * (over VFS all formats) */
 #define DQUOT_INIT_ALLOC max(V1_INIT_ALLOC, V2_INIT_ALLOC)
index 90c23f690c0deab4fedeb6f5126dfbb4838cb54d..5110201a415949e5e10bd8381ff4f38e120320cf 100644 (file)
@@ -37,9 +37,6 @@ extern int dquot_release(struct dquot *dquot);
 extern int dquot_commit_info(struct super_block *sb, int type);
 extern int dquot_mark_dquot_dirty(struct dquot *dquot);
 
-int remove_inode_dquot_ref(struct inode *inode, int type,
-                          struct list_head *tofree_head);
-
 extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
 extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
                int format_id, int type);
index 0deb842541acee1aad74d1e742895ba9812d0661..f9e77d2ee3201ea3565a409216c601734fc17140 100644 (file)
@@ -87,10 +87,10 @@ do {                                                                        \
  * management of their lifetimes must be completely managed by API users.
  *
  * For API usage, in general,
- * - any function _modifying_ the the tree or tags (inserting or deleting
+ * - any function _modifying_ the tree or tags (inserting or deleting
  *   items, setting or clearing tags must exclude other modifications, and
  *   exclude any functions reading the tree.
- * - any function _reading_ the the tree or tags (looking up items or tags,
+ * - any function _reading_ the tree or tags (looking up items or tags,
  *   gang lookups) must exclude modifications to the tree, but may occur
  *   concurrently with other readers.
  *
index de72c49747c8b20ac6f0844bc2703d8f22f347b9..a121f36f443729feef8ae03c240496429a64cf4b 100644 (file)
@@ -201,7 +201,6 @@ struct mddev_s
        struct mutex                    reconfig_mutex;
        atomic_t                        active;
 
-       int                             changed;        /* true if we might need to reread partition info */
        int                             degraded;       /* whether md should consider
                                                         * adding a spare
                                                         */
index 3a28742d86f96ce04faaad22f0b296619724da89..1e5488ede037799e36d421547fbf0689471fcc16 100644 (file)
@@ -401,9 +401,10 @@ struct reiserfs_sb_info {
        int reserved_blocks;    /* amount of blocks reserved for further allocations */
        spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */
        struct dentry *priv_root;       /* root of /.reiserfs_priv */
+#ifdef CONFIG_REISERFS_FS_XATTR
        struct dentry *xattr_root;      /* root of /.reiserfs_priv/.xa */
        struct rw_semaphore xattr_dir_sem;
-
+#endif
        int j_errno;
 #ifdef CONFIG_QUOTA
        char *s_qf_names[MAXQUOTAS];
index 759a0f97bec23db4e26bddcfe124e095ced54b3a..6cd8c4425fc7d5dfb400b37b436c960bf6e163d7 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/fs.h>
@@ -38,7 +39,7 @@ struct rchan_buf
        size_t subbufs_consumed;        /* count of sub-buffers consumed */
        struct rchan *chan;             /* associated channel */
        wait_queue_head_t read_wait;    /* reader wait queue */
-       struct delayed_work wake_readers; /* reader wake-up work struct */
+       struct timer_list timer;        /* reader wake-up timer */
        struct dentry *dentry;          /* channel file dentry */
        struct kref kref;               /* channel buffer refcount */
        struct page **page_array;       /* array of current buffer pages */
index ace25acfdc97375d0d403afb4bf12c08443e6309..746580c1939c028d8f8ef8dc6bb460e5ed6dfc17 100644 (file)
@@ -34,6 +34,7 @@
  * @prim:      Primitive element, index form
  * @iprim:     prim-th root of 1, index form
  * @gfpoly:    The primitive generator polynominal
+ * @gffunc:    Function to generate the field, if non-canonical representation
  * @users:     Users of this structure
  * @list:      List entry for the rs control list
 */
@@ -48,6 +49,7 @@ struct rs_control {
        int             prim;
        int             iprim;
        int             gfpoly;
+       int             (*gffunc)(int);
        int             users;
        struct list_head list;
 };
@@ -77,6 +79,8 @@ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
 /* Create or get a matching rs control structure */
 struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
                           int nroots);
+struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int),
+                                         int fcr, int prim, int nroots);
 
 /* Release a rs control structure */
 void free_rs(struct rs_control *rs);
index 5e22d4510d11107eb67ffdb3c82f378ef1f9eccc..6d5e4a46781ef1ca6dff692b6685e2e645c42153 100644 (file)
@@ -4,7 +4,7 @@
  * service. It is used with both the legacy mc146818 and also  EFI
  * Struct rtc_time and first 12 ioctl by Paul Gortmaker, 1996 - separated out
  * from <linux/mc146818rtc.h> to this file for 2.4 kernels.
- * 
+ *
  * Copyright (C) 1999 Hewlett-Packard Co.
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  */
@@ -13,7 +13,7 @@
 
 /*
  * The struct used to pass data via the following ioctl. Similar to the
- * struct tm in <time.h>, but it needs to be here so that the kernel 
+ * struct tm in <time.h>, but it needs to be here so that the kernel
  * source is self contained, allowing cross-compiles, etc. etc.
  */
 
@@ -50,7 +50,7 @@ struct rtc_wkalrm {
  *   pll_value*pll_posmult/pll_clock
  * -ve pll_value means clock will run slower by
  *   pll_value*pll_negmult/pll_clock
- */ 
+ */
 
 struct rtc_pll_info {
        int pll_ctrl;       /* placeholder for fancier control */
@@ -106,7 +106,6 @@ extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year
 extern int rtc_valid_tm(struct rtc_time *tm);
 extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
 extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
-extern void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm);
 
 #include <linux/device.h>
 #include <linux/seq_file.h>
@@ -136,7 +135,7 @@ struct rtc_task;
 
 struct rtc_device
 {
-       struct class_device class_dev;
+       struct device dev;
        struct module *owner;
 
        int id;
@@ -145,7 +144,6 @@ struct rtc_device
        const struct rtc_class_ops *ops;
        struct mutex ops_lock;
 
-       struct class_device *rtc_dev;
        struct cdev char_dev;
        struct mutex char_lock;
 
@@ -169,35 +167,34 @@ struct rtc_device
        unsigned int uie_timer_active:1;
 #endif
 };
-#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev)
+#define to_rtc_device(d) container_of(d, struct rtc_device, dev)
 
 extern struct rtc_device *rtc_device_register(const char *name,
                                        struct device *dev,
                                        const struct rtc_class_ops *ops,
                                        struct module *owner);
-extern void rtc_device_unregister(struct rtc_device *rdev);
-extern int rtc_interface_register(struct class_interface *intf);
+extern void rtc_device_unregister(struct rtc_device *rtc);
 
-extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm);
-extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm);
-extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs);
-extern int rtc_read_alarm(struct class_device *class_dev,
+extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
+extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
+extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
+extern int rtc_read_alarm(struct rtc_device *rtc,
                        struct rtc_wkalrm *alrm);
-extern int rtc_set_alarm(struct class_device *class_dev,
+extern int rtc_set_alarm(struct rtc_device *rtc,
                                struct rtc_wkalrm *alrm);
-extern void rtc_update_irq(struct class_device *class_dev,
+extern void rtc_update_irq(struct rtc_device *rtc,
                        unsigned long num, unsigned long events);
 
-extern struct class_device *rtc_class_open(char *name);
-extern void rtc_class_close(struct class_device *class_dev);
+extern struct rtc_device *rtc_class_open(char *name);
+extern void rtc_class_close(struct rtc_device *rtc);
 
-extern int rtc_irq_register(struct class_device *class_dev,
+extern int rtc_irq_register(struct rtc_device *rtc,
                                struct rtc_task *task);
-extern void rtc_irq_unregister(struct class_device *class_dev,
+extern void rtc_irq_unregister(struct rtc_device *rtc,
                                struct rtc_task *task);
-extern int rtc_irq_set_state(struct class_device *class_dev,
+extern int rtc_irq_set_state(struct rtc_device *rtc,
                                struct rtc_task *task, int enabled);
-extern int rtc_irq_set_freq(struct class_device *class_dev,
+extern int rtc_irq_set_freq(struct rtc_device *rtc,
                                struct rtc_task *task, int freq);
 
 typedef struct rtc_task {
index a1707583de495993d152b1e5b35b90643660ea98..17b72d88c4cb4c048f1f24e3d5b8f1e6b28b6529 100644 (file)
@@ -194,6 +194,14 @@ extern void sched_init_smp(void);
 extern void init_idle(struct task_struct *idle, int cpu);
 
 extern cpumask_t nohz_cpu_mask;
+#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
+extern int select_nohz_load_balancer(int cpu);
+#else
+static inline int select_nohz_load_balancer(int cpu)
+{
+       return 0;
+}
+#endif
 
 /*
  * Only dump TASK_* tasks. (0 for all tasks)
@@ -226,6 +234,7 @@ extern void scheduler_tick(void);
 extern void softlockup_tick(void);
 extern void spawn_softlockup_task(void);
 extern void touch_softlockup_watchdog(void);
+extern void touch_all_softlockup_watchdogs(void);
 #else
 static inline void softlockup_tick(void)
 {
@@ -236,6 +245,9 @@ static inline void spawn_softlockup_task(void)
 static inline void touch_softlockup_watchdog(void)
 {
 }
+static inline void touch_all_softlockup_watchdogs(void)
+{
+}
 #endif
 
 
@@ -668,8 +680,14 @@ struct sched_group {
        /*
         * CPU power of this group, SCHED_LOAD_SCALE being max power for a
         * single CPU. This is read only (except for setup, hotplug CPU).
+        * Note : Never change cpu_power without recompute its reciprocal
+        */
+       unsigned int __cpu_power;
+       /*
+        * reciprocal value of cpu_power to avoid expensive divides
+        * (see include/linux/reciprocal_div.h)
         */
-       unsigned long cpu_power;
+       u32 reciprocal_cpu_power;
 };
 
 struct sched_domain {
@@ -799,10 +817,10 @@ struct prio_array;
 
 struct task_struct {
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
-       struct thread_info *thread_info;
+       void *stack;
        atomic_t usage;
-       unsigned long flags;    /* per process flags, defined below */
-       unsigned long ptrace;
+       unsigned int flags;     /* per process flags, defined below */
+       unsigned int ptrace;
 
        int lock_depth;         /* BKL lock depth */
 
@@ -825,7 +843,7 @@ struct task_struct {
        unsigned long long sched_time; /* sched_clock time spent running */
        enum sleep_type sleep_type;
 
-       unsigned long policy;
+       unsigned int policy;
        cpumask_t cpus_allowed;
        unsigned int time_slice, first_time_slice;
 
@@ -845,11 +863,11 @@ struct task_struct {
 
 /* task state */
        struct linux_binfmt *binfmt;
-       long exit_state;
+       int exit_state;
        int exit_code, exit_signal;
        int pdeath_signal;  /*  The signal sent when the parent dies  */
        /* ??? */
-       unsigned long personality;
+       unsigned int personality;
        unsigned did_exec:1;
        pid_t pid;
        pid_t tgid;
@@ -881,7 +899,7 @@ struct task_struct {
        int __user *set_child_tid;              /* CLONE_CHILD_SETTID */
        int __user *clear_child_tid;            /* CLONE_CHILD_CLEARTID */
 
-       unsigned long rt_priority;
+       unsigned int rt_priority;
        cputime_t utime, stime;
        unsigned long nvcsw, nivcsw; /* context switch counts */
        struct timespec start_time;
@@ -1299,6 +1317,7 @@ extern int in_egroup_p(gid_t);
 
 extern void proc_caches_init(void);
 extern void flush_signals(struct task_struct *);
+extern void ignore_signals(struct task_struct *);
 extern void flush_signal_handlers(struct task_struct *, int force_default);
 extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info);
 
@@ -1494,8 +1513,8 @@ static inline void unlock_task_sighand(struct task_struct *tsk,
 
 #ifndef __HAVE_THREAD_FUNCTIONS
 
-#define task_thread_info(task) (task)->thread_info
-#define task_stack_page(task) ((void*)((task)->thread_info))
+#define task_thread_info(task) ((struct thread_info *)(task)->stack)
+#define task_stack_page(task)  ((task)->stack)
 
 static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
 {
@@ -1505,7 +1524,7 @@ static inline void setup_thread_stack(struct task_struct *p, struct task_struct
 
 static inline unsigned long *end_of_stack(struct task_struct *p)
 {
-       return (unsigned long *)(p->thread_info + 1);
+       return (unsigned long *)(task_thread_info(p) + 1);
 }
 
 #endif
@@ -1641,10 +1660,7 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
 extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
 extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
 
-#include <linux/sysdev.h>
 extern int sched_mc_power_savings, sched_smt_power_savings;
-extern struct sysdev_attribute attr_sched_mc_power_savings, attr_sched_smt_power_savings;
-extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls);
 
 extern void normalize_rt_tasks(void);
 
index 47e82c120f9ab662963ab17a25fd43417a03998b..9eb9e0fe03312614b8702e0435c1604b928e4190 100644 (file)
@@ -322,7 +322,7 @@ struct request_sock;
  *     @dir contains the inode structure of parent of the new file.
  *     @dentry contains the dentry structure of the new file.
  *     @mode contains the mode of the new file.
- *     @dev contains the the device number.
+ *     @dev contains the device number.
  *     Return 0 if permission is granted.
  * @inode_rename:
  *     Check for permission to rename a file or directory.
index 14749056dd630ac0072439ed53225caac9025c2f..3fa0fab4a04bfc3b5ce155a1b92146cde54d962d 100644 (file)
@@ -243,6 +243,131 @@ extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
 
 extern struct kmem_cache *sighand_cachep;
 
+/*
+ * In POSIX a signal is sent either to a specific thread (Linux task)
+ * or to the process as a whole (Linux thread group).  How the signal
+ * is sent determines whether it's to one thread or the whole group,
+ * which determines which signal mask(s) are involved in blocking it
+ * from being delivered until later.  When the signal is delivered,
+ * either it's caught or ignored by a user handler or it has a default
+ * effect that applies to the whole thread group (POSIX process).
+ *
+ * The possible effects an unblocked signal set to SIG_DFL can have are:
+ *   ignore    - Nothing Happens
+ *   terminate - kill the process, i.e. all threads in the group,
+ *               similar to exit_group.  The group leader (only) reports
+ *               WIFSIGNALED status to its parent.
+ *   coredump  - write a core dump file describing all threads using
+ *               the same mm and then kill all those threads
+ *   stop      - stop all the threads in the group, i.e. TASK_STOPPED state
+ *
+ * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
+ * Other signals when not blocked and set to SIG_DFL behaves as follows.
+ * The job control signals also have other special effects.
+ *
+ *     +--------------------+------------------+
+ *     |  POSIX signal      |  default action  |
+ *     +--------------------+------------------+
+ *     |  SIGHUP            |  terminate       |
+ *     |  SIGINT            |  terminate       |
+ *     |  SIGQUIT           |  coredump        |
+ *     |  SIGILL            |  coredump        |
+ *     |  SIGTRAP           |  coredump        |
+ *     |  SIGABRT/SIGIOT    |  coredump        |
+ *     |  SIGBUS            |  coredump        |
+ *     |  SIGFPE            |  coredump        |
+ *     |  SIGKILL           |  terminate(+)    |
+ *     |  SIGUSR1           |  terminate       |
+ *     |  SIGSEGV           |  coredump        |
+ *     |  SIGUSR2           |  terminate       |
+ *     |  SIGPIPE           |  terminate       |
+ *     |  SIGALRM           |  terminate       |
+ *     |  SIGTERM           |  terminate       |
+ *     |  SIGCHLD           |  ignore          |
+ *     |  SIGCONT           |  ignore(*)       |
+ *     |  SIGSTOP           |  stop(*)(+)      |
+ *     |  SIGTSTP           |  stop(*)         |
+ *     |  SIGTTIN           |  stop(*)         |
+ *     |  SIGTTOU           |  stop(*)         |
+ *     |  SIGURG            |  ignore          |
+ *     |  SIGXCPU           |  coredump        |
+ *     |  SIGXFSZ           |  coredump        |
+ *     |  SIGVTALRM         |  terminate       |
+ *     |  SIGPROF           |  terminate       |
+ *     |  SIGPOLL/SIGIO     |  terminate       |
+ *     |  SIGSYS/SIGUNUSED  |  coredump        |
+ *     |  SIGSTKFLT         |  terminate       |
+ *     |  SIGWINCH          |  ignore          |
+ *     |  SIGPWR            |  terminate       |
+ *     |  SIGRTMIN-SIGRTMAX |  terminate       |
+ *     +--------------------+------------------+
+ *     |  non-POSIX signal  |  default action  |
+ *     +--------------------+------------------+
+ *     |  SIGEMT            |  coredump        |
+ *     +--------------------+------------------+
+ *
+ * (+) For SIGKILL and SIGSTOP the action is "always", not just "default".
+ * (*) Special job control effects:
+ * When SIGCONT is sent, it resumes the process (all threads in the group)
+ * from TASK_STOPPED state and also clears any pending/queued stop signals
+ * (any of those marked with "stop(*)").  This happens regardless of blocking,
+ * catching, or ignoring SIGCONT.  When any stop signal is sent, it clears
+ * any pending/queued SIGCONT signals; this happens regardless of blocking,
+ * catching, or ignored the stop signal, though (except for SIGSTOP) the
+ * default action of stopping the process may happen later or never.
+ */
+
+#ifdef SIGEMT
+#define SIGEMT_MASK    rt_sigmask(SIGEMT)
+#else
+#define SIGEMT_MASK    0
+#endif
+
+#if SIGRTMIN > BITS_PER_LONG
+#define rt_sigmask(sig)        (1ULL << ((sig)-1))
+#else
+#define rt_sigmask(sig)        sigmask(sig)
+#endif
+#define siginmask(sig, mask) (rt_sigmask(sig) & (mask))
+
+#define SIG_KERNEL_ONLY_MASK (\
+       rt_sigmask(SIGKILL)   |  rt_sigmask(SIGSTOP))
+
+#define SIG_KERNEL_STOP_MASK (\
+       rt_sigmask(SIGSTOP)   |  rt_sigmask(SIGTSTP)   | \
+       rt_sigmask(SIGTTIN)   |  rt_sigmask(SIGTTOU)   )
+
+#define SIG_KERNEL_COREDUMP_MASK (\
+        rt_sigmask(SIGQUIT)   |  rt_sigmask(SIGILL)    | \
+       rt_sigmask(SIGTRAP)   |  rt_sigmask(SIGABRT)   | \
+        rt_sigmask(SIGFPE)    |  rt_sigmask(SIGSEGV)   | \
+       rt_sigmask(SIGBUS)    |  rt_sigmask(SIGSYS)    | \
+        rt_sigmask(SIGXCPU)   |  rt_sigmask(SIGXFSZ)   | \
+       SIGEMT_MASK                                    )
+
+#define SIG_KERNEL_IGNORE_MASK (\
+        rt_sigmask(SIGCONT)   |  rt_sigmask(SIGCHLD)   | \
+       rt_sigmask(SIGWINCH)  |  rt_sigmask(SIGURG)    )
+
+#define sig_kernel_only(sig) \
+       (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_ONLY_MASK))
+#define sig_kernel_coredump(sig) \
+       (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_COREDUMP_MASK))
+#define sig_kernel_ignore(sig) \
+       (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_IGNORE_MASK))
+#define sig_kernel_stop(sig) \
+       (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_STOP_MASK))
+
+#define sig_needs_tasklist(sig)        ((sig) == SIGCONT)
+
+#define sig_user_defined(t, signr) \
+       (((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) &&  \
+        ((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
+
+#define sig_fatal(t, signr) \
+       (!siginmask(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \
+        (t)->sighand->action[(signr)-1].sa.sa_handler == SIG_DFL)
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SIGNAL_H */
index 7ba23ec8211b11f22edd21369f824d81b5a2ee52..3f70149eabbb2e7d40c91ce069cce466c3162615 100644 (file)
@@ -83,7 +83,6 @@ void smp_prepare_boot_cpu(void);
  *     These macros fold the SMP functionality into a single CPU system
  */
 #define raw_smp_processor_id()                 0
-#define hard_smp_processor_id()                        0
 static inline int up_smp_call_function(void)
 {
        return 0;
index f56d2473495004a6958b95fc5a07b54f28a5aba8..34d4b075f7b86013a3399a928dfe303147bbffba 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
 
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  *
  * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
  *
diff --git a/include/linux/spi/Kbuild b/include/linux/spi/Kbuild
new file mode 100644 (file)
index 0000000..d375a08
--- /dev/null
@@ -0,0 +1 @@
+header-y += spidev.h
index 4f0f8c2e58a5f1cfd937cdb8291cd34b0e5d454e..b6bedc3ee95c8f80fb9be6a6ad413f10c7f67a82 100644 (file)
@@ -32,11 +32,12 @@ extern struct bus_type spi_bus_type;
  * @max_speed_hz: Maximum clock rate to be used with this chip
  *     (on this board); may be changed by the device's driver.
  *     The spi_transfer.speed_hz can override this for each transfer.
- * @chip-select: Chipselect, distinguishing chips handled by "master".
+ * @chip_select: Chipselect, distinguishing chips handled by @master.
  * @mode: The spi mode defines how data is clocked out and in.
  *     This may be changed by the device's driver.
- *     The "active low" default for chipselect mode can be overridden,
- *     as can the "MSB first" default for each word in a transfer.
+ *     The "active low" default for chipselect mode can be overridden
+ *     (by specifying SPI_CS_HIGH) as can the "MSB first" default for
+ *     each word in a transfer (by specifying SPI_LSB_FIRST).
  * @bits_per_word: Data transfers involve one or more words; word sizes
  *     like eight or 12 bits are common.  In-memory wordsizes are
  *     powers of two bytes (e.g. 20 bit samples use 32 bits).
@@ -48,14 +49,18 @@ extern struct bus_type spi_bus_type;
  * @controller_state: Controller's runtime state
  * @controller_data: Board-specific definitions for controller, such as
  *     FIFO initialization parameters; from board_info.controller_data
+ * @modalias: Name of the driver to use with this device, or an alias
+ *     for that name.  This appears in the sysfs "modalias" attribute
+ *     for driver coldplugging, and in uevents used for hotplugging
  *
- * Aspi_device is used to interchange data between an SPI slave
+ * A @spi_device is used to interchange data between an SPI slave
  * (usually a discrete chip) and CPU memory.
  *
- * In "dev", the platform_data is used to hold information about this
+ * In @dev, the platform_data is used to hold information about this
  * device that's meaningful to the device's protocol driver, but not
  * to its controller.  One example might be an identifier for a chip
- * variant with slightly different functionality.
+ * variant with slightly different functionality; another might be
+ * information about how this particular board wires the chip's pins.
  */
 struct spi_device {
        struct device           dev;
@@ -77,13 +82,15 @@ struct spi_device {
        void                    *controller_data;
        const char              *modalias;
 
-       // likely need more hooks for more protocol options affecting how
-       // the controller talks to each chip, like:
-       //  - memory packing (12 bit samples into low bits, others zeroed)
-       //  - priority
-       //  - drop chipselect after each word
-       //  - chipselect delays
-       //  - ...
+       /*
+        * likely need more hooks for more protocol options affecting how
+        * the controller talks to each chip, like:
+        *  - memory packing (12 bit samples into low bits, others zeroed)
+        *  - priority
+        *  - drop chipselect after each word
+        *  - chipselect delays
+        *  - ...
+        */
 };
 
 static inline struct spi_device *to_spi_device(struct device *dev)
@@ -146,6 +153,11 @@ static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
 
 extern int spi_register_driver(struct spi_driver *sdrv);
 
+/**
+ * spi_unregister_driver - reverse effect of spi_register_driver
+ * @sdrv: the driver to unregister
+ * Context: can sleep
+ */
 static inline void spi_unregister_driver(struct spi_driver *sdrv)
 {
        if (sdrv)
@@ -165,18 +177,20 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @setup: updates the device mode and clocking records used by a
  *     device's SPI controller; protocol code may call this.  This
  *     must fail if an unrecognized or unsupported mode is requested.
+ *     It's always safe to call this unless transfers are pending on
+ *     the device whose settings are being modified.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
  *
- * Each SPI master controller can communicate with one or more spi_device
+ * Each SPI master controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
  * but not chip select signals.  Each device may be configured to use a
  * different clock rate, since those shared signals are ignored unless
  * the chip is selected.
  *
  * The driver for an SPI controller manages access to those devices through
- * a queue of spi_message transactions, copyin data between CPU memory and
- * an SPI slave device).  For each such message it queues, it calls the
+ * a queue of spi_message transactions, copying data between CPU memory and
+ * an SPI slave device.  For each such message it queues, it calls the
  * message's completion function when the transaction completes.
  */
 struct spi_master {
@@ -280,27 +294,27 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * struct spi_transfer - a read/write buffer pair
  * @tx_buf: data to be written (dma-safe memory), or NULL
  * @rx_buf: data to be read (dma-safe memory), or NULL
- * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
- * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
+ * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
+ * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
  * @len: size of rx and tx buffers (in bytes)
  * @speed_hz: Select a speed other then the device default for this
- *      transfer. If 0 the default (from spi_device) is used.
+ *      transfer. If 0 the default (from @spi_device) is used.
  * @bits_per_word: select a bits_per_word other then the device default
- *      for this transfer. If 0 the default (from spi_device) is used.
+ *      for this transfer. If 0 the default (from @spi_device) is used.
  * @cs_change: affects chipselect after this transfer completes
  * @delay_usecs: microseconds to delay after this transfer before
  *     (optionally) changing the chipselect status, then starting
- *     the next transfer or completing this spi_message.
- * @transfer_list: transfers are sequenced through spi_message.transfers
+ *     the next transfer or completing this @spi_message.
+ * @transfer_list: transfers are sequenced through @spi_message.transfers
  *
  * SPI transfers always write the same number of bytes as they read.
- * Protocol drivers should always provide rx_buf and/or tx_buf.
+ * Protocol drivers should always provide @rx_buf and/or @tx_buf.
  * In some cases, they may also want to provide DMA addresses for
  * the data being transferred; that may reduce overhead, when the
  * underlying driver uses dma.
  *
  * If the transmit buffer is null, zeroes will be shifted out
- * while filling rx_buf.  If the receive buffer is null, the data
+ * while filling @rx_buf.  If the receive buffer is null, the data
  * shifted in will be discarded.  Only "len" bytes shift out (or in).
  * It's an error to try to shift out a partial word.  (For example, by
  * shifting out three bytes with word size of sixteen or twenty bits;
@@ -309,7 +323,7 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * In-memory data values are always in native CPU byte order, translated
  * from the wire byte order (big-endian except with SPI_LSB_FIRST).  So
  * for example when bits_per_word is sixteen, buffers are 2N bytes long
- * and hold N sixteen bit words in CPU byte order.
+ * (@len = 2N) and hold N sixteen bit words in CPU byte order.
  *
  * When the word size of the SPI transfer is not a power-of-two multiple
  * of eight bits, those in-memory words include extra bits.  In-memory
@@ -318,7 +332,7 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  *
  * All SPI transfers start with the relevant chipselect active.  Normally
  * it stays selected until after the last transfer in a message.  Drivers
- * can affect the chipselect signal using cs_change:
+ * can affect the chipselect signal using cs_change.
  *
  * (i) If the transfer isn't the last one in the message, this flag is
  * used to make the chipselect briefly go inactive in the middle of the
@@ -372,7 +386,7 @@ struct spi_transfer {
  * @queue: for use by whichever driver currently owns the message
  * @state: for use by whichever driver currently owns the message
  *
- * Aspi_message is used to execute an atomic sequence of data transfers,
+ * A @spi_message is used to execute an atomic sequence of data transfers,
  * each represented by a struct spi_transfer.  The sequence is "atomic"
  * in the sense that no other spi_message may use that SPI bus until that
  * sequence completes.  On some systems, many such sequences can execute as
@@ -464,8 +478,9 @@ static inline void spi_message_free(struct spi_message *m)
 }
 
 /**
- * spi_setup -- setup SPI mode and clock rate
+ * spi_setup - setup SPI mode and clock rate
  * @spi: the device whose settings are being modified
+ * Context: can sleep
  *
  * SPI protocol drivers may need to update the transfer mode if the
  * device doesn't work with the mode 0 default.  They may likewise need
@@ -474,7 +489,7 @@ static inline void spi_message_free(struct spi_message *m)
  * The changes take effect the next time the device is selected and data
  * is transferred to or from it.
  *
- * Note that this call wil fail if the protocol driver specifies an option
+ * Note that this call will fail if the protocol driver specifies an option
  * that the underlying controller or its driver does not support.  For
  * example, not all hardware supports wire transfers using nine bit words,
  * LSB-first wire encoding, or active-high chipselects.
@@ -487,9 +502,10 @@ spi_setup(struct spi_device *spi)
 
 
 /**
- * spi_async -- asynchronous SPI transfer
+ * spi_async - asynchronous SPI transfer
  * @spi: device with which data will be exchanged
  * @message: describes the data transfers, including completion callback
+ * Context: any (irqs may be blocked, etc)
  *
  * This call may be used in_irq and other contexts which can't sleep,
  * as well as from task contexts which can sleep.
@@ -535,6 +551,7 @@ extern int spi_sync(struct spi_device *spi, struct spi_message *message);
  * @spi: device to which data will be written
  * @buf: data buffer
  * @len: data buffer size
+ * Context: can sleep
  *
  * This writes the buffer and returns zero or a negative error code.
  * Callable only from contexts that can sleep.
@@ -558,8 +575,9 @@ spi_write(struct spi_device *spi, const u8 *buf, size_t len)
  * @spi: device from which data will be read
  * @buf: data buffer
  * @len: data buffer size
+ * Context: can sleep
  *
- * This writes the buffer and returns zero or a negative error code.
+ * This reads the buffer and returns zero or a negative error code.
  * Callable only from contexts that can sleep.
  */
 static inline int
@@ -585,6 +603,7 @@ extern int spi_write_then_read(struct spi_device *spi,
  * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
  * @spi: device with which data will be exchanged
  * @cmd: command to be written before data is read back
+ * Context: can sleep
  *
  * This returns the (unsigned) eight bit number returned by the
  * device, or else a negative error code.  Callable only from
@@ -605,6 +624,7 @@ static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
  * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
  * @spi: device with which data will be exchanged
  * @cmd: command to be written before data is read back
+ * Context: can sleep
  *
  * This returns the (unsigned) sixteen bit number returned by the
  * device, or else a negative error code.  Callable only from
diff --git a/include/linux/spi/spidev.h b/include/linux/spi/spidev.h
new file mode 100644 (file)
index 0000000..7d700be
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * include/linux/spi/spidev.h
+ *
+ * Copyright (C) 2006 SWAPP
+ *     Andrea Paterniani <a.paterniani@swapp-eng.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+
+#ifndef SPIDEV_H
+#define SPIDEV_H
+
+
+/* User space versions of kernel symbols for SPI clocking modes,
+ * matching <linux/spi/spi.h>
+ */
+
+#define SPI_CPHA               0x01
+#define SPI_CPOL               0x02
+
+#define SPI_MODE_0             (0|0)
+#define SPI_MODE_1             (0|SPI_CPHA)
+#define SPI_MODE_2             (SPI_CPOL|0)
+#define SPI_MODE_3             (SPI_CPOL|SPI_CPHA)
+
+
+/*---------------------------------------------------------------------------*/
+
+/* IOCTL commands */
+
+#define SPI_IOC_MAGIC                  'k'
+
+/**
+ * struct spi_ioc_transfer - describes a single SPI transfer
+ * @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
+ *     If no data is provided, zeroes are shifted out.
+ * @rx_buf: Holds pointer to userspace buffer for receive data, or null.
+ * @len: Length of tx and rx buffers, in bytes.
+ * @speed_hz: Temporary override of the device's bitrate.
+ * @bits_per_word: Temporary override of the device's wordsize.
+ * @delay_usecs: If nonzero, how long to delay after the last bit transfer
+ *     before optionally deselecting the device before the next transfer.
+ * @cs_change: True to deselect device before starting the next transfer.
+ *
+ * This structure is mapped directly to the kernel spi_transfer structure;
+ * the fields have the same meanings, except of course that the pointers
+ * are in a different address space (and may be of different sizes in some
+ * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel).
+ * Zero-initialize the structure, including currently unused fields, to
+ * accomodate potential future updates.
+ *
+ * SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync().
+ * Pass it an array of related transfers, they'll execute together.
+ * Each transfer may be half duplex (either direction) or full duplex.
+ *
+ *     struct spi_ioc_transfer mesg[4];
+ *     ...
+ *     status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg);
+ *
+ * So for example one transfer might send a nine bit command (right aligned
+ * in a 16-bit word), the next could read a block of 8-bit data before
+ * terminating that command by temporarily deselecting the chip; the next
+ * could send a different nine bit command (re-selecting the chip), and the
+ * last transfer might write some register values.
+ */
+struct spi_ioc_transfer {
+       __u64           tx_buf;
+       __u64           rx_buf;
+
+       __u32           len;
+       __u32           speed_hz;
+
+       __u16           delay_usecs;
+       __u8            bits_per_word;
+       __u8            cs_change;
+       __u32           pad;
+
+       /* If the contents of 'struct spi_ioc_transfer' ever change
+        * incompatibly, then the ioctl number (currently 0) must change;
+        * ioctls with constant size fields get a bit more in the way of
+        * error checking than ones (like this) where that field varies.
+        *
+        * NOTE: struct layout is the same in 64bit and 32bit userspace.
+        */
+};
+
+/* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
+#define SPI_MSGSIZE(N) \
+       ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
+               ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
+#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
+
+
+/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
+#define SPI_IOC_RD_MODE                        _IOR(SPI_IOC_MAGIC, 1, __u8)
+#define SPI_IOC_WR_MODE                        _IOW(SPI_IOC_MAGIC, 1, __u8)
+
+/* Read / Write SPI bit justification */
+#define SPI_IOC_RD_LSB_FIRST           _IOR(SPI_IOC_MAGIC, 2, __u8)
+#define SPI_IOC_WR_LSB_FIRST           _IOW(SPI_IOC_MAGIC, 2, __u8)
+
+/* Read / Write SPI device word length (1..N) */
+#define SPI_IOC_RD_BITS_PER_WORD       _IOR(SPI_IOC_MAGIC, 3, __u8)
+#define SPI_IOC_WR_BITS_PER_WORD       _IOW(SPI_IOC_MAGIC, 3, __u8)
+
+/* Read / Write SPI device default max speed hz */
+#define SPI_IOC_RD_MAX_SPEED_HZ                _IOR(SPI_IOC_MAGIC, 4, __u32)
+#define SPI_IOC_WR_MAX_SPEED_HZ                _IOW(SPI_IOC_MAGIC, 4, __u32)
+
+
+
+#endif /* SPIDEV_H */
index dc5fb69e4de9333ec84fef3f28c9a5bbbbab649d..210549ba4ef4b8a0fad84e8760ef6c84ec23ec9e 100644 (file)
@@ -85,6 +85,12 @@ typedef struct {
                                RW_DEP_MAP_INIT(lockname) }
 #endif
 
+/*
+ * SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
+ * are hence deprecated.
+ * Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
+ * __SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate.
+ */
 #define SPIN_LOCK_UNLOCKED     __SPIN_LOCK_UNLOCKED(old_style_spin_init)
 #define RW_LOCK_UNLOCKED       __RW_LOCK_UNLOCKED(old_style_rw_init)
 
index 50e2b01e517cc3c9bdf3af4b328c4afb8d3aab21..1d2b084c01859a3b4ebb4f1657129e8451110b5e 100644 (file)
@@ -6,15 +6,13 @@ struct stack_trace {
        unsigned int nr_entries, max_entries;
        unsigned long *entries;
        int skip;       /* input argument: How many entries to skip */
-       int all_contexts; /* input argument: if true do than one stack */
 };
 
-extern void save_stack_trace(struct stack_trace *trace,
-                            struct task_struct *task);
+extern void save_stack_trace(struct stack_trace *trace);
 
 extern void print_stack_trace(struct stack_trace *trace, int spaces);
 #else
-# define save_stack_trace(trace, task)                 do { } while (0)
+# define save_stack_trace(trace)                       do { } while (0)
 # define print_stack_trace(trace)                      do { } while (0)
 #endif
 
index 679ef0d70b6b1bae44fb4d9a60af100b1ec2d8fb..611c398dab72bd52e47c3945e81935b25956d818 100644 (file)
@@ -53,6 +53,9 @@
 #define S_IWUGO                (S_IWUSR|S_IWGRP|S_IWOTH)
 #define S_IXUGO                (S_IXUSR|S_IXGRP|S_IXOTH)
 
+#define UTIME_NOW      ((1l << 30) - 1l)
+#define UTIME_OMIT     ((1l << 30) - 2l)
+
 #include <linux/types.h>
 #include <linux/time.h>
 
index 35fa4d5aadd06e4685339abe13ff9986535645cf..4a7ae8ab6eb873e75aa2f14c59fc40332dd7da48 100644 (file)
@@ -396,4 +396,23 @@ char *                svc_print_addr(struct svc_rqst *, char *, size_t);
 
 #define        RPC_MAX_ADDRBUFLEN      (63U)
 
+/*
+ * When we want to reduce the size of the reserved space in the response
+ * buffer, we need to take into account the size of any checksum data that
+ * may be at the end of the packet. This is difficult to determine exactly
+ * for all cases without actually generating the checksum, so we just use a
+ * static value.
+ */
+static inline void
+svc_reserve_auth(struct svc_rqst *rqstp, int space)
+{
+       int                     added_space = 0;
+
+       switch(rqstp->rq_authop->flavour) {
+               case RPC_AUTH_GSS:
+                       added_space = RPC_MAX_AUTH_SIZE;
+       }
+       return svc_reserve(rqstp, space + added_space);
+}
+
 #endif /* SUNRPC_SVC_H */
index 7909687557bf70f29b4bf18f9021061933d72cad..e21dd93ac4b7c3a197f8b1d843d2afbddadc8ff0 100644 (file)
@@ -37,7 +37,8 @@ struct svc_sock {
 
        atomic_t                sk_reserved;    /* space on outq that is reserved */
 
-       spinlock_t              sk_defer_lock;  /* protects sk_deferred */
+       spinlock_t              sk_lock;        /* protects sk_deferred and
+                                                * sk_info_authunix */
        struct list_head        sk_deferred;    /* deferred requests that need to
                                                 * be revisted */
        struct mutex            sk_mutex;       /* to serialize sending data */
index 96868be9c211ce435f258ba363911e5ed777b796..9c7cb643066660e36ccef3c44eecde72d1e453a0 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32)
+#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
 #include <asm/suspend.h>
 #endif
 #include <linux/swap.h>
@@ -32,18 +32,51 @@ static inline int pm_prepare_console(void) { return 0; }
 static inline void pm_restore_console(void) {}
 #endif
 
+/**
+ * struct hibernation_ops - hibernation platform support
+ *
+ * The methods in this structure allow a platform to override the default
+ * mechanism of shutting down the machine during a hibernation transition.
+ *
+ * All three methods must be assigned.
+ *
+ * @prepare: prepare system for hibernation
+ * @enter: shut down system after state has been saved to disk
+ * @finish: finish/clean up after state has been reloaded
+ */
+struct hibernation_ops {
+       int (*prepare)(void);
+       int (*enter)(void);
+       void (*finish)(void);
+};
+
 #if defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND)
 /* kernel/power/snapshot.c */
-extern void __init register_nosave_region(unsigned long, unsigned long);
+extern void __register_nosave_region(unsigned long b, unsigned long e, int km);
+static inline void register_nosave_region(unsigned long b, unsigned long e)
+{
+       __register_nosave_region(b, e, 0);
+}
+static inline void register_nosave_region_late(unsigned long b, unsigned long e)
+{
+       __register_nosave_region(b, e, 1);
+}
 extern int swsusp_page_is_forbidden(struct page *);
 extern void swsusp_set_page_free(struct page *);
 extern void swsusp_unset_page_free(struct page *);
 extern unsigned long get_safe_page(gfp_t gfp_mask);
+
+extern void hibernation_set_ops(struct hibernation_ops *ops);
+extern int hibernate(void);
 #else
 static inline void register_nosave_region(unsigned long b, unsigned long e) {}
+static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
 static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
 static inline void swsusp_set_page_free(struct page *p) {}
 static inline void swsusp_unset_page_free(struct page *p) {}
+
+static inline void hibernation_set_ops(struct hibernation_ops *ops) {}
+static inline int hibernate(void) { return -ENOSYS; }
 #endif /* defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND) */
 
 void save_processor_state(void);
index eadb981bb37c94b9e9da908234f85e27f2a27fd6..13ad0b82ac286a37355a321928cbcd7dd5f31944 100644 (file)
@@ -112,6 +112,9 @@ void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area);
 void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect);
 void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit);
 void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor);
+int svga_get_tilemax(struct fb_info *info);
+void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
+                  struct fb_var_screeninfo *var);
 
 int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node);
 int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node);
index 1912c6cbef553cd1d05795c223df8f8e4425af16..3139f44122979f605816b891653e43a62bcc916c 100644 (file)
@@ -576,6 +576,8 @@ asmlinkage long sys_fstatat64(int dfd, char __user *filename,
                               struct stat64 __user *statbuf, int flag);
 asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
                               int bufsiz);
+asmlinkage long sys_utimensat(int dfd, char __user *filename,
+                               struct timespec __user *utimes, int flags);
 asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,
                                     struct compat_timeval __user *t);
 asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
index 389ccf858d378013f7cc86f94e51db5df46f9991..e699ab279c2c1302d03bdb25e10bd36567fbc507 100644 (file)
@@ -22,6 +22,7 @@
 #define _SYSDEV_H_
 
 #include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/pm.h>
 
 
index 2a196982601f8b6647d2137a1e97df2a94c2bd91..6b3a31805c72ff2e5d450697e15afc5e507d2599 100644 (file)
@@ -63,6 +63,7 @@ enum {
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
+#define TIFM_CTRL_POWER_MASK      0x00000007
 
 #define TIFM_SOCK_STATE_OCCUPIED  0x00000008
 #define TIFM_SOCK_STATE_POWERED   0x00000080
index 8ea8dea713c7c5d7a7da0fcd2e72d3d70f9112af..dda9be685ab62871c116054394cecb29aec0502f 100644 (file)
@@ -109,7 +109,7 @@ extern void do_gettimeofday(struct timeval *tv);
 extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
 #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
-extern long do_utimes(int dfd, char __user *filename, struct timeval *times);
+extern long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags);
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value,
                        struct itimerval *ovalue);
@@ -119,6 +119,7 @@ extern void getnstimeofday(struct timespec *tv);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_is_continuous(void);
+extern void update_wall_time(void);
 
 /**
  * timespec_to_ns - Convert timespec to nanoseconds
index 719113b652dd55e31bd1f0afd039a55b1d972de0..e0c5c16c992f2aeac2a2db8436354aec639c1f9a 100644 (file)
@@ -37,6 +37,7 @@ extern struct tvec_t_base_s boot_tvec_bases;
                TIMER_INITIALIZER(_function, _expires, _data)
 
 void fastcall init_timer(struct timer_list * timer);
+void fastcall init_timer_deferrable(struct timer_list *timer);
 
 static inline void setup_timer(struct timer_list * timer,
                                void (*function)(unsigned long),
index dee72b9a20fb320e6809002f3d186e4d0103e611..bb4576085203cb12fbc6e367efff3f8d82933f05 100644 (file)
@@ -313,6 +313,7 @@ extern int tty_hung_up_p(struct file * filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
+extern void no_tty(void);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
@@ -333,7 +334,6 @@ extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 extern dev_t tty_devnum(struct tty_struct *tty);
 extern void proc_clear_tty(struct task_struct *p);
-extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 extern struct tty_struct *get_current_tty(void);
 
 extern struct mutex tty_mutex;
index 1fd61eeed664c6958e4595aa455f4c3228807712..a6c1e8eed2265e914f90b6611902974eed726fa0 100644 (file)
@@ -32,6 +32,8 @@
  *             - first public version
  */
 
+#include <linux/input.h>
+
 #define UINPUT_VERSION         3
 
 #ifdef __KERNEL__
index cfbd2bb8fa2c495d33bc4de0fcbd8338115f83f6..94bd38a6d947be480281f3a8e4de4edff7f03c84 100644 (file)
@@ -126,7 +126,7 @@ enum usb_interface_condition {
  * Each interface may have alternate settings.  The initial configuration
  * of a device sets altsetting 0, but the device driver can change
  * that setting using usb_set_interface().  Alternate settings are often
- * used to control the the use of periodic endpoints, such as by having
+ * used to control the use of periodic endpoints, such as by having
  * different endpoints use different amounts of reserved USB bandwidth.
  * All standards-conformant USB devices that use isochronous endpoints
  * will use them in non-default settings.
index e10267d402c5b982d46869d1c4f49345081b7f5c..f8d3b326e93a2f9b8a2f5bc616877a433acfa73a 100644 (file)
@@ -49,9 +49,7 @@ static inline void get_uts_ns(struct uts_namespace *ns)
 }
 
 #ifdef CONFIG_UTS_NS
-extern int unshare_utsname(unsigned long unshare_flags,
-                               struct uts_namespace **new_uts);
-extern int copy_utsname(int flags, struct task_struct *tsk);
+extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
 extern void free_uts_ns(struct kref *kref);
 
 static inline void put_uts_ns(struct uts_namespace *ns)
@@ -59,21 +57,12 @@ static inline void put_uts_ns(struct uts_namespace *ns)
        kref_put(&ns->kref, free_uts_ns);
 }
 #else
-static inline int unshare_utsname(unsigned long unshare_flags,
-                       struct uts_namespace **new_uts)
+static inline struct uts_namespace *copy_utsname(int flags,
+                                               struct uts_namespace *ns)
 {
-       if (unshare_flags & CLONE_NEWUTS)
-               return -EINVAL;
-
-       return 0;
+       return ns;
 }
 
-static inline int copy_utsname(int flags, struct task_struct *tsk)
-{
-       if (flags & CLONE_NEWUTS)
-               return -EINVAL;
-       return 0;
-}
 static inline void put_uts_ns(struct uts_namespace *ns)
 {
 }
index 924e502905d40a27cdd6e7afe5d37e9d88b526b4..4b7ee83787c1fb18e24720743262910d0b464b58 100644 (file)
@@ -53,6 +53,7 @@ extern void vunmap(void *addr);
 
 extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
                                                        unsigned long pgoff);
+void vmalloc_sync_all(void);
  
 /*
  *     Lowlevel-APIs (not for driver use!)
index acb1f105870c9f4f2535259d46bfa9371ab1a612..d9325cf8a1342476c3989e791167d86f54a418e7 100644 (file)
@@ -212,8 +212,6 @@ extern void dec_zone_state(struct zone *, enum zone_stat_item);
 extern void __dec_zone_state(struct zone *, enum zone_stat_item);
 
 void refresh_cpu_vm_stats(int);
-void refresh_vm_stats(void);
-
 #else /* CONFIG_SMP */
 
 /*
@@ -260,7 +258,6 @@ static inline void __dec_zone_page_state(struct page *page,
 #define mod_zone_page_state __mod_zone_page_state
 
 static inline void refresh_cpu_vm_stats(int cpu) { }
-static inline void refresh_vm_stats(void) { }
 #endif
 
 #endif /* _LINUX_VMSTAT_H */
index e0db669998f3e98ff72dbc02ca230aad82c8a75c..d961635d0e618038cae7ebbcc3abcacddce4f59d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/vt.h>
 #include <linux/kd.h>
 #include <linux/tty.h>
+#include <linux/mutex.h>
 #include <linux/console_struct.h>
 #include <linux/mm.h>
 
@@ -82,7 +83,7 @@ void reset_vc(struct vc_data *vc);
 
 #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
 extern char con_buf[CON_BUF_SIZE];
-extern struct semaphore con_buf_sem;
+extern struct mutex con_buf_mtx;
 extern char vt_dont_switch;
 
 struct vt_spawn_console {
index b8abfc74d038384092d1089337a51bf0aa6023ec..d555f31c0746a31a50f376ca41ed2cbcf48742fe 100644 (file)
@@ -24,15 +24,13 @@ typedef void (*work_func_t)(struct work_struct *work);
 struct work_struct {
        atomic_long_t data;
 #define WORK_STRUCT_PENDING 0          /* T if work item pending execution */
-#define WORK_STRUCT_NOAUTOREL 1                /* F if work item automatically released on exec */
 #define WORK_STRUCT_FLAG_MASK (3UL)
 #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
        struct list_head entry;
        work_func_t func;
 };
 
-#define WORK_DATA_INIT(autorelease) \
-       ATOMIC_LONG_INIT((autorelease) << WORK_STRUCT_NOAUTOREL)
+#define WORK_DATA_INIT()       ATOMIC_LONG_INIT(0)
 
 struct delayed_work {
        struct work_struct work;
@@ -44,14 +42,8 @@ struct execute_work {
 };
 
 #define __WORK_INITIALIZER(n, f) {                             \
-       .data = WORK_DATA_INIT(0),                              \
-        .entry = { &(n).entry, &(n).entry },                   \
-       .func = (f),                                            \
-       }
-
-#define __WORK_INITIALIZER_NAR(n, f) {                         \
-       .data = WORK_DATA_INIT(1),                              \
-        .entry = { &(n).entry, &(n).entry },                   \
+       .data = WORK_DATA_INIT(),                               \
+       .entry  = { &(n).entry, &(n).entry },                   \
        .func = (f),                                            \
        }
 
@@ -60,23 +52,12 @@ struct execute_work {
        .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
        }
 
-#define __DELAYED_WORK_INITIALIZER_NAR(n, f) {                 \
-       .work = __WORK_INITIALIZER_NAR((n).work, (f)),          \
-       .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
-       }
-
 #define DECLARE_WORK(n, f)                                     \
        struct work_struct n = __WORK_INITIALIZER(n, f)
 
-#define DECLARE_WORK_NAR(n, f)                                 \
-       struct work_struct n = __WORK_INITIALIZER_NAR(n, f)
-
 #define DECLARE_DELAYED_WORK(n, f)                             \
        struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)
 
-#define DECLARE_DELAYED_WORK_NAR(n, f)                 \
-       struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f)
-
 /*
  * initialize a work item's function pointer
  */
@@ -95,16 +76,9 @@ struct execute_work {
  * assignment of the work data initializer allows the compiler
  * to generate better code.
  */
-#define INIT_WORK(_work, _func)                                        \
-       do {                                                    \
-               (_work)->data = (atomic_long_t) WORK_DATA_INIT(0);      \
-               INIT_LIST_HEAD(&(_work)->entry);                \
-               PREPARE_WORK((_work), (_func));                 \
-       } while (0)
-
-#define INIT_WORK_NAR(_work, _func)                                    \
+#define INIT_WORK(_work, _func)                                                \
        do {                                                            \
-               (_work)->data = (atomic_long_t) WORK_DATA_INIT(1);      \
+               (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                INIT_LIST_HEAD(&(_work)->entry);                        \
                PREPARE_WORK((_work), (_func));                         \
        } while (0)
@@ -115,10 +89,10 @@ struct execute_work {
                init_timer(&(_work)->timer);                    \
        } while (0)
 
-#define INIT_DELAYED_WORK_NAR(_work, _func)                    \
+#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func)                     \
        do {                                                    \
-               INIT_WORK_NAR(&(_work)->work, (_func));         \
-               init_timer(&(_work)->timer);                    \
+               INIT_WORK(&(_work)->work, (_func));             \
+               init_timer_deferrable(&(_work)->timer);         \
        } while (0)
 
 /**
@@ -137,24 +111,10 @@ struct execute_work {
        work_pending(&(w)->work)
 
 /**
- * work_release - Release a work item under execution
- * @work: The work item to release
- *
- * This is used to release a work item that has been initialised with automatic
- * release mode disabled (WORK_STRUCT_NOAUTOREL is set).  This gives the work
- * function the opportunity to grab auxiliary data from the container of the
- * work_struct before clearing the pending bit as the work_struct may be
- * subject to deallocation the moment the pending bit is cleared.
- *
- * In such a case, this should be called in the work function after it has
- * fetched any data it may require from the containter of the work_struct.
- * After this function has been called, the work_struct may be scheduled for
- * further execution or it may be deallocated unless other precautions are
- * taken.
- *
- * This should also be used to release a delayed work item.
+ * work_clear_pending - for internal use only, mark a work item as not pending
+ * @work: The work item in question
  */
-#define work_release(work) \
+#define work_clear_pending(work) \
        clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
 
 
@@ -168,27 +128,28 @@ extern struct workqueue_struct *__create_workqueue(const char *name,
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
 extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work));
-extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay));
+extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq,
+                       struct delayed_work *work, unsigned long delay));
 extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
-       struct delayed_work *work, unsigned long delay);
+                       struct delayed_work *work, unsigned long delay);
+
 extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
+extern void flush_scheduled_work(void);
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
-extern int FASTCALL(run_scheduled_work(struct work_struct *work));
-extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay));
-
-extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay);
+extern int FASTCALL(schedule_delayed_work(struct delayed_work *work,
+                                       unsigned long delay));
+extern int schedule_delayed_work_on(int cpu, struct delayed_work *work,
+                                       unsigned long delay);
 extern int schedule_on_each_cpu(work_func_t func);
-extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
 
 extern void init_workqueues(void);
-void cancel_rearming_delayed_work(struct delayed_work *work);
-void cancel_rearming_delayed_workqueue(struct workqueue_struct *,
-                                      struct delayed_work *);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
+extern void cancel_work_sync(struct work_struct *work);
+
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
  * function may still be running on return from cancel_delayed_work(), unless
@@ -201,8 +162,18 @@ static inline int cancel_delayed_work(struct delayed_work *work)
 
        ret = del_timer(&work->timer);
        if (ret)
-               work_release(&work->work);
+               work_clear_pending(&work->work);
        return ret;
 }
 
+extern void cancel_rearming_delayed_work(struct delayed_work *work);
+
+/* Obsolete. use cancel_rearming_delayed_work() */
+static inline
+void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
+                                       struct delayed_work *work)
+{
+       cancel_rearming_delayed_work(work);
+}
+
 #endif
diff --git a/include/math-emu/extended.h b/include/math-emu/extended.h
deleted file mode 100644 (file)
index 84770fc..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/* Software floating-point emulation.
-   Definitions for IEEE Extended Precision.
-   Copyright (C) 1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Jakub Jelinek (jj@ultra.linux.cz).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-
-#ifndef    __MATH_EMU_EXTENDED_H__
-#define    __MATH_EMU_EXTENDED_H__
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_E         (4*_FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_E                (2*_FP_W_TYPE_SIZE)
-#endif
-
-#define _FP_FRACBITS_E         64
-#define _FP_FRACXBITS_E                (_FP_FRACTBITS_E - _FP_FRACBITS_E)
-#define _FP_WFRACBITS_E                (_FP_WORKBITS + _FP_FRACBITS_E)
-#define _FP_WFRACXBITS_E       (_FP_FRACTBITS_E - _FP_WFRACBITS_E)
-#define _FP_EXPBITS_E          15
-#define _FP_EXPBIAS_E          16383
-#define _FP_EXPMAX_E           32767
-
-#define _FP_QNANBIT_E          \
-       ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_E          \
-       ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_E         \
-       ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_E
-{
-   long double flt;
-   struct 
-   {
-#if __BYTE_ORDER == __BIG_ENDIAN
-      unsigned long pad1 : _FP_W_TYPE_SIZE;
-      unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
-      unsigned long sign : 1;
-      unsigned long exp : _FP_EXPBITS_E;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned exp : _FP_EXPBITS_E;
-      unsigned sign : 1;
-#endif /* not bigendian */
-   } bits __attribute__((packed));
-};
-
-
-#define FP_DECL_E(X)           _FP_DECL(4,X)
-
-#define FP_UNPACK_RAW_E(X, val)                                \
-  do {                                                 \
-    union _FP_UNION_E _flo; _flo.flt = (val);          \
-                                                       \
-    X##_f[2] = 0; X##_f[3] = 0;                                \
-    X##_f[0] = _flo.bits.frac0;                                \
-    X##_f[1] = _flo.bits.frac1;                                \
-    X##_e  = _flo.bits.exp;                            \
-    X##_s  = _flo.bits.sign;                           \
-    if (!X##_e && (X##_f[1] || X##_f[0])               \
-        && !(X##_f[1] & _FP_IMPLBIT_E))                        \
-      {                                                        \
-        X##_e++;                                       \
-        FP_SET_EXCEPTION(FP_EX_DENORM);                        \
-      }                                                        \
-  } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val)                       \
-  do {                                                 \
-    union _FP_UNION_E *_flo =                          \
-    (union _FP_UNION_E *)(val);                                \
-                                                       \
-    X##_f[2] = 0; X##_f[3] = 0;                                \
-    X##_f[0] = _flo->bits.frac0;                       \
-    X##_f[1] = _flo->bits.frac1;                       \
-    X##_e  = _flo->bits.exp;                           \
-    X##_s  = _flo->bits.sign;                          \
-    if (!X##_e && (X##_f[1] || X##_f[0])               \
-        && !(X##_f[1] & _FP_IMPLBIT_E))                        \
-      {                                                        \
-        X##_e++;                                       \
-        FP_SET_EXCEPTION(FP_EX_DENORM);                        \
-      }                                                        \
-  } while (0)
-
-#define FP_PACK_RAW_E(val, X)                          \
-  do {                                                 \
-    union _FP_UNION_E _flo;                            \
-                                                       \
-    if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;              \
-    else X##_f[1] &= ~(_FP_IMPLBIT_E);                 \
-    _flo.bits.frac0 = X##_f[0];                                \
-    _flo.bits.frac1 = X##_f[1];                                \
-    _flo.bits.exp   = X##_e;                           \
-    _flo.bits.sign  = X##_s;                           \
-                                                       \
-    (val) = _flo.flt;                                  \
-  } while (0)
-
-#define FP_PACK_RAW_EP(val, X)                         \
-  do {                                                 \
-    if (!FP_INHIBIT_RESULTS)                           \
-      {                                                        \
-       union _FP_UNION_E *_flo =                       \
-         (union _FP_UNION_E *)(val);                   \
-                                                       \
-       if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;           \
-       else X##_f[1] &= ~(_FP_IMPLBIT_E);              \
-       _flo->bits.frac0 = X##_f[0];                    \
-       _flo->bits.frac1 = X##_f[1];                    \
-       _flo->bits.exp   = X##_e;                       \
-       _flo->bits.sign  = X##_s;                       \
-      }                                                        \
-  } while (0)
-
-#define FP_UNPACK_E(X,val)             \
-  do {                                 \
-    FP_UNPACK_RAW_E(X,val);            \
-    _FP_UNPACK_CANONICAL(E,4,X);       \
-  } while (0)
-
-#define FP_UNPACK_EP(X,val)            \
-  do {                                 \
-    FP_UNPACK_RAW_2_P(X,val);          \
-    _FP_UNPACK_CANONICAL(E,4,X);       \
-  } while (0)
-
-#define FP_PACK_E(val,X)               \
-  do {                                 \
-    _FP_PACK_CANONICAL(E,4,X);         \
-    FP_PACK_RAW_E(val,X);              \
-  } while (0)
-
-#define FP_PACK_EP(val,X)              \
-  do {                                 \
-    _FP_PACK_CANONICAL(E,4,X);         \
-    FP_PACK_RAW_EP(val,X);             \
-  } while (0)
-
-#define FP_ISSIGNAN_E(X)       _FP_ISSIGNAN(E,4,X)
-#define FP_NEG_E(R,X)          _FP_NEG(E,4,R,X)
-#define FP_ADD_E(R,X,Y)                _FP_ADD(E,4,R,X,Y)
-#define FP_SUB_E(R,X,Y)                _FP_SUB(E,4,R,X,Y)
-#define FP_MUL_E(R,X,Y)                _FP_MUL(E,4,R,X,Y)
-#define FP_DIV_E(R,X,Y)                _FP_DIV(E,4,R,X,Y)
-#define FP_SQRT_E(R,X)         _FP_SQRT(E,4,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * This has special _E version because standard _4 square
- * root would not work (it has to start normally with the
- * second word and not the first), but as we have to do it
- * anyway, we optimize it by doing most of the calculations
- * in two UWtype registers instead of four.
- */
-#define _FP_SQRT_MEAT_E(R, S, T, X, q)                 \
-  do {                                                 \
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);                \
-    _FP_FRAC_SRL_4(X, (_FP_WORKBITS));                 \
-    while (q)                                          \
-      {                                                        \
-       T##_f[1] = S##_f[1] + q;                        \
-       if (T##_f[1] <= X##_f[1])                       \
-         {                                             \
-           S##_f[1] = T##_f[1] + q;                    \
-           X##_f[1] -= T##_f[1];                       \
-           R##_f[1] += q;                              \
-         }                                             \
-       _FP_FRAC_SLL_2(X, 1);                           \
-       q >>= 1;                                        \
-      }                                                        \
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);                \
-    while (q)                                          \
-      {                                                        \
-       T##_f[0] = S##_f[0] + q;                        \
-       T##_f[1] = S##_f[1];                            \
-       if (T##_f[1] < X##_f[1] ||                      \
-           (T##_f[1] == X##_f[1] &&                    \
-            T##_f[0] <= X##_f[0]))                     \
-         {                                             \
-           S##_f[0] = T##_f[0] + q;                    \
-           S##_f[1] += (T##_f[0] > S##_f[0]);          \
-           _FP_FRAC_DEC_2(X, T);                       \
-           R##_f[0] += q;                              \
-         }                                             \
-       _FP_FRAC_SLL_2(X, 1);                           \
-       q >>= 1;                                        \
-      }                                                        \
-    _FP_FRAC_SLL_4(R, (_FP_WORKBITS));                 \
-    if (X##_f[0] | X##_f[1])                           \
-      {                                                        \
-       if (S##_f[1] < X##_f[1] ||                      \
-           (S##_f[1] == X##_f[1] &&                    \
-            S##_f[0] < X##_f[0]))                      \
-         R##_f[0] |= _FP_WORK_ROUND;                   \
-       R##_f[0] |= _FP_WORK_STICKY;                    \
-      }                                                        \
-  } while (0)
-
-#define FP_CMP_E(r,X,Y,un)     _FP_CMP(E,4,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y)     _FP_CMP_EQ(E,4,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg)       _FP_TO_INT(E,4,r,X,rsz,rsg)
-#define FP_TO_INT_ROUND_E(r,X,rsz,rsg) _FP_TO_INT_ROUND(E,4,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt)       _FP_FROM_INT(E,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X)     (X##_f[2])
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
-
-#else   /* not _FP_W_TYPE_SIZE < 64 */
-union _FP_UNION_E
-{
-  long double flt /* __attribute__((mode(TF))) */ ;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
-    unsigned sign  : 1;
-    unsigned exp   : _FP_EXPBITS_E;
-    unsigned long frac : _FP_W_TYPE_SIZE;
-#else
-    unsigned long frac : _FP_W_TYPE_SIZE;
-    unsigned exp   : _FP_EXPBITS_E;
-    unsigned sign  : 1;
-#endif
-  } bits;
-};
-
-#define FP_DECL_E(X)           _FP_DECL(2,X)
-
-#define FP_UNPACK_RAW_E(X, val)                                        \
-  do {                                                         \
-    union _FP_UNION_E _flo; _flo.flt = (val);                  \
-                                                               \
-    X##_f0 = _flo.bits.frac;                                   \
-    X##_f1 = 0;                                                        \
-    X##_e = _flo.bits.exp;                                     \
-    X##_s = _flo.bits.sign;                                    \
-    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))         \
-      {                                                                \
-        X##_e++;                                               \
-        FP_SET_EXCEPTION(FP_EX_DENORM);                                \
-      }                                                                \
-  } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val)                               \
-  do {                                                         \
-    union _FP_UNION_E *_flo =                                  \
-      (union _FP_UNION_E *)(val);                              \
-                                                               \
-    X##_f0 = _flo->bits.frac;                                  \
-    X##_f1 = 0;                                                        \
-    X##_e = _flo->bits.exp;                                    \
-    X##_s = _flo->bits.sign;                                   \
-    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))         \
-      {                                                                \
-        X##_e++;                                               \
-        FP_SET_EXCEPTION(FP_EX_DENORM);                                \
-      }                                                                \
-  } while (0)
-
-#define FP_PACK_RAW_E(val, X)                                  \
-  do {                                                         \
-    union _FP_UNION_E _flo;                                    \
-                                                               \
-    if (X##_e) X##_f0 |= _FP_IMPLBIT_E;                                \
-    else X##_f0 &= ~(_FP_IMPLBIT_E);                           \
-    _flo.bits.frac = X##_f0;                                   \
-    _flo.bits.exp  = X##_e;                                    \
-    _flo.bits.sign = X##_s;                                    \
-                                                               \
-    (val) = _flo.flt;                                          \
-  } while (0)
-
-#define FP_PACK_RAW_EP(fs, val, X)                             \
-  do {                                                         \
-    if (!FP_INHIBIT_RESULTS)                                   \
-      {                                                                \
-       union _FP_UNION_E *_flo =                               \
-         (union _FP_UNION_E *)(val);                           \
-                                                               \
-       if (X##_e) X##_f0 |= _FP_IMPLBIT_E;                     \
-       else X##_f0 &= ~(_FP_IMPLBIT_E);                        \
-       _flo->bits.frac = X##_f0;                               \
-       _flo->bits.exp  = X##_e;                                \
-       _flo->bits.sign = X##_s;                                \
-      }                                                                \
-  } while (0)
-
-
-#define FP_UNPACK_E(X,val)             \
-  do {                                 \
-    FP_UNPACK_RAW_E(X,val);            \
-    _FP_UNPACK_CANONICAL(E,2,X);       \
-  } while (0)
-
-#define FP_UNPACK_EP(X,val)            \
-  do {                                 \
-    FP_UNPACK_RAW_EP(X,val);           \
-    _FP_UNPACK_CANONICAL(E,2,X);       \
-  } while (0)
-
-#define FP_PACK_E(val,X)               \
-  do {                                 \
-    _FP_PACK_CANONICAL(E,2,X);         \
-    FP_PACK_RAW_E(val,X);              \
-  } while (0)
-
-#define FP_PACK_EP(val,X)              \
-  do {                                 \
-    _FP_PACK_CANONICAL(E,2,X);         \
-    FP_PACK_RAW_EP(val,X);             \
-  } while (0)
-
-#define FP_ISSIGNAN_E(X)       _FP_ISSIGNAN(E,2,X)
-#define FP_NEG_E(R,X)          _FP_NEG(E,2,R,X)
-#define FP_ADD_E(R,X,Y)                _FP_ADD(E,2,R,X,Y)
-#define FP_SUB_E(R,X,Y)                _FP_SUB(E,2,R,X,Y)
-#define FP_MUL_E(R,X,Y)                _FP_MUL(E,2,R,X,Y)
-#define FP_DIV_E(R,X,Y)                _FP_DIV(E,2,R,X,Y)
-#define FP_SQRT_E(R,X)         _FP_SQRT(E,2,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * We optimize it by doing most of the calculations
- * in one UWtype registers instead of two, although we don't
- * have to.
- */
-#define _FP_SQRT_MEAT_E(R, S, T, X, q)                 \
-  do {                                                 \
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);                \
-    _FP_FRAC_SRL_2(X, (_FP_WORKBITS));                 \
-    while (q)                                          \
-      {                                                        \
-        T##_f0 = S##_f0 + q;                           \
-        if (T##_f0 <= X##_f0)                          \
-          {                                            \
-            S##_f0 = T##_f0 + q;                       \
-            X##_f0 -= T##_f0;                          \
-            R##_f0 += q;                               \
-          }                                            \
-        _FP_FRAC_SLL_1(X, 1);                          \
-        q >>= 1;                                       \
-      }                                                        \
-    _FP_FRAC_SLL_2(R, (_FP_WORKBITS));                 \
-    if (X##_f0)                                                \
-      {                                                        \
-       if (S##_f0 < X##_f0)                            \
-         R##_f0 |= _FP_WORK_ROUND;                     \
-       R##_f0 |= _FP_WORK_STICKY;                      \
-      }                                                        \
-  } while (0)
-#define FP_CMP_E(r,X,Y,un)     _FP_CMP(E,2,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y)     _FP_CMP_EQ(E,2,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg)       _FP_TO_INT(E,2,r,X,rsz,rsg)
-#define FP_TO_INT_ROUND_E(r,X,rsz,rsg) _FP_TO_INT_ROUND(E,2,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt)       _FP_FROM_INT(E,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X)     (X##_f1)
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
-
-#endif /* not _FP_W_TYPE_SIZE < 64 */
-
-#endif /* __MATH_EMU_EXTENDED_H__ */
index 7a209f61c48259550a0a163e8f42b1df993598c9..0df574931522d852269946e80865cad5913778eb 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index 89fe534045f1c61f8cd6c3bad1e7905911f57d7e..36bee441aa56cec008017badcdb235487f947cd8 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index 2007c5a0a43f8d9d25f409c0d121ff4952d70eec..fcc896491a95396209e36429b3ab87778c50487d 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 4ca3d2071b0392da937b077ba0b361a12817d844..89747f06d9ebc9dc17645b2ecda220c601c273d4 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index c41196b879556fa2ccd5d73917b75cb599f27d47..83f78081799c2365b3e2039a9a82f46038afe322 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index 736dabe211e34ff8d57ca157f05ff6cfd8ad36fb..fa8455eda28068df1f41f81cf65b4509c4d61af4 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 9592c374b41d536e182930ff6f16f7a70d71a813..73cacb3ac16cae48a2e494ec10874bb8258b44db 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 9a9b3619d305a03eaa8c2f343e4f5202e493d5a4..0062347600b9d7796cc969c20651e7115009fed1 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index b9baac9eb8b676e585139d95132ee5b4cefb441e..6d9539f05806a63efc03757bcadca6b496c59ae8 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 1720539ac2c1b0270e1358e6a6541e34dc709005..a5a2539485bddf24bd7d43eea82b56fe93e39237 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index ca51d5b7c999871e8acbd222f8ee15e74c4f9d28..92f3b0e1029b4314c113732702b53508a7bbb09a 100644 (file)
@@ -16,7 +16,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index e77eb88d9226b5e991047f3e97f54e02e24a94d5..f0248fb8e196f0c5b4cd669cefe34f536d374bf9 100644 (file)
@@ -18,7 +18,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index e212b9bc2503d64439cd70c3ffa4d080d15751dd..3ffc1d0f93d6ac40178911208e07279f20f7ece3 100644 (file)
@@ -18,7 +18,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 03c6f81a502a267b5ce1c034688e8f7632ecfedb..e03ae4ae3963fa112606e8f372fa0a4083e40bbb 100644 (file)
@@ -18,7 +18,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index c463f8bca85601ec457a4bdb1991c7fcb8738efe..1906eb71422e2d401abaeb0c0310ba2db15a5699 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 72b446c1e22c805bbf0ff8d6ed27f02b478a430b..86f0dbb8ee5d1ae69b5373515b871fbcf0c5b43b 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charg.
  *     
index 335b0ace96659e14d54363311ebf47d510961574..37f512bd673321e2fb0eed0bd8ce2653cfe7b850 100644 (file)
@@ -21,7 +21,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *     
index a899e5837be84525771fae96fcaba8d66368ea49..cf80c1af5854a4d7c9351bb8922fd3892884a887 100644 (file)
@@ -18,7 +18,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 3a605d37ddbf0c820437a582fb4c16d71827a8fe..c0d938847bd3ba8fbd2e3d0b163074e25977a64b 100644 (file)
@@ -26,7 +26,7 @@
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  *     MA 02111-1307 USA
  *
- *     Michel Dänzer <daenzer@debian.org>, 10/2001
+ *     Michel Dänzer <daenzer@debian.org>, 10/2001
  *     - simplify irda_pv_t to avoid endianness issues
  *     
  ********************************************************************/
index cb61568547d1328e8d59daf26920bea600a20013..cb2615ccf761d68123406d3600646d147a6e2f47 100644 (file)
@@ -18,7 +18,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 98768b3f9e313c5132befcf931dc713b7f682558..2942ad6ab932eb5e0f0fbbd8395803175b4592aa 100644 (file)
@@ -17,7 +17,7 @@
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
index 25c37e34bfdce0cd854debc57d34ed2fdfaa1b59..689b886038da88da7b4268c377606a96293932d9 100644 (file)
@@ -1361,15 +1361,6 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
-#ifdef CONFIG_NET
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-#else
-static inline int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       return -ENODEV;
-}
-#endif
-
 extern void sk_init(void);
 
 #ifdef CONFIG_SYSCTL
index ad0182ef7809bba62450e4788dfb658fd601ce8d..2e6bdc4e7a0ae1deb116b7d9e96e8e29bbf05b99 100644 (file)
@@ -314,8 +314,7 @@ struct scsi_core {
        struct list_head  task_queue;
        int               task_queue_size;
 
-       struct semaphore  queue_thread_sema;
-       int               queue_thread_kill;
+       struct task_struct *queue_thread;
 };
 
 struct sas_ha_event {
index 09a7f4a7289f429afffd976dc06c50d4dd605042..a8332e528ec19ef6d7b50540e615ec108ce36a0f 100644 (file)
 #define SDRAM                  4
 #define SGRAM                  5
 #define WRAM                   6
+#define SDRAM32                        6
 
 #define DAC_INTERNAL           0x00
 #define DAC_IBMRGB514          0x01
index b95d36289336711d69ad7edf76a213cdf25a6431..9e49c9571ec3b6d7d9c840ba8f30f4e431c733c3 100644 (file)
 #define PM2VI_RD_CLK1_PRESCALE                         0x204
 #define PM2VI_RD_CLK1_FEEDBACK                         0x205
 #define PM2VI_RD_CLK1_POSTSCALE                                0x206
+#define PM2VI_RD_MCLK_CONTROL                          0x20D
+#define PM2VI_RD_MCLK_PRESCALE                         0x20E
+#define PM2VI_RD_MCLK_FEEDBACK                         0x20F
+#define PM2VI_RD_MCLK_POSTSCALE                                0x210
 #define PM2VI_RD_CURSOR_PALETTE                                0x303
 #define PM2VI_RD_CURSOR_PATTERN                                0x400
 
index be2b3e94e2513361fa07e5d79b29884178aed11d..03d0dbe293a8718902663f2ec190b545c4e6dae8 100644 (file)
@@ -39,6 +39,7 @@
 #define        TGA_RASTEROP_REG                0x0034
 #define        TGA_PIXELSHIFT_REG              0x0038
 #define        TGA_DEEP_REG                    0x0050
+#define        TGA_START_REG                   0x0054
 #define        TGA_PIXELMASK_REG               0x005c
 #define        TGA_CURSOR_BASE_REG             0x0060
 #define        TGA_HORIZ_REG                   0x0064
 
 
 /*
- * Useful defines for managing the BT463 on the 24-plane TGAs
+ * Useful defines for managing the BT463 on the 24-plane TGAs/SFB+s
  */
 
 #define        BT463_ADDR_LO           0x0
 
 #define        BT463_WINDOW_TYPE_BASE  0x0300
 
+/*
+ * Useful defines for managing the BT459 on the 8-plane SFB+s
+ */
+
+#define        BT459_ADDR_LO           0x0
+#define        BT459_ADDR_HI           0x1
+#define        BT459_REG_ACC           0x2
+#define        BT459_PALETTE           0x3
+
+#define        BT459_CUR_CLR_1         0x0181
+#define        BT459_CUR_CLR_2         0x0182
+#define        BT459_CUR_CLR_3         0x0183
+
+#define        BT459_CMD_REG_0         0x0201
+#define        BT459_CMD_REG_1         0x0202
+#define        BT459_CMD_REG_2         0x0203
+
+#define        BT459_READ_MASK         0x0204
+
+#define        BT459_BLINK_MASK        0x0206
+
+#define        BT459_CUR_CMD_REG       0x0300
+
 /*
  * The framebuffer driver private data.
  */
 
 struct tga_par {
-       /* PCI device.  */
-       struct pci_dev *pdev;
+       /* PCI/TC device.  */
+       struct device *dev;
 
        /* Device dependent information.  */
        void __iomem *tga_mem_base;
@@ -235,4 +259,21 @@ BT463_WRITE(struct tga_par *par, u32 m, u16 a, u8 v)
        TGA_WRITE_REG(par, m << 10 | v, TGA_RAMDAC_REG);
 }
 
+static inline void
+BT459_LOAD_ADDR(struct tga_par *par, u16 a)
+{
+       TGA_WRITE_REG(par, BT459_ADDR_LO << 2, TGA_RAMDAC_SETUP_REG);
+       TGA_WRITE_REG(par, a & 0xff, TGA_RAMDAC_REG);
+       TGA_WRITE_REG(par, BT459_ADDR_HI << 2, TGA_RAMDAC_SETUP_REG);
+       TGA_WRITE_REG(par, a >> 8, TGA_RAMDAC_REG);
+}
+
+static inline void
+BT459_WRITE(struct tga_par *par, u32 m, u16 a, u8 v)
+{
+       BT459_LOAD_ADDR(par, a);
+       TGA_WRITE_REG(par, m << 2, TGA_RAMDAC_SETUP_REG);
+       TGA_WRITE_REG(par, v, TGA_RAMDAC_REG);
+}
+
 #endif /* TGAFB_H */
index ebe04f56d8343b980814b5ee551cc7f62242e282..e63a017c391eb23b11ae5769f19cabf5cfb7dae8 100644 (file)
@@ -143,9 +143,7 @@ config POSIX_MQUEUE
          queues every message has a priority which decides about succession
          of receiving it by a process. If you want to compile and run
          programs written e.g. for Solaris with use of its POSIX message
-         queues (functions mq_*) say Y here. To use this feature you will
-         also need mqueue library, available from
-         <http://www.mat.uni.torun.pl/~wrona/posix_ipc/>
+         queues (functions mq_*) say Y here.
 
          POSIX message queues are visible as a filesystem called 'mqueue'
          and can be mounted somewhere if you want to do filesystem
@@ -266,6 +264,23 @@ config IKCONFIG_PROC
          This option enables access to the kernel configuration file
          through /proc/config.gz.
 
+config LOG_BUF_SHIFT
+       int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
+       range 12 21
+       default 17 if S390 || LOCKDEP
+       default 16 if X86_NUMAQ || IA64
+       default 15 if SMP
+       default 14
+       help
+         Select kernel log buffer size as a power of 2.
+         Defaults and Examples:
+                    17 => 128 KB for S/390
+                    16 => 64 KB for x86 NUMAQ or IA-64
+                    15 => 32 KB for SMP
+                    14 => 16 KB for uniprocessor
+                    13 =>  8 KB
+                    12 =>  4 KB
+
 config CPUSETS
        bool "Cpuset support"
        depends on SMP
@@ -291,7 +306,7 @@ config SYSFS_DEPRECATED
          releases.
 
          If enabled, this option will also move any device structures
-         that belong to a class, back into the /sys/class heirachy, in
+         that belong to a class, back into the /sys/class hierarchy, in
          order to support older versions of udev.
 
          If you are using a distro that was released in 2006 or later,
@@ -487,6 +502,15 @@ config VM_EVENT_COUNTERS
          on EMBEDDED systems.  /proc/vmstat will only show page counts
          if VM event counters are disabled.
 
+config SLUB_DEBUG
+       default y
+       bool "Enable SLUB debugging support" if EMBEDDED
+       help
+         SLUB has extensive debug support features. Disabling these can
+         result in significant savings in code size. This also disables
+         SLUB sysfs support. /sys/slab will not exist and there will be
+         no support for cache validation etc.
+
 choice
        prompt "Choose SLAB allocator"
        default SLAB
@@ -497,9 +521,9 @@ config SLAB
        bool "SLAB"
        help
          The regular slab allocator that is established and known to work
-         well in all environments. It organizes chache hot objects in
+         well in all environments. It organizes cache hot objects in
          per cpu and per node queues. SLAB is the default choice for
-         slab allocator.
+         slab allocator.
 
 config SLUB
        depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
@@ -509,21 +533,20 @@ config SLUB
           instead of managing queues of cached objects (SLAB approach).
           Per cpu caching is realized using slabs of objects instead
           of queues of objects. SLUB can use memory efficiently
-          way and has enhanced diagnostics.
+          and has enhanced diagnostics.
 
 config SLOB
 #
-#      SLOB cannot support SMP because SLAB_DESTROY_BY_RCU does not work
-#      properly.
+#      SLOB does not support SMP because SLAB_DESTROY_BY_RCU is unsupported
 #
        depends on EMBEDDED && !SMP && !SPARSEMEM
        bool "SLOB (Simple Allocator)"
        help
           SLOB replaces the SLAB allocator with a drastically simpler
           allocator.  SLOB is more space efficient that SLAB but does not
-          scale well (single lock for all operations) and is more susceptible
-          to fragmentation. SLOB it is a great choice to reduce
-          memory usage and code size for embedded systems.
+          scale well (single lock for all operations) and is also highly
+          susceptible to fragmentation. SLUB can accomplish a higher object
+          density. It is usually better to use SLUB instead of SLOB.
 
 endchoice
 
index dc1ec0803ef9b93b76c27b9db3a9d3e741f98280..46fe407fb03eb6be6236378be2daa79a61cd5aa1 100644 (file)
@@ -7,8 +7,10 @@
 #include <linux/root_dev.h>
 #include <linux/security.h>
 #include <linux/delay.h>
+#include <linux/genhd.h>
 #include <linux/mount.h>
 #include <linux/device.h>
+#include <linux/init.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -307,17 +309,21 @@ retry:
                /*
                 * Allow the user to distinguish between failed sys_open
                 * and bad superblock on root device.
+                * and give them a list of the available devices
                 */
 #ifdef CONFIG_BLOCK
                __bdevname(ROOT_DEV, b);
 #endif
                printk("VFS: Cannot open root device \"%s\" or %s\n",
                                root_device_name, b);
-               printk("Please append a correct \"root=\" boot option\n");
+               printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");
 
+               printk_all_partitions();
                panic("VFS: Unable to mount root fs on %s", b);
        }
 
+       printk("List of all partitions:\n");
+       printk_all_partitions();
        printk("No filesystem could mount root, tried: ");
        for (p = fs_names; *p; p += strlen(p)+1)
                printk(" %s", p);
index 0e22f40487bba5bceea3ddf7266b0a340e005ce1..e8d080cab443750f7360d50bd32aa0c7644a6a4e 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/lockdep.h>
 #include <linux/pid_namespace.h>
 #include <linux/device.h>
+#include <linux/kthread.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -94,7 +95,6 @@ extern void pidmap_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
-extern void prepare_namespace(void);
 #ifdef CONFIG_ACPI
 extern void acpi_early_init(void);
 #else
@@ -426,8 +426,12 @@ static void __init setup_command_line(char *command_line)
 static void noinline rest_init(void)
        __releases(kernel_lock)
 {
+       int pid;
+
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
+       pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
+       kthreadd_task = find_task_by_pid(pid);
        unlock_kernel();
 
        /*
@@ -649,6 +653,7 @@ static void __init do_initcalls(void)
        int count = preempt_count();
 
        for (call = __initcall_start; call < __initcall_end; call++) {
+               ktime_t t0, t1, delta;
                char *msg = NULL;
                char msgbuf[40];
                int result;
@@ -658,10 +663,26 @@ static void __init do_initcalls(void)
                        print_fn_descriptor_symbol(": %s()",
                                        (unsigned long) *call);
                        printk("\n");
+                       t0 = ktime_get();
                }
 
                result = (*call)();
 
+               if (initcall_debug) {
+                       t1 = ktime_get();
+                       delta = ktime_sub(t1, t0);
+
+                       printk("initcall 0x%p", *call);
+                       print_fn_descriptor_symbol(": %s()",
+                                       (unsigned long) *call);
+                       printk(" returned %d.\n", result);
+
+                       printk("initcall 0x%p ran for %Ld msecs: ",
+                               *call, (unsigned long long)delta.tv64 >> 20);
+                       print_fn_descriptor_symbol("%s()\n",
+                               (unsigned long) *call);
+               }
+
                if (result && result != -ENODEV && initcall_debug) {
                        sprintf(msgbuf, "error code %d", result);
                        msg = msgbuf;
index fa18141539fb38d4f6980c5b1f74b4c4dafa66e9..8b44aa9a7c95dd928b2a4125d23381a3c1edcede 100644 (file)
@@ -542,6 +542,8 @@ static inline int put_compat_shminfo64(struct shminfo64 *smi,
 
        if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
                return -EFAULT;
+       if (smi->shmmax > INT_MAX)
+               smi->shmmax = INT_MAX;
        err  = __put_user(smi->shmmax, &up64->shmmax);
        err |= __put_user(smi->shmmin, &up64->shmmin);
        err |= __put_user(smi->shmmni, &up64->shmmni);
@@ -557,6 +559,8 @@ static inline int put_compat_shminfo(struct shminfo64 *smi,
 
        if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
                return -EFAULT;
+       if (smi->shmmax > INT_MAX)
+               smi->shmmax = INT_MAX;
        err  = __put_user(smi->shmmax, &up->shmmax);
        err |= __put_user(smi->shmmin, &up->shmmin);
        err |= __put_user(smi->shmmni, &up->shmmni);
index d3e12efd55cb39e6cdce7cd48ac73833100f60cf..9964b2224c707d48c6aec6ef658bd3506e12467a 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -75,7 +75,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/time.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
index 0b652387d169a6b6af1609071bfb3aa2e8a6b954..7536a7292d4821ae7b64b4f79f6f32f6657c40da 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/shm.h>
 #include <linux/init.h>
 #include <linux/msg.h>
-#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/capability.h>
@@ -85,53 +84,20 @@ err_mem:
        return ERR_PTR(err);
 }
 
-int unshare_ipcs(unsigned long unshare_flags, struct ipc_namespace **new_ipc)
+struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
 {
-       struct ipc_namespace *new;
-
-       if (unshare_flags & CLONE_NEWIPC) {
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
-               new = clone_ipc_ns(current->nsproxy->ipc_ns);
-               if (IS_ERR(new))
-                       return PTR_ERR(new);
-
-               *new_ipc = new;
-       }
-
-       return 0;
-}
-
-int copy_ipcs(unsigned long flags, struct task_struct *tsk)
-{
-       struct ipc_namespace *old_ns = tsk->nsproxy->ipc_ns;
        struct ipc_namespace *new_ns;
-       int err = 0;
 
-       if (!old_ns)
-               return 0;
-
-       get_ipc_ns(old_ns);
+       BUG_ON(!ns);
+       get_ipc_ns(ns);
 
        if (!(flags & CLONE_NEWIPC))
-               return 0;
+               return ns;
 
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
+       new_ns = clone_ipc_ns(ns);
 
-       new_ns = clone_ipc_ns(old_ns);
-       if (!new_ns) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       tsk->nsproxy->ipc_ns = new_ns;
-out:
-       put_ipc_ns(old_ns);
-       return err;
+       put_ipc_ns(ns);
+       return new_ns;
 }
 
 void free_ipc_ns(struct kref *kref)
@@ -145,11 +111,11 @@ void free_ipc_ns(struct kref *kref)
        kfree(ns);
 }
 #else
-int copy_ipcs(unsigned long flags, struct task_struct *tsk)
+struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
 {
        if (flags & CLONE_NEWIPC)
-               return -EINVAL;
-       return 0;
+               return ERR_PTR(-EINVAL);
+       return ns;
 }
 #endif
 
index 0b46a5dff4c047c72f9d062484124bd3261cf1a3..c64ce9c14207644bfc07c5f2c729f5fe9b66c5b6 100644 (file)
@@ -23,7 +23,7 @@ config PREEMPT_VOLUNTARY
          "explicit preemption points" to the kernel code. These new
          preemption points have been selected to reduce the maximum
          latency of rescheduling, providing faster application reactions,
-         at the cost of slighly lower throughput.
+         at the cost of slightly lower throughput.
 
          This allows reaction to interactive events by allowing a
          low priority process to voluntarily preempt itself even if it
@@ -43,7 +43,7 @@ config PREEMPT
          even if it is in kernel mode executing a system call and would
          otherwise not be about to reach a natural preemption point.
          This allows applications to run more 'smoothly' even when the
-         system is under load, at the cost of slighly lower throughput
+         system is under load, at the cost of slightly lower throughput
          and a slight runtime overhead to kernel code.
 
          Select this if you are building a kernel for a desktop or
index ac6b27abb1adf21bccafac0dc9dde9c5929ffe83..642d4277c2ea4c13dcc0269dcaeaa224cff8f5ab 100644 (file)
@@ -8,7 +8,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
            signal.o sys.o kmod.o workqueue.o pid.o \
            rcupdate.o extable.o params.o posix-timers.o \
            kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
-           hrtimer.o rwsem.o latency.o nsproxy.o srcu.o
+           hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
index 4e9d20829681c251e7dcfa9bdfd59d2e5f6fade5..d13276d41410c28a21bdc3e69cf7104b02e28bc4 100644 (file)
@@ -515,8 +515,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
                        err = -EPERM;
                break;
        case AUDIT_USER:
-       case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
-       case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
+       case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
+       case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
                if (security_netlink_recv(skb, CAP_AUDIT_WRITE))
                        err = -EPERM;
                break;
@@ -614,8 +614,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                                        loginuid, sid);
                break;
        case AUDIT_USER:
-       case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
-       case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
+       case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
+       case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
 
index 8fa1fb28f8a79b895d6438a2485466d2ac8efda1..e84d3f9c6c7ba87218df59577462fc2523c0b6f9 100644 (file)
@@ -61,18 +61,9 @@ static ssize_t
 ikconfig_read_current(struct file *file, char __user *buf,
                      size_t len, loff_t * offset)
 {
-       loff_t pos = *offset;
-       ssize_t count;
-
-       if (pos >= kernel_config_data_size)
-               return 0;
-
-       count = min(len, (size_t)(kernel_config_data_size - pos));
-       if (copy_to_user(buf, kernel_config_data + MAGIC_SIZE + pos, count))
-               return -EFAULT;
-
-       *offset += count;
-       return count;
+       return simple_read_from_buffer(buf, len, offset,
+                                      kernel_config_data + MAGIC_SIZE,
+                                      kernel_config_data_size);
 }
 
 static const struct file_operations ikconfig_file_ops = {
index 36e70845cfc3b40a4cfa98b06365df480caac6f3..208cf3497c10230552e12de042a72a1da61fe955 100644 (file)
@@ -97,7 +97,7 @@ static inline void check_for_tasks(int cpu)
                    (!cputime_eq(p->utime, cputime_zero) ||
                     !cputime_eq(p->stime, cputime_zero)))
                        printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\
-                               (state = %ld, flags = %lx) \n",
+                               (state = %ld, flags = %x) \n",
                                 p->comm, p->pid, cpu, p->state, p->flags);
        }
        write_unlock_irq(&tasklist_lock);
@@ -120,11 +120,13 @@ static int take_cpu_down(void *unused)
 }
 
 /* Requires cpu_add_remove_lock to be held */
-static int _cpu_down(unsigned int cpu)
+static int _cpu_down(unsigned int cpu, int tasks_frozen)
 {
-       int err;
+       int err, nr_calls = 0;
        struct task_struct *p;
        cpumask_t old_allowed, tmp;
+       void *hcpu = (void *)(long)cpu;
+       unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
 
        if (num_online_cpus() == 1)
                return -EBUSY;
@@ -132,12 +134,16 @@ static int _cpu_down(unsigned int cpu)
        if (!cpu_online(cpu))
                return -EINVAL;
 
-       err = raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
-                                               (void *)(long)cpu);
+       raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu);
+       err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
+                                       hcpu, -1, &nr_calls);
        if (err == NOTIFY_BAD) {
+               __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
+                                         hcpu, nr_calls, NULL);
                printk("%s: attempt to take down CPU %u failed\n",
                                __FUNCTION__, cpu);
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_release;
        }
 
        /* Ensure that we are not runnable on dying cpu */
@@ -152,8 +158,8 @@ static int _cpu_down(unsigned int cpu)
 
        if (IS_ERR(p) || cpu_online(cpu)) {
                /* CPU didn't die: tell everyone.  Can't complain. */
-               if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
-                               (void *)(long)cpu) == NOTIFY_BAD)
+               if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
+                                           hcpu) == NOTIFY_BAD)
                        BUG();
 
                if (IS_ERR(p)) {
@@ -170,13 +176,9 @@ static int _cpu_down(unsigned int cpu)
        /* This actually kills the CPU. */
        __cpu_die(cpu);
 
-       /* Move it here so it can run. */
-       kthread_bind(p, get_cpu());
-       put_cpu();
-
        /* CPU is completely dead: tell everyone.  Too late to complain. */
-       if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD,
-                       (void *)(long)cpu) == NOTIFY_BAD)
+       if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD | mod,
+                                   hcpu) == NOTIFY_BAD)
                BUG();
 
        check_for_tasks(cpu);
@@ -185,6 +187,8 @@ out_thread:
        err = kthread_stop(p);
 out_allowed:
        set_cpus_allowed(current, old_allowed);
+out_release:
+       raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, hcpu);
        return err;
 }
 
@@ -196,7 +200,7 @@ int cpu_down(unsigned int cpu)
        if (cpu_hotplug_disabled)
                err = -EBUSY;
        else
-               err = _cpu_down(cpu);
+               err = _cpu_down(cpu, 0);
 
        mutex_unlock(&cpu_add_remove_lock);
        return err;
@@ -204,15 +208,18 @@ int cpu_down(unsigned int cpu)
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 /* Requires cpu_add_remove_lock to be held */
-static int __cpuinit _cpu_up(unsigned int cpu)
+static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
 {
-       int ret;
+       int ret, nr_calls = 0;
        void *hcpu = (void *)(long)cpu;
+       unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
 
        if (cpu_online(cpu) || !cpu_present(cpu))
                return -EINVAL;
 
-       ret = raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+       raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu);
+       ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE | mod, hcpu,
+                                                       -1, &nr_calls);
        if (ret == NOTIFY_BAD) {
                printk("%s: attempt to bring up CPU %u failed\n",
                                __FUNCTION__, cpu);
@@ -229,12 +236,13 @@ static int __cpuinit _cpu_up(unsigned int cpu)
        BUG_ON(!cpu_online(cpu));
 
        /* Now call notifier in preparation. */
-       raw_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
+       raw_notifier_call_chain(&cpu_chain, CPU_ONLINE | mod, hcpu);
 
 out_notify:
        if (ret != 0)
-               raw_notifier_call_chain(&cpu_chain,
-                               CPU_UP_CANCELED, hcpu);
+               __raw_notifier_call_chain(&cpu_chain,
+                               CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
+       raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, hcpu);
 
        return ret;
 }
@@ -247,19 +255,13 @@ int __cpuinit cpu_up(unsigned int cpu)
        if (cpu_hotplug_disabled)
                err = -EBUSY;
        else
-               err = _cpu_up(cpu);
+               err = _cpu_up(cpu, 0);
 
        mutex_unlock(&cpu_add_remove_lock);
        return err;
 }
 
 #ifdef CONFIG_SUSPEND_SMP
-/* Needed to prevent the microcode driver from requesting firmware in its CPU
- * hotplug notifier during the suspend/resume.
- */
-int suspend_cpu_hotplug;
-EXPORT_SYMBOL(suspend_cpu_hotplug);
-
 static cpumask_t frozen_cpus;
 
 int disable_nonboot_cpus(void)
@@ -267,7 +269,6 @@ int disable_nonboot_cpus(void)
        int cpu, first_cpu, error = 0;
 
        mutex_lock(&cpu_add_remove_lock);
-       suspend_cpu_hotplug = 1;
        first_cpu = first_cpu(cpu_online_map);
        /* We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
@@ -277,7 +278,7 @@ int disable_nonboot_cpus(void)
        for_each_online_cpu(cpu) {
                if (cpu == first_cpu)
                        continue;
-               error = _cpu_down(cpu);
+               error = _cpu_down(cpu, 1);
                if (!error) {
                        cpu_set(cpu, frozen_cpus);
                        printk("CPU%d is down\n", cpu);
@@ -294,7 +295,6 @@ int disable_nonboot_cpus(void)
        } else {
                printk(KERN_ERR "Non-boot CPUs are not disabled\n");
        }
-       suspend_cpu_hotplug = 0;
        mutex_unlock(&cpu_add_remove_lock);
        return error;
 }
@@ -309,10 +309,9 @@ void enable_nonboot_cpus(void)
        if (cpus_empty(frozen_cpus))
                goto out;
 
-       suspend_cpu_hotplug = 1;
        printk("Enabling non-boot CPUs ...\n");
        for_each_cpu_mask(cpu, frozen_cpus) {
-               error = _cpu_up(cpu);
+               error = _cpu_up(cpu, 1);
                if (!error) {
                        printk("CPU%d is up\n", cpu);
                        continue;
@@ -320,7 +319,6 @@ void enable_nonboot_cpus(void)
                printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
        }
        cpus_clear(frozen_cpus);
-       suspend_cpu_hotplug = 0;
 out:
        mutex_unlock(&cpu_add_remove_lock);
 }
index d240349cbf0f282d56e12205b68d19ecce215b40..f57854b0892275d901e9e1b7b8f2e4784adcc37a 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/seq_file.h>
 #include <linux/security.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/string.h>
@@ -822,11 +821,22 @@ static int update_cpumask(struct cpuset *cs, char *buf)
                return -EACCES;
 
        trialcs = *cs;
-       retval = cpulist_parse(buf, trialcs.cpus_allowed);
-       if (retval < 0)
-               return retval;
+
+       /*
+        * We allow a cpuset's cpus_allowed to be empty; if it has attached
+        * tasks, we'll catch it later when we validate the change and return
+        * -ENOSPC.
+        */
+       if (!buf[0] || (buf[0] == '\n' && !buf[1])) {
+               cpus_clear(trialcs.cpus_allowed);
+       } else {
+               retval = cpulist_parse(buf, trialcs.cpus_allowed);
+               if (retval < 0)
+                       return retval;
+       }
        cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
-       if (cpus_empty(trialcs.cpus_allowed))
+       /* cpus_allowed cannot be empty for a cpuset with attached tasks. */
+       if (atomic_read(&cs->count) && cpus_empty(trialcs.cpus_allowed))
                return -ENOSPC;
        retval = validate_change(cs, &trialcs);
        if (retval < 0)
@@ -919,16 +929,27 @@ static int update_nodemask(struct cpuset *cs, char *buf)
                return -EACCES;
 
        trialcs = *cs;
-       retval = nodelist_parse(buf, trialcs.mems_allowed);
-       if (retval < 0)
-               goto done;
+
+       /*
+        * We allow a cpuset's mems_allowed to be empty; if it has attached
+        * tasks, we'll catch it later when we validate the change and return
+        * -ENOSPC.
+        */
+       if (!buf[0] || (buf[0] == '\n' && !buf[1])) {
+               nodes_clear(trialcs.mems_allowed);
+       } else {
+               retval = nodelist_parse(buf, trialcs.mems_allowed);
+               if (retval < 0)
+                       goto done;
+       }
        nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map);
        oldmem = cs->mems_allowed;
        if (nodes_equal(oldmem, trialcs.mems_allowed)) {
                retval = 0;             /* Too easy - nothing to do */
                goto done;
        }
-       if (nodes_empty(trialcs.mems_allowed)) {
+       /* mems_allowed cannot be empty for a cpuset with attached tasks. */
+       if (atomic_read(&cs->count) && nodes_empty(trialcs.mems_allowed)) {
                retval = -ENOSPC;
                goto done;
        }
@@ -1751,12 +1772,7 @@ static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
 {
        struct ctr_struct *ctr = file->private_data;
 
-       if (*ppos + nbytes > ctr->bufsz)
-               nbytes = ctr->bufsz - *ppos;
-       if (copy_to_user(buf, ctr->buf + *ppos, nbytes))
-               return -EFAULT;
-       *ppos += nbytes;
-       return nbytes;
+       return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
 }
 
 static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
@@ -2200,10 +2216,6 @@ void cpuset_fork(struct task_struct *child)
  * it is holding that mutex while calling check_for_release(),
  * which calls kmalloc(), so can't be called holding callback_mutex().
  *
- * We don't need to task_lock() this reference to tsk->cpuset,
- * because tsk is already marked PF_EXITING, so attach_task() won't
- * mess with it, or task is a failed fork, never visible to attach_task.
- *
  * the_top_cpuset_hack:
  *
  *    Set the exiting tasks cpuset to the root cpuset (top_cpuset).
@@ -2242,8 +2254,10 @@ void cpuset_exit(struct task_struct *tsk)
 {
        struct cpuset *cs;
 
+       task_lock(current);
        cs = tsk->cpuset;
        tsk->cpuset = &top_cpuset;      /* the_top_cpuset_hack - see above */
+       task_unlock(current);
 
        if (notify_on_release(cs)) {
                char *pathbuf = NULL;
diff --git a/kernel/die_notifier.c b/kernel/die_notifier.c
new file mode 100644 (file)
index 0000000..0d98827
--- /dev/null
@@ -0,0 +1,38 @@
+
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/vmalloc.h>
+#include <linux/kdebug.h>
+
+
+static ATOMIC_NOTIFIER_HEAD(die_chain);
+
+int notify_die(enum die_val val, const char *str,
+              struct pt_regs *regs, long err, int trap, int sig)
+{
+       struct die_args args = {
+               .regs           = regs,
+               .str            = str,
+               .err            = err,
+               .trapnr         = trap,
+               .signr          = sig,
+
+       };
+
+       return atomic_notifier_call_chain(&die_chain, val, &args);
+}
+
+int register_die_notifier(struct notifier_block *nb)
+{
+       vmalloc_sync_all();
+       return atomic_notifier_chain_register(&die_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&die_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_die_notifier);
+
+
index 92369240d91d3a9582b490da701be24a6f81795f..b0c6f0c3a2dfadd5e36647f2b0e5e5699174330d 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/capability.h>
 #include <linux/completion.h>
@@ -27,6 +26,7 @@
 #include <linux/profile.h>
 #include <linux/mount.h>
 #include <linux/proc_fs.h>
+#include <linux/kthread.h>
 #include <linux/mempolicy.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
@@ -255,26 +255,25 @@ static int has_stopped_jobs(struct pid *pgrp)
 }
 
 /**
- * reparent_to_init - Reparent the calling kernel thread to the init task of the pid space that the thread belongs to.
+ * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd
  *
  * If a kernel thread is launched as a result of a system call, or if
- * it ever exits, it should generally reparent itself to init so that
- * it is correctly cleaned up on exit.
+ * it ever exits, it should generally reparent itself to kthreadd so it
+ * isn't in the way of other processes and is correctly cleaned up on exit.
  *
  * The various task state such as scheduling policy and priority may have
  * been inherited from a user process, so we reset them to sane values here.
  *
- * NOTE that reparent_to_init() gives the caller full capabilities.
+ * NOTE that reparent_to_kthreadd() gives the caller full capabilities.
  */
-static void reparent_to_init(void)
+static void reparent_to_kthreadd(void)
 {
        write_lock_irq(&tasklist_lock);
 
        ptrace_unlink(current);
        /* Reparent to init */
        remove_parent(current);
-       current->parent = child_reaper(current);
-       current->real_parent = child_reaper(current);
+       current->real_parent = current->parent = kthreadd_task;
        add_parent(current);
 
        /* Set the exit signal to SIGCHLD so we signal init on exit */
@@ -348,7 +347,7 @@ int disallow_signal(int sig)
                return -EINVAL;
 
        spin_lock_irq(&current->sighand->siglock);
-       sigaddset(&current->blocked, sig);
+       current->sighand->action[(sig)-1].sa.sa_handler = SIG_IGN;
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
        return 0;
@@ -401,7 +400,7 @@ void daemonize(const char *name, ...)
        current->files = init_task.files;
        atomic_inc(&current->files->count);
 
-       reparent_to_init();
+       reparent_to_kthreadd();
 }
 
 EXPORT_SYMBOL(daemonize);
index b7d169def9424f5cff4f1c89d772711dd0a5b44c..5dd3979747f5ef8e1e217d039f14ad8759e38984 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/unistd.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/completion.h>
@@ -106,7 +105,7 @@ static struct kmem_cache *mm_cachep;
 
 void free_task(struct task_struct *tsk)
 {
-       free_thread_info(tsk->thread_info);
+       free_thread_info(tsk->stack);
        rt_mutex_debug_task_free(tsk);
        free_task_struct(tsk);
 }
@@ -176,7 +175,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        }
 
        *tsk = *orig;
-       tsk->thread_info = ti;
+       tsk->stack = ti;
        setup_thread_stack(tsk, orig);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
@@ -1515,26 +1514,6 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
        return 0;
 }
 
-/*
- * Unshare the mnt_namespace structure if it is being shared
- */
-static int unshare_mnt_namespace(unsigned long unshare_flags,
-               struct mnt_namespace **new_nsp, struct fs_struct *new_fs)
-{
-       struct mnt_namespace *ns = current->nsproxy->mnt_ns;
-
-       if ((unshare_flags & CLONE_NEWNS) && ns) {
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
-               *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs);
-               if (!*new_nsp)
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 /*
  * Unsharing of sighand is not supported yet
  */
@@ -1593,16 +1572,6 @@ static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **n
        return 0;
 }
 
-#ifndef CONFIG_IPC_NS
-static inline int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns)
-{
-       if (flags & CLONE_NEWIPC)
-               return -EINVAL;
-
-       return 0;
-}
-#endif
-
 /*
  * unshare allows a process to 'unshare' part of the process
  * context which was originally shared using clone.  copy_*
@@ -1615,14 +1584,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
 {
        int err = 0;
        struct fs_struct *fs, *new_fs = NULL;
-       struct mnt_namespace *ns, *new_ns = NULL;
        struct sighand_struct *new_sigh = NULL;
        struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
        struct files_struct *fd, *new_fd = NULL;
        struct sem_undo_list *new_ulist = NULL;
        struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL;
-       struct uts_namespace *uts, *new_uts = NULL;
-       struct ipc_namespace *ipc, *new_ipc = NULL;
 
        check_unshare_flags(&unshare_flags);
 
@@ -1637,36 +1603,24 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                goto bad_unshare_out;
        if ((err = unshare_fs(unshare_flags, &new_fs)))
                goto bad_unshare_cleanup_thread;
-       if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs)))
-               goto bad_unshare_cleanup_fs;
        if ((err = unshare_sighand(unshare_flags, &new_sigh)))
-               goto bad_unshare_cleanup_ns;
+               goto bad_unshare_cleanup_fs;
        if ((err = unshare_vm(unshare_flags, &new_mm)))
                goto bad_unshare_cleanup_sigh;
        if ((err = unshare_fd(unshare_flags, &new_fd)))
                goto bad_unshare_cleanup_vm;
        if ((err = unshare_semundo(unshare_flags, &new_ulist)))
                goto bad_unshare_cleanup_fd;
-       if ((err = unshare_utsname(unshare_flags, &new_uts)))
+       if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
+                       new_fs)))
                goto bad_unshare_cleanup_semundo;
-       if ((err = unshare_ipcs(unshare_flags, &new_ipc)))
-               goto bad_unshare_cleanup_uts;
-
-       if (new_ns || new_uts || new_ipc) {
-               old_nsproxy = current->nsproxy;
-               new_nsproxy = dup_namespaces(old_nsproxy);
-               if (!new_nsproxy) {
-                       err = -ENOMEM;
-                       goto bad_unshare_cleanup_ipc;
-               }
-       }
 
-       if (new_fs || new_ns || new_mm || new_fd || new_ulist ||
-                               new_uts || new_ipc) {
+       if (new_fs ||  new_mm || new_fd || new_ulist || new_nsproxy) {
 
                task_lock(current);
 
                if (new_nsproxy) {
+                       old_nsproxy = current->nsproxy;
                        current->nsproxy = new_nsproxy;
                        new_nsproxy = old_nsproxy;
                }
@@ -1677,12 +1631,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                        new_fs = fs;
                }
 
-               if (new_ns) {
-                       ns = current->nsproxy->mnt_ns;
-                       current->nsproxy->mnt_ns = new_ns;
-                       new_ns = ns;
-               }
-
                if (new_mm) {
                        mm = current->mm;
                        active_mm = current->active_mm;
@@ -1698,32 +1646,12 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                        new_fd = fd;
                }
 
-               if (new_uts) {
-                       uts = current->nsproxy->uts_ns;
-                       current->nsproxy->uts_ns = new_uts;
-                       new_uts = uts;
-               }
-
-               if (new_ipc) {
-                       ipc = current->nsproxy->ipc_ns;
-                       current->nsproxy->ipc_ns = new_ipc;
-                       new_ipc = ipc;
-               }
-
                task_unlock(current);
        }
 
        if (new_nsproxy)
                put_nsproxy(new_nsproxy);
 
-bad_unshare_cleanup_ipc:
-       if (new_ipc)
-               put_ipc_ns(new_ipc);
-
-bad_unshare_cleanup_uts:
-       if (new_uts)
-               put_uts_ns(new_uts);
-
 bad_unshare_cleanup_semundo:
 bad_unshare_cleanup_fd:
        if (new_fd)
@@ -1738,10 +1666,6 @@ bad_unshare_cleanup_sigh:
                if (atomic_dec_and_test(&new_sigh->count))
                        kmem_cache_free(sighand_cachep, new_sigh);
 
-bad_unshare_cleanup_ns:
-       if (new_ns)
-               put_mnt_ns(new_ns);
-
 bad_unshare_cleanup_fs:
        if (new_fs)
                put_fs_struct(new_fs);
index 5a270b5e3f95de173e44194cd7e5b3d511ec6ff8..b7ce15c67e324b468d13599d47df7423adcd69d4 100644 (file)
@@ -16,6 +16,9 @@
  *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
  *  Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
  *
+ *  PRIVATE futexes by Eric Dumazet
+ *  Copyright (C) 2007 Eric Dumazet <dada1@cosmosbay.com>
+ *
  *  Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
  *  enough at me, Linus for the original (flawed) idea, Matthew
  *  Kirkwood for proof-of-concept implementation.
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
+#include <linux/module.h>
 #include <asm/futex.h>
 
 #include "rtmutex_common.h"
 
-#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
 
-/*
- * Futexes are matched on equal values of this key.
- * The key type depends on whether it's a shared or private mapping.
- * Don't rearrange members without looking at hash_futex().
- *
- * offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
- * We set bit 0 to indicate if it's an inode-based key.
- */
-union futex_key {
-       struct {
-               unsigned long pgoff;
-               struct inode *inode;
-               int offset;
-       } shared;
-       struct {
-               unsigned long address;
-               struct mm_struct *mm;
-               int offset;
-       } private;
-       struct {
-               unsigned long word;
-               void *ptr;
-               int offset;
-       } both;
-};
+#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
  * Priority Inheritance state:
@@ -106,12 +90,12 @@ struct futex_pi_state {
  * we can wake only the relevant ones (hashed queues may be shared).
  *
  * A futex_q has a woken state, just like tasks have TASK_RUNNING.
- * It is considered woken when list_empty(&q->list) || q->lock_ptr == 0.
+ * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
  * The order of wakup is always to make the first condition true, then
  * wake up q->waiters, then make the second condition true.
  */
 struct futex_q {
-       struct list_head list;
+       struct plist_node list;
        wait_queue_head_t waiters;
 
        /* Which hash list lock to use: */
@@ -127,14 +111,20 @@ struct futex_q {
        /* Optional priority inheritance state: */
        struct futex_pi_state *pi_state;
        struct task_struct *task;
+
+       /*
+        * This waiter is used in case of requeue from a
+        * normal futex to a PI-futex
+        */
+       struct rt_mutex_waiter waiter;
 };
 
 /*
  * Split the global futex_lock into every hash list lock.
  */
 struct futex_hash_bucket {
-       spinlock_t              lock;
-       struct list_head       chain;
+       spinlock_t lock;
+       struct plist_head chain;
 };
 
 static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
@@ -163,19 +153,26 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
                && key1->both.offset == key2->both.offset);
 }
 
-/*
- * Get parameters which are the keys for a futex.
+/**
+ * get_futex_key - Get parameters which are the keys for a futex.
+ * @uaddr: virtual address of the futex
+ * @shared: NULL for a PROCESS_PRIVATE futex,
+ *     &current->mm->mmap_sem for a PROCESS_SHARED futex
+ * @key: address where result is stored.
+ *
+ * Returns a negative error code or 0
+ * The key words are stored in *key on success.
  *
  * For shared mappings, it's (page->index, vma->vm_file->f_path.dentry->d_inode,
  * offset_within_page).  For private mappings, it's (uaddr, current->mm).
  * We can usually work out the index without swapping in the page.
  *
- * Returns: 0, or negative error code.
- * The key words are stored in *key on success.
- *
- * Should be called with &current->mm->mmap_sem but NOT any spinlocks.
+ * fshared is NULL for PROCESS_PRIVATE futexes
+ * For other futexes, it points to &current->mm->mmap_sem and
+ * caller must have taken the reader lock. but NOT any spinlocks.
  */
-static int get_futex_key(u32 __user *uaddr, union futex_key *key)
+int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
+                 union futex_key *key)
 {
        unsigned long address = (unsigned long)uaddr;
        struct mm_struct *mm = current->mm;
@@ -187,10 +184,24 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
         * The futex address must be "naturally" aligned.
         */
        key->both.offset = address % PAGE_SIZE;
-       if (unlikely((key->both.offset % sizeof(u32)) != 0))
+       if (unlikely((address % sizeof(u32)) != 0))
                return -EINVAL;
        address -= key->both.offset;
 
+       /*
+        * PROCESS_PRIVATE futexes are fast.
+        * As the mm cannot disappear under us and the 'key' only needs
+        * virtual address, we dont even have to find the underlying vma.
+        * Note : We do have to check 'uaddr' is a valid user address,
+        *        but access_ok() should be faster than find_vma()
+        */
+       if (!fshared) {
+               if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
+                       return -EFAULT;
+               key->private.mm = mm;
+               key->private.address = address;
+               return 0;
+       }
        /*
         * The futex is hashed differently depending on whether
         * it's in a shared or private mapping.  So check vma first.
@@ -205,6 +216,9 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
        if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ))
                return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES;
 
+       /* Save the user address in the ley */
+       key->uaddr = uaddr;
+
        /*
         * Private mappings are handled in a simple way.
         *
@@ -215,6 +229,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
         * mappings of _writable_ handles.
         */
        if (likely(!(vma->vm_flags & VM_MAYSHARE))) {
+               key->both.offset |= FUT_OFF_MMSHARED; /* reference taken on mm */
                key->private.mm = mm;
                key->private.address = address;
                return 0;
@@ -224,7 +239,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
         * Linear file mappings are also simple.
         */
        key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
-       key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
+       key->both.offset |= FUT_OFF_INODE; /* inode-based key. */
        if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
                key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
                                     + vma->vm_pgoff);
@@ -246,37 +261,46 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
        }
        return err;
 }
+EXPORT_SYMBOL_GPL(get_futex_key);
 
 /*
  * Take a reference to the resource addressed by a key.
  * Can be called while holding spinlocks.
  *
- * NOTE: mmap_sem MUST be held between get_futex_key() and calling this
- * function, if it is called at all.  mmap_sem keeps key->shared.inode valid.
  */
-static inline void get_key_refs(union futex_key *key)
+inline void get_futex_key_refs(union futex_key *key)
 {
-       if (key->both.ptr != 0) {
-               if (key->both.offset & 1)
+       if (key->both.ptr == 0)
+               return;
+       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+               case FUT_OFF_INODE:
                        atomic_inc(&key->shared.inode->i_count);
-               else
+                       break;
+               case FUT_OFF_MMSHARED:
                        atomic_inc(&key->private.mm->mm_count);
+                       break;
        }
 }
+EXPORT_SYMBOL_GPL(get_futex_key_refs);
 
 /*
  * Drop a reference to the resource addressed by a key.
  * The hash bucket spinlock must not be held.
  */
-static void drop_key_refs(union futex_key *key)
+void drop_futex_key_refs(union futex_key *key)
 {
-       if (key->both.ptr != 0) {
-               if (key->both.offset & 1)
+       if (key->both.ptr == 0)
+               return;
+       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+               case FUT_OFF_INODE:
                        iput(key->shared.inode);
-               else
+                       break;
+               case FUT_OFF_MMSHARED:
                        mmdrop(key->private.mm);
+                       break;
        }
 }
+EXPORT_SYMBOL_GPL(drop_futex_key_refs);
 
 static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
 {
@@ -290,28 +314,38 @@ static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
 }
 
 /*
- * Fault handling. Called with current->mm->mmap_sem held.
+ * Fault handling.
+ * if fshared is non NULL, current->mm->mmap_sem is already held
  */
-static int futex_handle_fault(unsigned long address, int attempt)
+static int futex_handle_fault(unsigned long address,
+                             struct rw_semaphore *fshared, int attempt)
 {
        struct vm_area_struct * vma;
        struct mm_struct *mm = current->mm;
+       int ret = -EFAULT;
 
-       if (attempt > 2 || !(vma = find_vma(mm, address)) ||
-           vma->vm_start > address || !(vma->vm_flags & VM_WRITE))
-               return -EFAULT;
+       if (attempt > 2)
+               return ret;
 
-       switch (handle_mm_fault(mm, vma, address, 1)) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       default:
-               return -EFAULT;
+       if (!fshared)
+               down_read(&mm->mmap_sem);
+       vma = find_vma(mm, address);
+       if (vma && address >= vma->vm_start &&
+           (vma->vm_flags & VM_WRITE)) {
+               switch (handle_mm_fault(mm, vma, address, 1)) {
+               case VM_FAULT_MINOR:
+                       ret = 0;
+                       current->min_flt++;
+                       break;
+               case VM_FAULT_MAJOR:
+                       ret = 0;
+                       current->maj_flt++;
+                       break;
+               }
        }
-       return 0;
+       if (!fshared)
+               up_read(&mm->mmap_sem);
+       return ret;
 }
 
 /*
@@ -461,18 +495,19 @@ void exit_pi_state_list(struct task_struct *curr)
 }
 
 static int
-lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
+lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
+               union futex_key *key, struct futex_pi_state **ps)
 {
        struct futex_pi_state *pi_state = NULL;
        struct futex_q *this, *next;
-       struct list_head *head;
+       struct plist_head *head;
        struct task_struct *p;
        pid_t pid;
 
        head = &hb->chain;
 
-       list_for_each_entry_safe(this, next, head, list) {
-               if (match_futex(&this->key, &me->key)) {
+       plist_for_each_entry_safe(this, next, head, list) {
+               if (match_futex(&this->key, key)) {
                        /*
                         * Another waiter already exists - bump up
                         * the refcount and return its pi_state:
@@ -487,7 +522,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
                        WARN_ON(!atomic_read(&pi_state->refcount));
 
                        atomic_inc(&pi_state->refcount);
-                       me->pi_state = pi_state;
+                       *ps = pi_state;
 
                        return 0;
                }
@@ -514,7 +549,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
        rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
 
        /* Store the key for possible exit cleanups: */
-       pi_state->key = me->key;
+       pi_state->key = *key;
 
        spin_lock_irq(&p->pi_lock);
        WARN_ON(!list_empty(&pi_state->list));
@@ -524,7 +559,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
 
        put_task_struct(p);
 
-       me->pi_state = pi_state;
+       *ps = pi_state;
 
        return 0;
 }
@@ -535,12 +570,12 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
  */
 static void wake_futex(struct futex_q *q)
 {
-       list_del_init(&q->list);
+       plist_del(&q->list, &q->list.plist);
        if (q->filp)
                send_sigio(&q->filp->f_owner, q->fd, POLL_IN);
        /*
         * The lock in wake_up_all() is a crucial memory barrier after the
-        * list_del_init() and also before assigning to q->lock_ptr.
+        * plist_del() and also before assigning to q->lock_ptr.
         */
        wake_up_all(&q->waiters);
        /*
@@ -584,6 +619,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
         */
        if (!(uval & FUTEX_OWNER_DIED)) {
                newval = FUTEX_WAITERS | new_owner->pid;
+               /* Keep the FUTEX_WAITER_REQUEUED flag if it was set */
+               newval |= (uval & FUTEX_WAITER_REQUEUED);
 
                pagefault_disable();
                curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
@@ -651,17 +688,19 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
  * Wake up all waiters hashed on the physical page that is mapped
  * to this virtual address:
  */
-static int futex_wake(u32 __user *uaddr, int nr_wake)
+static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
+                     int nr_wake)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
-       struct list_head *head;
+       struct plist_head *head;
        union futex_key key;
        int ret;
 
-       down_read(&current->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr, &key);
+       ret = get_futex_key(uaddr, fshared, &key);
        if (unlikely(ret != 0))
                goto out;
 
@@ -669,7 +708,7 @@ static int futex_wake(u32 __user *uaddr, int nr_wake)
        spin_lock(&hb->lock);
        head = &hb->chain;
 
-       list_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, head, list) {
                if (match_futex (&this->key, &key)) {
                        if (this->pi_state) {
                                ret = -EINVAL;
@@ -683,7 +722,261 @@ static int futex_wake(u32 __user *uaddr, int nr_wake)
 
        spin_unlock(&hb->lock);
 out:
-       up_read(&current->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
+       return ret;
+}
+
+/*
+ * Called from futex_requeue_pi.
+ * Set FUTEX_WAITERS and FUTEX_WAITER_REQUEUED flags on the
+ * PI-futex value; search its associated pi_state if an owner exist
+ * or create a new one without owner.
+ */
+static inline int
+lookup_pi_state_for_requeue(u32 __user *uaddr, struct futex_hash_bucket *hb,
+                           union futex_key *key,
+                           struct futex_pi_state **pi_state)
+{
+       u32 curval, uval, newval;
+
+retry:
+       /*
+        * We can't handle a fault cleanly because we can't
+        * release the locks here. Simply return the fault.
+        */
+       if (get_futex_value_locked(&curval, uaddr))
+               return -EFAULT;
+
+       /* set the flags FUTEX_WAITERS and FUTEX_WAITER_REQUEUED */
+       if ((curval & (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED))
+           != (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED)) {
+               /*
+                * No waiters yet, we prepare the futex to have some waiters.
+                */
+
+               uval = curval;
+               newval = uval | FUTEX_WAITERS | FUTEX_WAITER_REQUEUED;
+
+               pagefault_disable();
+               curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+               pagefault_enable();
+
+               if (unlikely(curval == -EFAULT))
+                       return -EFAULT;
+               if (unlikely(curval != uval))
+                       goto retry;
+       }
+
+       if (!(curval & FUTEX_TID_MASK)
+           || lookup_pi_state(curval, hb, key, pi_state)) {
+               /* the futex has no owner (yet) or the lookup failed:
+                  allocate one pi_state without owner */
+
+               *pi_state = alloc_pi_state();
+
+               /* Already stores the key: */
+               (*pi_state)->key = *key;
+
+               /* init the mutex without owner */
+               __rt_mutex_init(&(*pi_state)->pi_mutex, NULL);
+       }
+
+       return 0;
+}
+
+/*
+ * Keep the first nr_wake waiter from futex1, wake up one,
+ * and requeue the next nr_requeue waiters following hashed on
+ * one physical page to another physical page (PI-futex uaddr2)
+ */
+static int futex_requeue_pi(u32 __user *uaddr1,
+                           struct rw_semaphore *fshared,
+                           u32 __user *uaddr2,
+                           int nr_wake, int nr_requeue, u32 *cmpval)
+{
+       union futex_key key1, key2;
+       struct futex_hash_bucket *hb1, *hb2;
+       struct plist_head *head1;
+       struct futex_q *this, *next;
+       struct futex_pi_state *pi_state2 = NULL;
+       struct rt_mutex_waiter *waiter, *top_waiter = NULL;
+       struct rt_mutex *lock2 = NULL;
+       int ret, drop_count = 0;
+
+       if (refill_pi_state_cache())
+               return -ENOMEM;
+
+retry:
+       /*
+        * First take all the futex related locks:
+        */
+       if (fshared)
+               down_read(fshared);
+
+       ret = get_futex_key(uaddr1, fshared, &key1);
+       if (unlikely(ret != 0))
+               goto out;
+       ret = get_futex_key(uaddr2, fshared, &key2);
+       if (unlikely(ret != 0))
+               goto out;
+
+       hb1 = hash_futex(&key1);
+       hb2 = hash_futex(&key2);
+
+       double_lock_hb(hb1, hb2);
+
+       if (likely(cmpval != NULL)) {
+               u32 curval;
+
+               ret = get_futex_value_locked(&curval, uaddr1);
+
+               if (unlikely(ret)) {
+                       spin_unlock(&hb1->lock);
+                       if (hb1 != hb2)
+                               spin_unlock(&hb2->lock);
+
+                       /*
+                        * If we would have faulted, release mmap_sem, fault
+                        * it in and start all over again.
+                        */
+                       if (fshared)
+                               up_read(fshared);
+
+                       ret = get_user(curval, uaddr1);
+
+                       if (!ret)
+                               goto retry;
+
+                       return ret;
+               }
+               if (curval != *cmpval) {
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
+       }
+
+       head1 = &hb1->chain;
+       plist_for_each_entry_safe(this, next, head1, list) {
+               if (!match_futex (&this->key, &key1))
+                       continue;
+               if (++ret <= nr_wake) {
+                       wake_futex(this);
+               } else {
+                       /*
+                        * FIRST: get and set the pi_state
+                        */
+                       if (!pi_state2) {
+                               int s;
+                               /* do this only the first time we requeue someone */
+                               s = lookup_pi_state_for_requeue(uaddr2, hb2,
+                                                               &key2, &pi_state2);
+                               if (s) {
+                                       ret = s;
+                                       goto out_unlock;
+                               }
+
+                               lock2 = &pi_state2->pi_mutex;
+                               spin_lock(&lock2->wait_lock);
+
+                               /* Save the top waiter of the wait_list */
+                               if (rt_mutex_has_waiters(lock2))
+                                       top_waiter = rt_mutex_top_waiter(lock2);
+                       } else
+                               atomic_inc(&pi_state2->refcount);
+
+
+                       this->pi_state = pi_state2;
+
+                       /*
+                        * SECOND: requeue futex_q to the correct hashbucket
+                        */
+
+                       /*
+                        * If key1 and key2 hash to the same bucket, no need to
+                        * requeue.
+                        */
+                       if (likely(head1 != &hb2->chain)) {
+                               plist_del(&this->list, &hb1->chain);
+                               plist_add(&this->list, &hb2->chain);
+                               this->lock_ptr = &hb2->lock;
+#ifdef CONFIG_DEBUG_PI_LIST
+                               this->list.plist.lock = &hb2->lock;
+#endif
+                       }
+                       this->key = key2;
+                       get_futex_key_refs(&key2);
+                       drop_count++;
+
+
+                       /*
+                        * THIRD: queue it to lock2
+                        */
+                       spin_lock_irq(&this->task->pi_lock);
+                       waiter = &this->waiter;
+                       waiter->task = this->task;
+                       waiter->lock = lock2;
+                       plist_node_init(&waiter->list_entry, this->task->prio);
+                       plist_node_init(&waiter->pi_list_entry, this->task->prio);
+                       plist_add(&waiter->list_entry, &lock2->wait_list);
+                       this->task->pi_blocked_on = waiter;
+                       spin_unlock_irq(&this->task->pi_lock);
+
+                       if (ret - nr_wake >= nr_requeue)
+                               break;
+               }
+       }
+
+       /* If we've requeued some tasks and the top_waiter of the rt_mutex
+          has changed, we must adjust the priority of the owner, if any */
+       if (drop_count) {
+               struct task_struct *owner = rt_mutex_owner(lock2);
+               if (owner &&
+                   (top_waiter != (waiter = rt_mutex_top_waiter(lock2)))) {
+                       int chain_walk = 0;
+
+                       spin_lock_irq(&owner->pi_lock);
+                       if (top_waiter)
+                               plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
+                       else
+                               /*
+                                * There was no waiters before the requeue,
+                                * the flag must be updated
+                                */
+                               mark_rt_mutex_waiters(lock2);
+
+                       plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
+                       __rt_mutex_adjust_prio(owner);
+                       if (owner->pi_blocked_on) {
+                               chain_walk = 1;
+                               get_task_struct(owner);
+                       }
+
+                       spin_unlock_irq(&owner->pi_lock);
+                       spin_unlock(&lock2->wait_lock);
+
+                       if (chain_walk)
+                               rt_mutex_adjust_prio_chain(owner, 0, lock2, NULL,
+                                                          current);
+               } else {
+                       /* No owner or the top_waiter does not change */
+                       mark_rt_mutex_waiters(lock2);
+                       spin_unlock(&lock2->wait_lock);
+               }
+       }
+
+out_unlock:
+       spin_unlock(&hb1->lock);
+       if (hb1 != hb2)
+               spin_unlock(&hb2->lock);
+
+       /* drop_futex_key_refs() must be called outside the spinlocks. */
+       while (--drop_count >= 0)
+               drop_futex_key_refs(&key1);
+
+out:
+       if (fshared)
+               up_read(fshared);
        return ret;
 }
 
@@ -692,22 +985,24 @@ out:
  * to this virtual address:
  */
 static int
-futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2,
+futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared,
+             u32 __user *uaddr2,
              int nr_wake, int nr_wake2, int op)
 {
        union futex_key key1, key2;
        struct futex_hash_bucket *hb1, *hb2;
-       struct list_head *head;
+       struct plist_head *head;
        struct futex_q *this, *next;
        int ret, op_ret, attempt = 0;
 
 retryfull:
-       down_read(&current->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr1, &key1);
+       ret = get_futex_key(uaddr1, fshared, &key1);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, &key2);
+       ret = get_futex_key(uaddr2, fshared, &key2);
        if (unlikely(ret != 0))
                goto out;
 
@@ -747,11 +1042,10 @@ retry:
                 * still holding the mmap_sem.
                 */
                if (attempt++) {
-                       if (futex_handle_fault((unsigned long)uaddr2,
-                                               attempt)) {
-                               ret = -EFAULT;
+                       ret = futex_handle_fault((unsigned long)uaddr2,
+                                               fshared, attempt);
+                       if (ret)
                                goto out;
-                       }
                        goto retry;
                }
 
@@ -759,7 +1053,8 @@ retry:
                 * If we would have faulted, release mmap_sem,
                 * fault it in and start all over again.
                 */
-               up_read(&current->mm->mmap_sem);
+               if (fshared)
+                       up_read(fshared);
 
                ret = get_user(dummy, uaddr2);
                if (ret)
@@ -770,7 +1065,7 @@ retry:
 
        head = &hb1->chain;
 
-       list_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, head, list) {
                if (match_futex (&this->key, &key1)) {
                        wake_futex(this);
                        if (++ret >= nr_wake)
@@ -782,7 +1077,7 @@ retry:
                head = &hb2->chain;
 
                op_ret = 0;
-               list_for_each_entry_safe(this, next, head, list) {
+               plist_for_each_entry_safe(this, next, head, list) {
                        if (match_futex (&this->key, &key2)) {
                                wake_futex(this);
                                if (++op_ret >= nr_wake2)
@@ -796,7 +1091,8 @@ retry:
        if (hb1 != hb2)
                spin_unlock(&hb2->lock);
 out:
-       up_read(&current->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
        return ret;
 }
 
@@ -804,22 +1100,24 @@ out:
  * Requeue all waiters hashed on one physical page to another
  * physical page.
  */
-static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
+static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
+                        u32 __user *uaddr2,
                         int nr_wake, int nr_requeue, u32 *cmpval)
 {
        union futex_key key1, key2;
        struct futex_hash_bucket *hb1, *hb2;
-       struct list_head *head1;
+       struct plist_head *head1;
        struct futex_q *this, *next;
        int ret, drop_count = 0;
 
  retry:
-       down_read(&current->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr1, &key1);
+       ret = get_futex_key(uaddr1, fshared, &key1);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, &key2);
+       ret = get_futex_key(uaddr2, fshared, &key2);
        if (unlikely(ret != 0))
                goto out;
 
@@ -842,7 +1140,8 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
                         * If we would have faulted, release mmap_sem, fault
                         * it in and start all over again.
                         */
-                       up_read(&current->mm->mmap_sem);
+                       if (fshared)
+                               up_read(fshared);
 
                        ret = get_user(curval, uaddr1);
 
@@ -858,7 +1157,7 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
        }
 
        head1 = &hb1->chain;
-       list_for_each_entry_safe(this, next, head1, list) {
+       plist_for_each_entry_safe(this, next, head1, list) {
                if (!match_futex (&this->key, &key1))
                        continue;
                if (++ret <= nr_wake) {
@@ -869,11 +1168,15 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
                         * requeue.
                         */
                        if (likely(head1 != &hb2->chain)) {
-                               list_move_tail(&this->list, &hb2->chain);
+                               plist_del(&this->list, &hb1->chain);
+                               plist_add(&this->list, &hb2->chain);
                                this->lock_ptr = &hb2->lock;
-                       }
+#ifdef CONFIG_DEBUG_PI_LIST
+                               this->list.plist.lock = &hb2->lock;
+#endif
+                       }
                        this->key = key2;
-                       get_key_refs(&key2);
+                       get_futex_key_refs(&key2);
                        drop_count++;
 
                        if (ret - nr_wake >= nr_requeue)
@@ -886,12 +1189,13 @@ out_unlock:
        if (hb1 != hb2)
                spin_unlock(&hb2->lock);
 
-       /* drop_key_refs() must be called outside the spinlocks. */
+       /* drop_futex_key_refs() must be called outside the spinlocks. */
        while (--drop_count >= 0)
-               drop_key_refs(&key1);
+               drop_futex_key_refs(&key1);
 
 out:
-       up_read(&current->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
        return ret;
 }
 
@@ -906,7 +1210,7 @@ queue_lock(struct futex_q *q, int fd, struct file *filp)
 
        init_waitqueue_head(&q->waiters);
 
-       get_key_refs(&q->key);
+       get_futex_key_refs(&q->key);
        hb = hash_futex(&q->key);
        q->lock_ptr = &hb->lock;
 
@@ -916,7 +1220,23 @@ queue_lock(struct futex_q *q, int fd, struct file *filp)
 
 static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
 {
-       list_add_tail(&q->list, &hb->chain);
+       int prio;
+
+       /*
+        * The priority used to register this element is
+        * - either the real thread-priority for the real-time threads
+        * (i.e. threads with a priority lower than MAX_RT_PRIO)
+        * - or MAX_RT_PRIO for non-RT threads.
+        * Thus, all RT-threads are woken first in priority order, and
+        * the others are woken last, in FIFO order.
+        */
+       prio = min(current->normal_prio, MAX_RT_PRIO);
+
+       plist_node_init(&q->list, prio);
+#ifdef CONFIG_DEBUG_PI_LIST
+       q->list.plist.lock = &hb->lock;
+#endif
+       plist_add(&q->list, &hb->chain);
        q->task = current;
        spin_unlock(&hb->lock);
 }
@@ -925,7 +1245,7 @@ static inline void
 queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
 {
        spin_unlock(&hb->lock);
-       drop_key_refs(&q->key);
+       drop_futex_key_refs(&q->key);
 }
 
 /*
@@ -971,8 +1291,8 @@ static int unqueue_me(struct futex_q *q)
                        spin_unlock(lock_ptr);
                        goto retry;
                }
-               WARN_ON(list_empty(&q->list));
-               list_del(&q->list);
+               WARN_ON(plist_node_empty(&q->list));
+               plist_del(&q->list, &q->list.plist);
 
                BUG_ON(q->pi_state);
 
@@ -980,29 +1300,94 @@ static int unqueue_me(struct futex_q *q)
                ret = 1;
        }
 
-       drop_key_refs(&q->key);
+       drop_futex_key_refs(&q->key);
        return ret;
 }
 
 /*
  * PI futexes can not be requeued and must remove themself from the
- * hash bucket. The hash bucket lock is held on entry and dropped here.
+ * hash bucket. The hash bucket lock (i.e. lock_ptr) is held on entry
+ * and dropped here.
  */
-static void unqueue_me_pi(struct futex_q *q, struct futex_hash_bucket *hb)
+static void unqueue_me_pi(struct futex_q *q)
 {
-       WARN_ON(list_empty(&q->list));
-       list_del(&q->list);
+       WARN_ON(plist_node_empty(&q->list));
+       plist_del(&q->list, &q->list.plist);
 
        BUG_ON(!q->pi_state);
        free_pi_state(q->pi_state);
        q->pi_state = NULL;
 
-       spin_unlock(&hb->lock);
+       spin_unlock(q->lock_ptr);
 
-       drop_key_refs(&q->key);
+       drop_futex_key_refs(&q->key);
 }
 
-static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
+/*
+ * Fixup the pi_state owner with current.
+ *
+ * The cur->mm semaphore must be  held, it is released at return of this
+ * function.
+ */
+static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
+                               struct futex_q *q,
+                               struct futex_hash_bucket *hb,
+                               struct task_struct *curr)
+{
+       u32 newtid = curr->pid | FUTEX_WAITERS;
+       struct futex_pi_state *pi_state = q->pi_state;
+       u32 uval, curval, newval;
+       int ret;
+
+       /* Owner died? */
+       if (pi_state->owner != NULL) {
+               spin_lock_irq(&pi_state->owner->pi_lock);
+               WARN_ON(list_empty(&pi_state->list));
+               list_del_init(&pi_state->list);
+               spin_unlock_irq(&pi_state->owner->pi_lock);
+       } else
+               newtid |= FUTEX_OWNER_DIED;
+
+       pi_state->owner = curr;
+
+       spin_lock_irq(&curr->pi_lock);
+       WARN_ON(!list_empty(&pi_state->list));
+       list_add(&pi_state->list, &curr->pi_state_list);
+       spin_unlock_irq(&curr->pi_lock);
+
+       /* Unqueue and drop the lock */
+       unqueue_me_pi(q);
+       if (fshared)
+               up_read(fshared);
+       /*
+        * We own it, so we have to replace the pending owner
+        * TID. This must be atomic as we have preserve the
+        * owner died bit here.
+        */
+       ret = get_user(uval, uaddr);
+       while (!ret) {
+               newval = (uval & FUTEX_OWNER_DIED) | newtid;
+               newval |= (uval & FUTEX_WAITER_REQUEUED);
+               curval = futex_atomic_cmpxchg_inatomic(uaddr,
+                                                      uval, newval);
+               if (curval == -EFAULT)
+                       ret = -EFAULT;
+               if (curval == uval)
+                       break;
+               uval = curval;
+       }
+       return ret;
+}
+
+/*
+ * In case we must use restart_block to restart a futex_wait,
+ * we encode in the 'arg3' shared capability
+ */
+#define ARG3_SHARED  1
+
+static long futex_wait_restart(struct restart_block *restart);
+static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
+                     u32 val, ktime_t *abs_time)
 {
        struct task_struct *curr = current;
        DECLARE_WAITQUEUE(wait, curr);
@@ -1010,12 +1395,15 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
        struct futex_q q;
        u32 uval;
        int ret;
+       struct hrtimer_sleeper t, *to = NULL;
+       int rem = 0;
 
        q.pi_state = NULL;
  retry:
-       down_read(&curr->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr, &q.key);
+       ret = get_futex_key(uaddr, fshared, &q.key);
        if (unlikely(ret != 0))
                goto out_release_sem;
 
@@ -1038,8 +1426,8 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
         * a wakeup when *uaddr != val on entry to the syscall.  This is
         * rare, but normal.
         *
-        * We hold the mmap semaphore, so the mapping cannot have changed
-        * since we looked it up in get_futex_key.
+        * for shared futexes, we hold the mmap semaphore, so the mapping
+        * cannot have changed since we looked it up in get_futex_key.
         */
        ret = get_futex_value_locked(&uval, uaddr);
 
@@ -1050,7 +1438,8 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
                 * If we would have faulted, release mmap_sem, fault it in and
                 * start all over again.
                 */
-               up_read(&curr->mm->mmap_sem);
+               if (fshared)
+                       up_read(fshared);
 
                ret = get_user(uval, uaddr);
 
@@ -1062,6 +1451,14 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
        if (uval != val)
                goto out_unlock_release_sem;
 
+       /*
+        * This rt_mutex_waiter structure is prepared here and will
+        * be used only if this task is requeued from a normal futex to
+        * a PI-futex with futex_requeue_pi.
+        */
+       debug_rt_mutex_init_waiter(&q.waiter);
+       q.waiter.task = NULL;
+
        /* Only actually queue if *uaddr contained val.  */
        __queue_me(&q, hb);
 
@@ -1069,7 +1466,8 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
         * Now the futex is queued and we have checked the data, we
         * don't want to hold mmap_sem while we sleep.
         */
-       up_read(&curr->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
 
        /*
         * There might have been scheduling since the queue_me(), as we
@@ -1084,11 +1482,34 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
        __set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&q.waiters, &wait);
        /*
-        * !list_empty() is safe here without any lock.
+        * !plist_node_empty() is safe here without any lock.
         * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
         */
-       if (likely(!list_empty(&q.list)))
-               time = schedule_timeout(time);
+       if (likely(!plist_node_empty(&q.list))) {
+               if (!abs_time)
+                       schedule();
+               else {
+                       to = &t;
+                       hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+                       hrtimer_init_sleeper(&t, current);
+                       t.timer.expires = *abs_time;
+
+                       hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS);
+
+                       /*
+                        * the timer could have already expired, in which
+                        * case current would be flagged for rescheduling.
+                        * Don't bother calling schedule.
+                        */
+                       if (likely(t.task))
+                               schedule();
+
+                       hrtimer_cancel(&t.timer);
+
+                       /* Flag if a timeout occured */
+                       rem = (t.task == NULL);
+               }
+       }
        __set_current_state(TASK_RUNNING);
 
        /*
@@ -1096,62 +1517,203 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
         * we are the only user of it.
         */
 
+       if (q.pi_state) {
+               /*
+                * We were woken but have been requeued on a PI-futex.
+                * We have to complete the lock acquisition by taking
+                * the rtmutex.
+                */
+
+               struct rt_mutex *lock = &q.pi_state->pi_mutex;
+
+               spin_lock(&lock->wait_lock);
+               if (unlikely(q.waiter.task)) {
+                       remove_waiter(lock, &q.waiter);
+               }
+               spin_unlock(&lock->wait_lock);
+
+               if (rem)
+                       ret = -ETIMEDOUT;
+               else
+                       ret = rt_mutex_timed_lock(lock, to, 1);
+
+               if (fshared)
+                       down_read(fshared);
+               spin_lock(q.lock_ptr);
+
+               /*
+                * Got the lock. We might not be the anticipated owner if we
+                * did a lock-steal - fix up the PI-state in that case.
+                */
+               if (!ret && q.pi_state->owner != curr) {
+                       /*
+                        * We MUST play with the futex we were requeued on,
+                        * NOT the current futex.
+                        * We can retrieve it from the key of the pi_state
+                        */
+                       uaddr = q.pi_state->key.uaddr;
+
+                       /* mmap_sem and hash_bucket lock are unlocked at
+                          return of this function */
+                       ret = fixup_pi_state_owner(uaddr, fshared,
+                                                  &q, hb, curr);
+               } else {
+                       /*
+                        * Catch the rare case, where the lock was released
+                        * when we were on the way back before we locked
+                        * the hash bucket.
+                        */
+                       if (ret && q.pi_state->owner == curr) {
+                               if (rt_mutex_trylock(&q.pi_state->pi_mutex))
+                                       ret = 0;
+                       }
+                       /* Unqueue and drop the lock */
+                       unqueue_me_pi(&q);
+                       if (fshared)
+                               up_read(fshared);
+               }
+
+               debug_rt_mutex_free_waiter(&q.waiter);
+
+               return ret;
+       }
+
+       debug_rt_mutex_free_waiter(&q.waiter);
+
        /* If we were woken (and unqueued), we succeeded, whatever. */
        if (!unqueue_me(&q))
                return 0;
-       if (time == 0)
+       if (rem)
                return -ETIMEDOUT;
+
        /*
         * We expect signal_pending(current), but another thread may
         * have handled it for us already.
         */
-       return -EINTR;
+       if (!abs_time)
+               return -ERESTARTSYS;
+       else {
+               struct restart_block *restart;
+               restart = &current_thread_info()->restart_block;
+               restart->fn = futex_wait_restart;
+               restart->arg0 = (unsigned long)uaddr;
+               restart->arg1 = (unsigned long)val;
+               restart->arg2 = (unsigned long)abs_time;
+               restart->arg3 = 0;
+               if (fshared)
+                       restart->arg3 |= ARG3_SHARED;
+               return -ERESTART_RESTARTBLOCK;
+       }
 
  out_unlock_release_sem:
        queue_unlock(&q, hb);
 
  out_release_sem:
-       up_read(&curr->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
        return ret;
 }
 
+
+static long futex_wait_restart(struct restart_block *restart)
+{
+       u32 __user *uaddr = (u32 __user *)restart->arg0;
+       u32 val = (u32)restart->arg1;
+       ktime_t *abs_time = (ktime_t *)restart->arg2;
+       struct rw_semaphore *fshared = NULL;
+
+       restart->fn = do_no_restart_syscall;
+       if (restart->arg3 & ARG3_SHARED)
+               fshared = &current->mm->mmap_sem;
+       return (long)futex_wait(uaddr, fshared, val, abs_time);
+}
+
+
+static void set_pi_futex_owner(struct futex_hash_bucket *hb,
+                              union futex_key *key, struct task_struct *p)
+{
+       struct plist_head *head;
+       struct futex_q *this, *next;
+       struct futex_pi_state *pi_state = NULL;
+       struct rt_mutex *lock;
+
+       /* Search a waiter that should already exists */
+
+       head = &hb->chain;
+
+       plist_for_each_entry_safe(this, next, head, list) {
+               if (match_futex (&this->key, key)) {
+                       pi_state = this->pi_state;
+                       break;
+               }
+       }
+
+       BUG_ON(!pi_state);
+
+       /* set p as pi_state's owner */
+       lock = &pi_state->pi_mutex;
+
+       spin_lock(&lock->wait_lock);
+       spin_lock_irq(&p->pi_lock);
+
+       list_add(&pi_state->list, &p->pi_state_list);
+       pi_state->owner = p;
+
+
+       /* set p as pi_mutex's owner */
+       debug_rt_mutex_proxy_lock(lock, p);
+       WARN_ON(rt_mutex_owner(lock));
+       rt_mutex_set_owner(lock, p, 0);
+       rt_mutex_deadlock_account_lock(lock, p);
+
+       plist_add(&rt_mutex_top_waiter(lock)->pi_list_entry,
+                 &p->pi_waiters);
+       __rt_mutex_adjust_prio(p);
+
+       spin_unlock_irq(&p->pi_lock);
+       spin_unlock(&lock->wait_lock);
+}
+
 /*
  * Userspace tried a 0 -> TID atomic transition of the futex value
  * and failed. The kernel side here does the whole locking operation:
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
-                        long nsec, int trylock)
+static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+                        int detect, ktime_t *time, int trylock)
 {
        struct hrtimer_sleeper timeout, *to = NULL;
        struct task_struct *curr = current;
        struct futex_hash_bucket *hb;
        u32 uval, newval, curval;
        struct futex_q q;
-       int ret, attempt = 0;
+       int ret, lock_held, attempt = 0;
 
        if (refill_pi_state_cache())
                return -ENOMEM;
 
-       if (sec != MAX_SCHEDULE_TIMEOUT) {
+       if (time) {
                to = &timeout;
                hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
                hrtimer_init_sleeper(to, current);
-               to->timer.expires = ktime_set(sec, nsec);
+               to->timer.expires = *time;
        }
 
        q.pi_state = NULL;
  retry:
-       down_read(&curr->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr, &q.key);
+       ret = get_futex_key(uaddr, fshared, &q.key);
        if (unlikely(ret != 0))
                goto out_release_sem;
 
        hb = queue_lock(&q, -1, NULL);
 
  retry_locked:
+       lock_held = 0;
+
        /*
         * To avoid races, we attempt to take the lock here again
         * (by doing a 0 -> TID atomic cmpxchg), while holding all
@@ -1170,7 +1732,16 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
        if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
                if (!detect && 0)
                        force_sig(SIGKILL, current);
-               ret = -EDEADLK;
+               /*
+                * Normally, this check is done in user space.
+                * In case of requeue, the owner may attempt to lock this futex,
+                * even if the ownership has already been given by the previous
+                * waker.
+                * In the usual case, this is a case of deadlock, but not in case
+                * of REQUEUE_PI.
+                */
+               if (!(curval & FUTEX_WAITER_REQUEUED))
+                       ret = -EDEADLK;
                goto out_unlock_release_sem;
        }
 
@@ -1182,7 +1753,18 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
                goto out_unlock_release_sem;
 
        uval = curval;
-       newval = uval | FUTEX_WAITERS;
+       /*
+        * In case of a requeue, check if there already is an owner
+        * If not, just take the futex.
+        */
+       if ((curval & FUTEX_WAITER_REQUEUED) && !(curval & FUTEX_TID_MASK)) {
+               /* set current as futex owner */
+               newval = curval | current->pid;
+               lock_held = 1;
+       } else
+               /* Set the WAITERS flag, so the owner will know it has someone
+                  to wake at next unlock */
+               newval = curval | FUTEX_WAITERS;
 
        pagefault_disable();
        curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
@@ -1193,11 +1775,16 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
        if (unlikely(curval != uval))
                goto retry_locked;
 
+       if (lock_held) {
+               set_pi_futex_owner(hb, &q.key, curr);
+               goto out_unlock_release_sem;
+       }
+
        /*
         * We dont have the lock. Look up the PI state (or create it if
         * we are the first waiter):
         */
-       ret = lookup_pi_state(uval, hb, &q);
+       ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
 
        if (unlikely(ret)) {
                /*
@@ -1239,7 +1826,8 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
         * Now the futex is queued and we have checked the data, we
         * don't want to hold mmap_sem while we sleep.
         */
-       up_read(&curr->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
 
        WARN_ON(!q.pi_state);
        /*
@@ -1253,52 +1841,18 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
                ret = ret ? 0 : -EWOULDBLOCK;
        }
 
-       down_read(&curr->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
        spin_lock(q.lock_ptr);
 
        /*
         * Got the lock. We might not be the anticipated owner if we
         * did a lock-steal - fix up the PI-state in that case.
         */
-       if (!ret && q.pi_state->owner != curr) {
-               u32 newtid = current->pid | FUTEX_WAITERS;
-
-               /* Owner died? */
-               if (q.pi_state->owner != NULL) {
-                       spin_lock_irq(&q.pi_state->owner->pi_lock);
-                       WARN_ON(list_empty(&q.pi_state->list));
-                       list_del_init(&q.pi_state->list);
-                       spin_unlock_irq(&q.pi_state->owner->pi_lock);
-               } else
-                       newtid |= FUTEX_OWNER_DIED;
-
-               q.pi_state->owner = current;
-
-               spin_lock_irq(&current->pi_lock);
-               WARN_ON(!list_empty(&q.pi_state->list));
-               list_add(&q.pi_state->list, &current->pi_state_list);
-               spin_unlock_irq(&current->pi_lock);
-
-               /* Unqueue and drop the lock */
-               unqueue_me_pi(&q, hb);
-               up_read(&curr->mm->mmap_sem);
-               /*
-                * We own it, so we have to replace the pending owner
-                * TID. This must be atomic as we have preserve the
-                * owner died bit here.
-                */
-               ret = get_user(uval, uaddr);
-               while (!ret) {
-                       newval = (uval & FUTEX_OWNER_DIED) | newtid;
-                       curval = futex_atomic_cmpxchg_inatomic(uaddr,
-                                                              uval, newval);
-                       if (curval == -EFAULT)
-                               ret = -EFAULT;
-                       if (curval == uval)
-                               break;
-                       uval = curval;
-               }
-       } else {
+       if (!ret && q.pi_state->owner != curr)
+               /* mmap_sem is unlocked at return of this function */
+               ret = fixup_pi_state_owner(uaddr, fshared, &q, hb, curr);
+       else {
                /*
                 * Catch the rare case, where the lock was released
                 * when we were on the way back before we locked
@@ -1309,8 +1863,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
                                ret = 0;
                }
                /* Unqueue and drop the lock */
-               unqueue_me_pi(&q, hb);
-               up_read(&curr->mm->mmap_sem);
+               unqueue_me_pi(&q);
+               if (fshared)
+                       up_read(fshared);
        }
 
        if (!detect && ret == -EDEADLK && 0)
@@ -1322,7 +1877,8 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
        queue_unlock(&q, hb);
 
  out_release_sem:
-       up_read(&curr->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
        return ret;
 
  uaddr_faulted:
@@ -1333,15 +1889,16 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
         * still holding the mmap_sem.
         */
        if (attempt++) {
-               if (futex_handle_fault((unsigned long)uaddr, attempt)) {
-                       ret = -EFAULT;
+               ret = futex_handle_fault((unsigned long)uaddr, fshared,
+                                        attempt);
+               if (ret)
                        goto out_unlock_release_sem;
-               }
                goto retry_locked;
        }
 
        queue_unlock(&q, hb);
-       up_read(&curr->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
 
        ret = get_user(uval, uaddr);
        if (!ret && (uval != -EFAULT))
@@ -1355,12 +1912,12 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
  * This is the in-kernel slowpath: we look up the PI state (if any),
  * and do the rt-mutex unlock.
  */
-static int futex_unlock_pi(u32 __user *uaddr)
+static int futex_unlock_pi(u32 __user *uaddr, struct rw_semaphore *fshared)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
        u32 uval;
-       struct list_head *head;
+       struct plist_head *head;
        union futex_key key;
        int ret, attempt = 0;
 
@@ -1375,9 +1932,10 @@ retry:
        /*
         * First take all the futex related locks:
         */
-       down_read(&current->mm->mmap_sem);
+       if (fshared)
+               down_read(fshared);
 
-       ret = get_futex_key(uaddr, &key);
+       ret = get_futex_key(uaddr, fshared, &key);
        if (unlikely(ret != 0))
                goto out;
 
@@ -1411,7 +1969,7 @@ retry_locked:
         */
        head = &hb->chain;
 
-       list_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, head, list) {
                if (!match_futex (&this->key, &key))
                        continue;
                ret = wake_futex_pi(uaddr, uval, this);
@@ -1436,7 +1994,8 @@ retry_locked:
 out_unlock:
        spin_unlock(&hb->lock);
 out:
-       up_read(&current->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
 
        return ret;
 
@@ -1448,15 +2007,16 @@ pi_faulted:
         * still holding the mmap_sem.
         */
        if (attempt++) {
-               if (futex_handle_fault((unsigned long)uaddr, attempt)) {
-                       ret = -EFAULT;
+               ret = futex_handle_fault((unsigned long)uaddr, fshared,
+                                        attempt);
+               if (ret)
                        goto out_unlock;
-               }
                goto retry_locked;
        }
 
        spin_unlock(&hb->lock);
-       up_read(&current->mm->mmap_sem);
+       if (fshared)
+               up_read(fshared);
 
        ret = get_user(uval, uaddr);
        if (!ret && (uval != -EFAULT))
@@ -1485,10 +2045,10 @@ static unsigned int futex_poll(struct file *filp,
        poll_wait(filp, &q->waiters, wait);
 
        /*
-        * list_empty() is safe here without any lock.
+        * plist_node_empty() is safe here without any lock.
         * q->lock_ptr != 0 is not safe, because of ordering against wakeup.
         */
-       if (list_empty(&q->list))
+       if (plist_node_empty(&q->list))
                ret = POLLIN | POLLRDNORM;
 
        return ret;
@@ -1508,6 +2068,7 @@ static int futex_fd(u32 __user *uaddr, int signal)
        struct futex_q *q;
        struct file *filp;
        int ret, err;
+       struct rw_semaphore *fshared;
        static unsigned long printk_interval;
 
        if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) {
@@ -1549,11 +2110,12 @@ static int futex_fd(u32 __user *uaddr, int signal)
        }
        q->pi_state = NULL;
 
-       down_read(&current->mm->mmap_sem);
-       err = get_futex_key(uaddr, &q->key);
+       fshared = &current->mm->mmap_sem;
+       down_read(fshared);
+       err = get_futex_key(uaddr, fshared, &q->key);
 
        if (unlikely(err != 0)) {
-               up_read(&current->mm->mmap_sem);
+               up_read(fshared);
                kfree(q);
                goto error;
        }
@@ -1565,7 +2127,7 @@ static int futex_fd(u32 __user *uaddr, int signal)
        filp->private_data = q;
 
        queue_me(q, ret, filp);
-       up_read(&current->mm->mmap_sem);
+       up_read(fshared);
 
        /* Now we map fd to filp, so userspace can access it */
        fd_install(ret, filp);
@@ -1678,6 +2240,8 @@ retry:
                 * userspace.
                 */
                mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
+               /* Also keep the FUTEX_WAITER_REQUEUED flag if set */
+               mval |= (uval & FUTEX_WAITER_REQUEUED);
                nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
 
                if (nval == -EFAULT)
@@ -1692,7 +2256,7 @@ retry:
                 */
                if (!pi) {
                        if (uval & FUTEX_WAITERS)
-                               futex_wake(uaddr, 1);
+                               futex_wake(uaddr, &curr->mm->mmap_sem, 1);
                }
        }
        return 0;
@@ -1748,7 +2312,8 @@ void exit_robust_list(struct task_struct *curr)
                return;
 
        if (pending)
-               handle_futex_death((void __user *)pending + futex_offset, curr, pip);
+               handle_futex_death((void __user *)pending + futex_offset,
+                                  curr, pip);
 
        while (entry != &head->list) {
                /*
@@ -1774,39 +2339,47 @@ void exit_robust_list(struct task_struct *curr)
        }
 }
 
-long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
+long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
                u32 __user *uaddr2, u32 val2, u32 val3)
 {
        int ret;
+       int cmd = op & FUTEX_CMD_MASK;
+       struct rw_semaphore *fshared = NULL;
 
-       switch (op) {
+       if (!(op & FUTEX_PRIVATE_FLAG))
+               fshared = &current->mm->mmap_sem;
+
+       switch (cmd) {
        case FUTEX_WAIT:
-               ret = futex_wait(uaddr, val, timeout);
+               ret = futex_wait(uaddr, fshared, val, timeout);
                break;
        case FUTEX_WAKE:
-               ret = futex_wake(uaddr, val);
+               ret = futex_wake(uaddr, fshared, val);
                break;
        case FUTEX_FD:
                /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */
                ret = futex_fd(uaddr, val);
                break;
        case FUTEX_REQUEUE:
-               ret = futex_requeue(uaddr, uaddr2, val, val2, NULL);
+               ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, NULL);
                break;
        case FUTEX_CMP_REQUEUE:
-               ret = futex_requeue(uaddr, uaddr2, val, val2, &val3);
+               ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3);
                break;
        case FUTEX_WAKE_OP:
-               ret = futex_wake_op(uaddr, uaddr2, val, val2, val3);
+               ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3);
                break;
        case FUTEX_LOCK_PI:
-               ret = futex_lock_pi(uaddr, val, timeout, val2, 0);
+               ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
                break;
        case FUTEX_UNLOCK_PI:
-               ret = futex_unlock_pi(uaddr);
+               ret = futex_unlock_pi(uaddr, fshared);
                break;
        case FUTEX_TRYLOCK_PI:
-               ret = futex_lock_pi(uaddr, 0, timeout, val2, 1);
+               ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
+               break;
+       case FUTEX_CMP_REQUEUE_PI:
+               ret = futex_requeue_pi(uaddr, fshared, uaddr2, val, val2, &val3);
                break;
        default:
                ret = -ENOSYS;
@@ -1819,29 +2392,30 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
                          struct timespec __user *utime, u32 __user *uaddr2,
                          u32 val3)
 {
-       struct timespec t;
-       unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+       struct timespec ts;
+       ktime_t t, *tp = NULL;
        u32 val2 = 0;
+       int cmd = op & FUTEX_CMD_MASK;
 
-       if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
-               if (copy_from_user(&t, utime, sizeof(t)) != 0)
+       if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) {
+               if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
                        return -EFAULT;
-               if (!timespec_valid(&t))
+               if (!timespec_valid(&ts))
                        return -EINVAL;
-               if (op == FUTEX_WAIT)
-                       timeout = timespec_to_jiffies(&t) + 1;
-               else {
-                       timeout = t.tv_sec;
-                       val2 = t.tv_nsec;
-               }
+
+               t = timespec_to_ktime(ts);
+               if (cmd == FUTEX_WAIT)
+                       t = ktime_add(ktime_get(), t);
+               tp = &t;
        }
        /*
-        * requeue parameter in 'utime' if op == FUTEX_REQUEUE.
+        * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE.
         */
-       if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE)
+       if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE
+           || cmd == FUTEX_CMP_REQUEUE_PI)
                val2 = (u32) (unsigned long) utime;
 
-       return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3);
+       return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
 }
 
 static int futexfs_get_sb(struct file_system_type *fs_type,
@@ -1871,7 +2445,7 @@ static int __init init(void)
        }
 
        for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-               INIT_LIST_HEAD(&futex_queues[i].chain);
+               plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
                spin_lock_init(&futex_queues[i].lock);
        }
        return 0;
index 50f24eea6cd02916bd53d0ea09b1b8de668f8823..338a9b489fbc34fc2ca2ceeecd19f44f2889dd21 100644 (file)
@@ -141,24 +141,24 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
                struct compat_timespec __user *utime, u32 __user *uaddr2,
                u32 val3)
 {
-       struct timespec t;
-       unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+       struct timespec ts;
+       ktime_t t, *tp = NULL;
        int val2 = 0;
 
        if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
-               if (get_compat_timespec(&t, utime))
+               if (get_compat_timespec(&ts, utime))
                        return -EFAULT;
-               if (!timespec_valid(&t))
+               if (!timespec_valid(&ts))
                        return -EINVAL;
+
+               t = timespec_to_ktime(ts);
                if (op == FUTEX_WAIT)
-                       timeout = timespec_to_jiffies(&t) + 1;
-               else {
-                       timeout = t.tv_sec;
-                       val2 = t.tv_nsec;
-               }
+                       t = ktime_add(ktime_get(), t);
+               tp = &t;
        }
-       if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE)
+       if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE
+           || op == FUTEX_CMP_REQUEUE_PI)
                val2 = (int) (unsigned long) utime;
 
-       return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3);
+       return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
 }
index 1b3033105b40ed0896cc7658c1cfeb9b8885a73e..23c03f43e1962d6f0dfa4cb8a716080cf671a48c 100644 (file)
@@ -669,6 +669,7 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
 
        return orun;
 }
+EXPORT_SYMBOL_GPL(hrtimer_forward);
 
 /*
  * enqueue_hrtimer - internal function to (re)start a timer
@@ -1410,11 +1411,13 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
        switch (action) {
 
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                init_hrtimers_cpu(cpu);
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &cpu);
                migrate_hrtimers(cpu);
                break;
index aff1f0fabb0df0b462c0d83ea4eb35d0ecc24fe0..e391cbb1f56665e4f751706403d69bd3bd86c471 100644 (file)
@@ -22,7 +22,6 @@
  * handle_bad_irq - handle spurious and unhandled irqs
  * @irq:       the interrupt number
  * @desc:      description of the interrupt
- * @regs:      pointer to a register structure
  *
  * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
  */
@@ -48,7 +47,7 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
  *
  * Controller mappings for all interrupt sources:
  */
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
+struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
        [0 ... NR_IRQS-1] = {
                .status = IRQ_DISABLED,
                .chip = &no_irq_chip,
@@ -180,6 +179,8 @@ fastcall unsigned int __do_IRQ(unsigned int irq)
                if (desc->chip->ack)
                        desc->chip->ack(irq);
                action_ret = handle_IRQ_event(irq, desc->action);
+               if (!noirqdebug)
+                       note_interrupt(irq, desc, action_ret);
                desc->chip->end(irq);
                return 1;
        }
index 5597c157442a19a5e5bbe7de068d86c261e98951..203a518b6f1437d134c115ce7d43e1e04e1d5c25 100644 (file)
@@ -317,10 +317,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        }
 
        *p = new;
-#if defined(CONFIG_IRQ_PER_CPU)
-       if (new->flags & IRQF_PERCPU)
-               desc->status |= IRQ_PER_CPU;
-#endif
+
        /* Exclude IRQ from balancing */
        if (new->flags & IRQF_NOBALANCING)
                desc->status |= IRQ_NO_BALANCING;
@@ -328,6 +325,11 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        if (!shared) {
                irq_chip_set_defaults(desc->chip);
 
+#if defined(CONFIG_IRQ_PER_CPU)
+               if (new->flags & IRQF_PERCPU)
+                       desc->status |= IRQ_PER_CPU;
+#endif
+
                /* Setup the type (level, edge polarity) if configured: */
                if (new->flags & IRQF_TRIGGER_MASK) {
                        if (desc->chip && desc->chip->set_type)
index 2db91eb54ad8bb539b2dccdcb059d6872c2191a4..ddde0ef9ccdcbb4dbd8834accc5f0264deee8403 100644 (file)
@@ -66,12 +66,19 @@ static int name_unique(unsigned int irq, struct irqaction *new_action)
 {
        struct irq_desc *desc = irq_desc + irq;
        struct irqaction *action;
+       unsigned long flags;
+       int ret = 1;
 
-       for (action = desc->action ; action; action = action->next)
+       spin_lock_irqsave(&desc->lock, flags);
+       for (action = desc->action ; action; action = action->next) {
                if ((action != new_action) && action->name &&
-                               !strcmp(new_action->name, action->name))
-                       return 0;
-       return 1;
+                               !strcmp(new_action->name, action->name)) {
+                       ret = 0;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&desc->lock, flags);
+       return ret;
 }
 
 void register_handler_proc(unsigned int irq, struct irqaction *action)
index 9d8c79b48823fdfb44d27fe3a3bf1c7adc9cdbc7..b0d81aae472ff44e61d3670f81112d4cd2f54ac9 100644 (file)
@@ -146,7 +146,9 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
 
        if (unlikely(irqfixup)) {
                /* Don't punish working computers */
-               if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
+               if ((irqfixup == 2 && ((irq == 0) ||
+                               (desc->action->flags & IRQF_IRQPOLL))) ||
+                               action_ret == IRQ_NONE) {
                        int ok = misrouted_irq(irq);
                        if (action_ret == IRQ_NONE)
                                desc->irqs_unhandled -= ok;
index 307c6a632ef6baa7ff0cec46273293d4cc84afc6..3205e8e114fa361eff4a1698c9a3ec2bbf4e730f 100644 (file)
@@ -7,7 +7,6 @@
 /* These are all the functions necessary to implement itimers */
 
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/syscalls.h>
 #include <linux/time.h>
@@ -138,60 +137,12 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
        return HRTIMER_NORESTART;
 }
 
-/*
- * We do not care about correctness. We just sanitize the values so
- * the ktime_t operations which expect normalized values do not
- * break. This converts negative values to long timeouts similar to
- * the code in kernel versions < 2.6.16
- *
- * Print a limited number of warning messages when an invalid timeval
- * is detected.
- */
-static void fixup_timeval(struct timeval *tv, int interval)
-{
-       static int warnlimit = 10;
-       unsigned long tmp;
-
-       if (warnlimit > 0) {
-               warnlimit--;
-               printk(KERN_WARNING
-                      "setitimer: %s (pid = %d) provided "
-                      "invalid timeval %s: tv_sec = %ld tv_usec = %ld\n",
-                      current->comm, current->pid,
-                      interval ? "it_interval" : "it_value",
-                      tv->tv_sec, (long) tv->tv_usec);
-       }
-
-       tmp = tv->tv_usec;
-       if (tmp >= USEC_PER_SEC) {
-               tv->tv_usec = tmp % USEC_PER_SEC;
-               tv->tv_sec += tmp / USEC_PER_SEC;
-       }
-
-       tmp = tv->tv_sec;
-       if (tmp > LONG_MAX)
-               tv->tv_sec = LONG_MAX;
-}
-
 /*
  * Returns true if the timeval is in canonical form
  */
 #define timeval_valid(t) \
        (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
 
-/*
- * Check for invalid timevals, sanitize them and print a limited
- * number of warnings.
- */
-static void check_itimerval(struct itimerval *value) {
-
-       if (unlikely(!timeval_valid(&value->it_value)))
-               fixup_timeval(&value->it_value, 0);
-
-       if (unlikely(!timeval_valid(&value->it_interval)))
-               fixup_timeval(&value->it_interval, 1);
-}
-
 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 {
        struct task_struct *tsk = current;
@@ -201,15 +152,10 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 
        /*
         * Validate the timevals in value.
-        *
-        * Note: Although the spec requires that invalid values shall
-        * return -EINVAL, we just fixup the value and print a limited
-        * number of warnings in order not to break users of this
-        * historical misfeature.
-        *
-        * Scheduled for replacement in March 2007
         */
-       check_itimerval(value);
+       if (!timeval_valid(&value->it_value) ||
+           !timeval_valid(&value->it_interval))
+               return -EINVAL;
 
        switch (which) {
        case ITIMER_REAL:
index 5a0de8409739588a0710cb46f204d8cb262f77a9..f1bda23140b2a60d0be17fade305d3ec3afae431 100644 (file)
@@ -214,8 +214,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
                        symbol_end = (unsigned long)_etext;
        }
 
-       *symbolsize = symbol_end - symbol_start;
-       *offset = addr - symbol_start;
+       if (symbolsize)
+               *symbolsize = symbol_end - symbol_start;
+       if (offset)
+               *offset = addr - symbol_start;
 
        return low;
 }
@@ -267,6 +269,42 @@ const char *kallsyms_lookup(unsigned long addr,
        return NULL;
 }
 
+int lookup_symbol_name(unsigned long addr, char *symname)
+{
+       symname[0] = '\0';
+       symname[KSYM_NAME_LEN] = '\0';
+
+       if (is_ksym_addr(addr)) {
+               unsigned long pos;
+
+               pos = get_symbol_pos(addr, NULL, NULL);
+               /* Grab name */
+               kallsyms_expand_symbol(get_symbol_offset(pos), symname);
+               return 0;
+       }
+       /* see if it's in a module */
+       return lookup_module_symbol_name(addr, symname);
+}
+
+int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
+                       unsigned long *offset, char *modname, char *name)
+{
+       name[0] = '\0';
+       name[KSYM_NAME_LEN] = '\0';
+
+       if (is_ksym_addr(addr)) {
+               unsigned long pos;
+
+               pos = get_symbol_pos(addr, size, offset);
+               /* Grab name */
+               kallsyms_expand_symbol(get_symbol_offset(pos), name);
+               modname[0] = '\0';
+               return 0;
+       }
+       /* see if it's in a module */
+       return lookup_module_symbol_attrs(addr, size, offset, modname, name);
+}
+
 /* Look up a kernel symbol and return it in a text buffer. */
 int sprint_symbol(char *buffer, unsigned long address)
 {
@@ -301,25 +339,20 @@ void __print_symbol(const char *fmt, unsigned long address)
 struct kallsym_iter
 {
        loff_t pos;
-       struct module *owner;
        unsigned long value;
        unsigned int nameoff; /* If iterating in core kernel symbols */
        char type;
        char name[KSYM_NAME_LEN+1];
+       char module_name[MODULE_NAME_LEN + 1];
+       int exported;
 };
 
 static int get_ksymbol_mod(struct kallsym_iter *iter)
 {
-       iter->owner = module_get_kallsym(iter->pos - kallsyms_num_syms,
-                                        &iter->value, &iter->type,
-                                        iter->name, sizeof(iter->name));
-       if (iter->owner == NULL)
+       if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
+                               &iter->type, iter->name, iter->module_name,
+                               &iter->exported) < 0)
                return 0;
-
-       /* Label it "global" if it is exported, "local" if not exported. */
-       iter->type = is_exported(iter->name, iter->owner)
-               ? toupper(iter->type) : tolower(iter->type);
-
        return 1;
 }
 
@@ -328,7 +361,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
 {
        unsigned off = iter->nameoff;
 
-       iter->owner = NULL;
+       iter->module_name[0] = '\0';
        iter->value = kallsyms_addresses[iter->pos];
 
        iter->type = kallsyms_get_symbol_type(off);
@@ -392,12 +425,17 @@ static int s_show(struct seq_file *m, void *p)
        if (!iter->name[0])
                return 0;
 
-       if (iter->owner)
+       if (iter->module_name[0]) {
+               char type;
+
+               /* Label it "global" if it is exported,
+                * "local" if not exported. */
+               type = iter->exported ? toupper(iter->type) :
+                                       tolower(iter->type);
                seq_printf(m, "%0*lx %c %s\t[%s]\n",
                           (int)(2*sizeof(void*)),
-                          iter->value, iter->type, iter->name,
-                          module_name(iter->owner));
-       else
+                          iter->value, type, iter->name, iter->module_name);
+       } else
                seq_printf(m, "%0*lx %c %s\n",
                           (int)(2*sizeof(void*)),
                           iter->value, iter->type, iter->name);
@@ -432,18 +470,11 @@ static int kallsyms_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static int kallsyms_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       kfree(m->private);
-       return seq_release(inode, file);
-}
-
 static const struct file_operations kallsyms_operations = {
        .open = kallsyms_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = kallsyms_release,
+       .release = seq_release_private,
 };
 
 static int __init kallsyms_init(void)
index 2a59c8a01ae0010da5ef5b80b39fad2ec1da14ae..25db14b89e82c529fcb217e311fbebf66c440c60 100644 (file)
@@ -1118,8 +1118,8 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
        memset(&prstatus, 0, sizeof(prstatus));
        prstatus.pr_pid = current->pid;
        elf_core_copy_regs(&prstatus.pr_reg, regs);
-       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
-                               sizeof(prstatus));
+       buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
+                             &prstatus, sizeof(prstatus));
        final_note(buf);
 }
 
index 796276141e51902bd466b1f5b81b5220c109ca4a..4d32eb077179a2babd3f49b9f31631d4c6e27bb7 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/kmod.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/mnt_namespace.h>
 #include <linux/completion.h>
@@ -136,7 +135,6 @@ static int ____call_usermodehelper(void *data)
 
        /* Unblock all signals and set the session keyring. */
        new_session = key_get(sub_info->ring);
-       flush_signals(current);
        spin_lock_irq(&current->sighand->siglock);
        old_session = __install_session_keyring(current, new_session);
        flush_signal_handlers(current, 1);
@@ -166,6 +164,12 @@ static int ____call_usermodehelper(void *data)
        /* We can run anywhere, unlike our parent keventd(). */
        set_cpus_allowed(current, CPU_MASK_ALL);
 
+       /*
+        * Our parent is keventd, which runs with elevated scheduling priority.
+        * Avoid propagating that into the userspace child.
+        */
+       set_user_nice(current, 0);
+
        retval = -EPERM;
        if (current->fs->root)
                retval = kernel_execve(sub_info->path,
@@ -181,14 +185,9 @@ static int wait_for_helper(void *data)
 {
        struct subprocess_info *sub_info = data;
        pid_t pid;
-       struct k_sigaction sa;
 
        /* Install a handler: if SIGCLD isn't handled sys_wait4 won't
         * populate the status, but will return -ECHILD. */
-       sa.sa.sa_handler = SIG_IGN;
-       sa.sa.sa_flags = 0;
-       siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
-       do_sigaction(SIGCHLD, &sa, NULL);
        allow_signal(SIGCHLD);
 
        pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
index d25a9ada3f8eb57c8b6ab2ac43e7123fb49ffa9f..9e47d8c493f3a7638d06892b2835ad87c859f7bf 100644 (file)
 #include <linux/hash.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/stddef.h>
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/kallsyms.h>
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
+#include <linux/kdebug.h>
+
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
-#include <asm/kdebug.h>
+#include <asm/uaccess.h>
 
 #define KPROBE_HASH_BITS 6
 #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
@@ -63,6 +66,9 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 static atomic_t kprobe_count;
 
+/* NOTE: change this value only with kprobe_mutex held */
+static bool kprobe_enabled;
+
 DEFINE_MUTEX(kprobe_mutex);            /* Protects kprobe_table */
 DEFINE_SPINLOCK(kretprobe_lock);       /* Protects kretprobe_inst_table */
 static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
@@ -132,9 +138,8 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
 
-      retry:
-       hlist_for_each(pos, &kprobe_insn_pages) {
-               kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
+ retry:
+       hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) {
                if (kip->nused < INSNS_PER_PAGE) {
                        int i;
                        for (i = 0; i < INSNS_PER_PAGE; i++) {
@@ -155,9 +160,8 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
        }
        /* All out of space.  Need to allocate a new page. Use slot 0. */
        kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
-       if (!kip) {
+       if (!kip)
                return NULL;
-       }
 
        /*
         * Use module_alloc so this page is within +/- 2GB of where the
@@ -213,9 +217,8 @@ static int __kprobes collect_garbage_slots(void)
        if (check_safety() != 0)
                return -EAGAIN;
 
-       hlist_for_each_safe(pos, next, &kprobe_insn_pages) {
+       hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) {
                int i;
-               kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
                if (kip->ngarbage == 0)
                        continue;
                kip->ngarbage = 0;      /* we will collect all garbages */
@@ -234,8 +237,7 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
 
-       hlist_for_each(pos, &kprobe_insn_pages) {
-               kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
+       hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) {
                if (kip->insns <= slot &&
                    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
                        int i = (slot - kip->insns) / MAX_INSN_SIZE;
@@ -248,9 +250,9 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
                        break;
                }
        }
-       if (dirty && (++kprobe_garbage_slots > INSNS_PER_PAGE)) {
+
+       if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)
                collect_garbage_slots();
-       }
 }
 #endif
 
@@ -316,7 +318,6 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
                        reset_kprobe_instance();
                }
        }
-       return;
 }
 
 static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
@@ -361,46 +362,6 @@ void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
        return;
 }
 
-/* Called with kretprobe_lock held */
-struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
-{
-       struct hlist_node *node;
-       struct kretprobe_instance *ri;
-       hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
-               return ri;
-       return NULL;
-}
-
-/* Called with kretprobe_lock held */
-static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
-                                                             *rp)
-{
-       struct hlist_node *node;
-       struct kretprobe_instance *ri;
-       hlist_for_each_entry(ri, node, &rp->used_instances, uflist)
-               return ri;
-       return NULL;
-}
-
-/* Called with kretprobe_lock held */
-void __kprobes add_rp_inst(struct kretprobe_instance *ri)
-{
-       /*
-        * Remove rp inst off the free list -
-        * Add it back when probed function returns
-        */
-       hlist_del(&ri->uflist);
-
-       /* Add rp inst onto table */
-       INIT_HLIST_NODE(&ri->hlist);
-       hlist_add_head(&ri->hlist,
-                       &kretprobe_inst_table[hash_ptr(ri->task, KPROBE_HASH_BITS)]);
-
-       /* Also add this rp inst to the used list. */
-       INIT_HLIST_NODE(&ri->uflist);
-       hlist_add_head(&ri->uflist, &ri->rp->used_instances);
-}
-
 /* Called with kretprobe_lock held */
 void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
                                struct hlist_head *head)
@@ -454,7 +415,9 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
 static inline void free_rp_inst(struct kretprobe *rp)
 {
        struct kretprobe_instance *ri;
-       while ((ri = get_free_rp_inst(rp)) != NULL) {
+       struct hlist_node *pos, *next;
+
+       hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) {
                hlist_del(&ri->uflist);
                kfree(ri);
        }
@@ -535,8 +498,8 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
 
 static int __kprobes in_kprobes_functions(unsigned long addr)
 {
-       if (addr >= (unsigned long)__kprobes_text_start
-               && addr < (unsigned long)__kprobes_text_end)
+       if (addr >= (unsigned long)__kprobes_text_start &&
+           addr < (unsigned long)__kprobes_text_end)
                return -EINVAL;
        return 0;
 }
@@ -563,19 +526,24 @@ static int __kprobes __register_kprobe(struct kprobe *p,
                return -EINVAL;
        p->addr = (kprobe_opcode_t *)(((char *)p->addr)+ p->offset);
 
-       if ((!kernel_text_address((unsigned long) p->addr)) ||
-               in_kprobes_functions((unsigned long) p->addr))
+       if (!kernel_text_address((unsigned long) p->addr) ||
+           in_kprobes_functions((unsigned long) p->addr))
                return -EINVAL;
 
        p->mod_refcounted = 0;
-       /* Check are we probing a module */
-       if ((probed_mod = module_text_address((unsigned long) p->addr))) {
+
+       /*
+        * Check if are we probing a module.
+        */
+       probed_mod = module_text_address((unsigned long) p->addr);
+       if (probed_mod) {
                struct module *calling_mod = module_text_address(called_from);
-               /* We must allow modules to probe themself and
-                * in this case avoid incrementing the module refcount,
-                * so as to allow unloading of self probing modules.
+               /*
+                * We must allow modules to probe themself and in this case
+                * avoid incrementing the module refcount, so as to allow
+                * unloading of self probing modules.
                 */
-               if (calling_mod && (calling_mod != probed_mod)) {
+               if (calling_mod && calling_mod != probed_mod) {
                        if (unlikely(!try_module_get(probed_mod)))
                                return -EINVAL;
                        p->mod_refcounted = 1;
@@ -593,19 +561,21 @@ static int __kprobes __register_kprobe(struct kprobe *p,
                goto out;
        }
 
-       if ((ret = arch_prepare_kprobe(p)) != 0)
+       ret = arch_prepare_kprobe(p);
+       if (ret)
                goto out;
 
        INIT_HLIST_NODE(&p->hlist);
        hlist_add_head_rcu(&p->hlist,
                       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
 
-       if (atomic_add_return(1, &kprobe_count) == \
+       if (kprobe_enabled) {
+               if (atomic_add_return(1, &kprobe_count) == \
                                (ARCH_INACTIVE_KPROBE_COUNT + 1))
-               register_page_fault_notifier(&kprobe_page_fault_nb);
-
-       arch_arm_kprobe(p);
+                       register_page_fault_notifier(&kprobe_page_fault_nb);
 
+               arch_arm_kprobe(p);
+       }
 out:
        mutex_unlock(&kprobe_mutex);
 
@@ -616,8 +586,7 @@ out:
 
 int __kprobes register_kprobe(struct kprobe *p)
 {
-       return __register_kprobe(p,
-               (unsigned long)__builtin_return_address(0));
+       return __register_kprobe(p, (unsigned long)__builtin_return_address(0));
 }
 
 void __kprobes unregister_kprobe(struct kprobe *p)
@@ -641,11 +610,16 @@ void __kprobes unregister_kprobe(struct kprobe *p)
                return;
        }
 valid_p:
-       if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
-               (p->list.next == &old_p->list) &&
-               (p->list.prev == &old_p->list))) {
-               /* Only probe on the hash list */
-               arch_disarm_kprobe(p);
+       if (old_p == p ||
+           (old_p->pre_handler == aggr_pre_handler &&
+            p->list.next == &old_p->list && p->list.prev == &old_p->list)) {
+               /*
+                * Only probe on the hash list. Disarm only if kprobes are
+                * enabled - otherwise, the breakpoint would already have
+                * been removed. We save on flushing icache.
+                */
+               if (kprobe_enabled)
+                       arch_disarm_kprobe(p);
                hlist_del_rcu(&old_p->hlist);
                cleanup_p = 1;
        } else {
@@ -656,9 +630,11 @@ valid_p:
        mutex_unlock(&kprobe_mutex);
 
        synchronize_sched();
-       if (p->mod_refcounted &&
-           (mod = module_text_address((unsigned long)p->addr)))
-               module_put(mod);
+       if (p->mod_refcounted) {
+               mod = module_text_address((unsigned long)p->addr);
+               if (mod)
+                       module_put(mod);
+       }
 
        if (cleanup_p) {
                if (p != old_p) {
@@ -729,7 +705,21 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
 
        /*TODO: consider to only swap the RA after the last pre_handler fired */
        spin_lock_irqsave(&kretprobe_lock, flags);
-       arch_prepare_kretprobe(rp, regs);
+       if (!hlist_empty(&rp->free_instances)) {
+               struct kretprobe_instance *ri;
+
+               ri = hlist_entry(rp->free_instances.first,
+                                struct kretprobe_instance, uflist);
+               ri->rp = rp;
+               ri->task = current;
+               arch_prepare_kretprobe(ri, regs);
+
+               /* XXX(hch): why is there no hlist_move_head? */
+               hlist_del(&ri->uflist);
+               hlist_add_head(&ri->uflist, &ri->rp->used_instances);
+               hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task));
+       } else
+               rp->nmissed++;
        spin_unlock_irqrestore(&kretprobe_lock, flags);
        return 0;
 }
@@ -792,11 +782,13 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp)
 {
        unsigned long flags;
        struct kretprobe_instance *ri;
+       struct hlist_node *pos, *next;
 
        unregister_kprobe(&rp->kp);
+
        /* No race here */
        spin_lock_irqsave(&kretprobe_lock, flags);
-       while ((ri = get_used_rp_inst(rp)) != NULL) {
+       hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
                ri->rp = NULL;
                hlist_del(&ri->uflist);
        }
@@ -816,6 +808,9 @@ static int __init init_kprobes(void)
        }
        atomic_set(&kprobe_count, 0);
 
+       /* By default, kprobes are enabled */
+       kprobe_enabled = true;
+
        err = arch_init_kprobes();
        if (!err)
                err = register_die_notifier(&kprobe_exceptions_nb);
@@ -825,7 +820,7 @@ static int __init init_kprobes(void)
 
 #ifdef CONFIG_DEBUG_FS
 static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
-               const char *sym, int offset,char *modname)
+               const char *sym, int offset,char *modname)
 {
        char *kprobe_type;
 
@@ -867,13 +862,13 @@ static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
        struct kprobe *p, *kp;
        const char *sym = NULL;
        unsigned int i = *(loff_t *) v;
-       unsigned long size, offset = 0;
+       unsigned long offset = 0;
        char *modname, namebuf[128];
 
        head = &kprobe_table[i];
        preempt_disable();
        hlist_for_each_entry_rcu(p, node, head, hlist) {
-               sym = kallsyms_lookup((unsigned long)p->addr, &size,
+               sym = kallsyms_lookup((unsigned long)p->addr, NULL,
                                        &offset, &modname, namebuf);
                if (p->pre_handler == aggr_pre_handler) {
                        list_for_each_entry_rcu(kp, &p->list, list)
@@ -904,21 +899,149 @@ static struct file_operations debugfs_kprobes_operations = {
        .release        = seq_release,
 };
 
+static void __kprobes enable_all_kprobes(void)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct kprobe *p;
+       unsigned int i;
+
+       mutex_lock(&kprobe_mutex);
+
+       /* If kprobes are already enabled, just return */
+       if (kprobe_enabled)
+               goto already_enabled;
+
+       /*
+        * Re-register the page fault notifier only if there are any
+        * active probes at the time of enabling kprobes globally
+        */
+       if (atomic_read(&kprobe_count) > ARCH_INACTIVE_KPROBE_COUNT)
+               register_page_fault_notifier(&kprobe_page_fault_nb);
+
+       for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
+               head = &kprobe_table[i];
+               hlist_for_each_entry_rcu(p, node, head, hlist)
+                       arch_arm_kprobe(p);
+       }
+
+       kprobe_enabled = true;
+       printk(KERN_INFO "Kprobes globally enabled\n");
+
+already_enabled:
+       mutex_unlock(&kprobe_mutex);
+       return;
+}
+
+static void __kprobes disable_all_kprobes(void)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct kprobe *p;
+       unsigned int i;
+
+       mutex_lock(&kprobe_mutex);
+
+       /* If kprobes are already disabled, just return */
+       if (!kprobe_enabled)
+               goto already_disabled;
+
+       kprobe_enabled = false;
+       printk(KERN_INFO "Kprobes globally disabled\n");
+       for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
+               head = &kprobe_table[i];
+               hlist_for_each_entry_rcu(p, node, head, hlist) {
+                       if (!arch_trampoline_kprobe(p))
+                               arch_disarm_kprobe(p);
+               }
+       }
+
+       mutex_unlock(&kprobe_mutex);
+       /* Allow all currently running kprobes to complete */
+       synchronize_sched();
+
+       mutex_lock(&kprobe_mutex);
+       /* Unconditionally unregister the page_fault notifier */
+       unregister_page_fault_notifier(&kprobe_page_fault_nb);
+
+already_disabled:
+       mutex_unlock(&kprobe_mutex);
+       return;
+}
+
+/*
+ * XXX: The debugfs bool file interface doesn't allow for callbacks
+ * when the bool state is switched. We can reuse that facility when
+ * available
+ */
+static ssize_t read_enabled_file_bool(struct file *file,
+              char __user *user_buf, size_t count, loff_t *ppos)
+{
+       char buf[3];
+
+       if (kprobe_enabled)
+               buf[0] = '1';
+       else
+               buf[0] = '0';
+       buf[1] = '\n';
+       buf[2] = 0x00;
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t write_enabled_file_bool(struct file *file,
+              const char __user *user_buf, size_t count, loff_t *ppos)
+{
+       char buf[32];
+       int buf_size;
+
+       buf_size = min(count, (sizeof(buf)-1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       switch (buf[0]) {
+       case 'y':
+       case 'Y':
+       case '1':
+               enable_all_kprobes();
+               break;
+       case 'n':
+       case 'N':
+       case '0':
+               disable_all_kprobes();
+               break;
+       }
+
+       return count;
+}
+
+static struct file_operations fops_kp = {
+       .read =         read_enabled_file_bool,
+       .write =        write_enabled_file_bool,
+};
+
 static int __kprobes debugfs_kprobe_init(void)
 {
        struct dentry *dir, *file;
+       unsigned int value = 1;
 
        dir = debugfs_create_dir("kprobes", NULL);
        if (!dir)
                return -ENOMEM;
 
-       file = debugfs_create_file("list", 0444, dir , 0 ,
+       file = debugfs_create_file("list", 0444, dir, NULL,
                                &debugfs_kprobes_operations);
        if (!file) {
                debugfs_remove(dir);
                return -ENOMEM;
        }
 
+       file = debugfs_create_file("enabled", 0600, dir,
+                                       &value, &fops_kp);
+       if (!file) {
+               debugfs_remove(dir);
+               return -ENOMEM;
+       }
+
        return 0;
 }
 
index 87c50ccd1d4e93850373d23c8d96b46a93cc0688..df8a8e8f6ca4fbb55d2da6770f9040d31de9cf0b 100644 (file)
@@ -1,7 +1,7 @@
 /* Kernel thread helper functions.
  *   Copyright (C) 2004 IBM Corporation, Rusty Russell.
  *
- * Creation is done via keventd, so that we get a clean environment
+ * Creation is done via kthreadd, so that we get a clean environment
  * even if we're invoked from userspace (think modprobe, hotplug cpu,
  * etc.).
  */
 #include <linux/mutex.h>
 #include <asm/semaphore.h>
 
-/*
- * We dont want to execute off keventd since it might
- * hold a semaphore our callers hold too:
- */
-static struct workqueue_struct *helper_wq;
+static DEFINE_SPINLOCK(kthread_create_lock);
+static LIST_HEAD(kthread_create_list);
+struct task_struct *kthreadd_task;
 
 struct kthread_create_info
 {
-       /* Information passed to kthread() from keventd. */
+       /* Information passed to kthread() from kthreadd. */
        int (*threadfn)(void *data);
        void *data;
        struct completion started;
 
-       /* Result passed back to kthread_create() from keventd. */
+       /* Result passed back to kthread_create() from kthreadd. */
        struct task_struct *result;
        struct completion done;
 
-       struct work_struct work;
+       struct list_head list;
 };
 
 struct kthread_stop_info
@@ -60,42 +58,17 @@ int kthread_should_stop(void)
 }
 EXPORT_SYMBOL(kthread_should_stop);
 
-static void kthread_exit_files(void)
-{
-       struct fs_struct *fs;
-       struct task_struct *tsk = current;
-
-       exit_fs(tsk);           /* current->fs->count--; */
-       fs = init_task.fs;
-       tsk->fs = fs;
-       atomic_inc(&fs->count);
-       exit_files(tsk);
-       current->files = init_task.files;
-       atomic_inc(&tsk->files->count);
-}
-
 static int kthread(void *_create)
 {
        struct kthread_create_info *create = _create;
        int (*threadfn)(void *data);
        void *data;
-       sigset_t blocked;
        int ret = -EINTR;
 
-       kthread_exit_files();
-
-       /* Copy data: it's on keventd's stack */
+       /* Copy data: it's on kthread's stack */
        threadfn = create->threadfn;
        data = create->data;
 
-       /* Block and flush all signals (in case we're not from keventd). */
-       sigfillset(&blocked);
-       sigprocmask(SIG_BLOCK, &blocked, NULL);
-       flush_signals(current);
-
-       /* By default we can run anywhere, unlike keventd. */
-       set_cpus_allowed(current, CPU_MASK_ALL);
-
        /* OK, tell user we're spawned, wait for stop or wakeup */
        __set_current_state(TASK_INTERRUPTIBLE);
        complete(&create->started);
@@ -112,11 +85,8 @@ static int kthread(void *_create)
        return 0;
 }
 
-/* We are keventd: create a thread. */
-static void keventd_create_kthread(struct work_struct *work)
+static void create_kthread(struct kthread_create_info *create)
 {
-       struct kthread_create_info *create =
-               container_of(work, struct kthread_create_info, work);
        int pid;
 
        /* We want our own signal handler (we take no signals by default). */
@@ -162,17 +132,14 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
        create.data = data;
        init_completion(&create.started);
        init_completion(&create.done);
-       INIT_WORK(&create.work, keventd_create_kthread);
-
-       /*
-        * The workqueue needs to start up first:
-        */
-       if (!helper_wq)
-               create.work.func(&create.work);
-       else {
-               queue_work(helper_wq, &create.work);
-               wait_for_completion(&create.done);
-       }
+
+       spin_lock(&kthread_create_lock);
+       list_add_tail(&create.list, &kthread_create_list);
+       wake_up_process(kthreadd_task);
+       spin_unlock(&kthread_create_lock);
+
+       wait_for_completion(&create.done);
+
        if (!IS_ERR(create.result)) {
                va_list args;
                va_start(args, namefmt);
@@ -180,7 +147,6 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
                          namefmt, args);
                va_end(args);
        }
-
        return create.result;
 }
 EXPORT_SYMBOL(kthread_create);
@@ -245,12 +211,47 @@ int kthread_stop(struct task_struct *k)
 }
 EXPORT_SYMBOL(kthread_stop);
 
-static __init int helper_init(void)
+
+static __init void kthreadd_setup(void)
 {
-       helper_wq = create_singlethread_workqueue("kthread");
-       BUG_ON(!helper_wq);
+       struct task_struct *tsk = current;
 
-       return 0;
+       set_task_comm(tsk, "kthreadd");
+
+       ignore_signals(tsk);
+
+       set_user_nice(tsk, -5);
+       set_cpus_allowed(tsk, CPU_MASK_ALL);
 }
 
-core_initcall(helper_init);
+int kthreadd(void *unused)
+{
+       /* Setup a clean context for our children to inherit. */
+       kthreadd_setup();
+
+       current->flags |= PF_NOFREEZE;
+
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (list_empty(&kthread_create_list))
+                       schedule();
+               __set_current_state(TASK_RUNNING);
+
+               spin_lock(&kthread_create_lock);
+               while (!list_empty(&kthread_create_list)) {
+                       struct kthread_create_info *create;
+
+                       create = list_entry(kthread_create_list.next,
+                                           struct kthread_create_info, list);
+                       list_del_init(&create->list);
+                       spin_unlock(&kthread_create_lock);
+
+                       create_kthread(create);
+
+                       spin_lock(&kthread_create_lock);
+               }
+               spin_unlock(&kthread_create_lock);
+       }
+
+       return 0;
+}
index 7065a687ac546020de4d53883f188f9702e036fd..1a5ff2211d8898076c601d4f9c639bfe34f5927c 100644 (file)
@@ -257,9 +257,8 @@ static int save_trace(struct stack_trace *trace)
        trace->entries = stack_trace + nr_stack_trace_entries;
 
        trace->skip = 3;
-       trace->all_contexts = 0;
 
-       save_stack_trace(trace, NULL);
+       save_stack_trace(trace);
 
        trace->max_entries = trace->nr_entries;
 
@@ -341,10 +340,7 @@ static const char *usage_str[] =
 
 const char * __get_key_name(struct lockdep_subclass_key *key, char *str)
 {
-       unsigned long offs, size;
-       char *modname;
-
-       return kallsyms_lookup((unsigned long)key, &size, &offs, &modname, str);
+       return kallsyms_lookup((unsigned long)key, NULL, NULL, NULL, str);
 }
 
 void
@@ -1313,8 +1309,9 @@ out_unlock_set:
 
 /*
  * Look up a dependency chain. If the key is not present yet then
- * add it and return 0 - in this case the new dependency chain is
- * validated. If the key is already hashed, return 1.
+ * add it and return 1 - in this case the new dependency chain is
+ * validated. If the key is already hashed, return 0.
+ * (On return with 1 graph_lock is held.)
  */
 static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class)
 {
@@ -1577,7 +1574,7 @@ valid_state(struct task_struct *curr, struct held_lock *this,
  * Mark a lock with a usage bit, and validate the state transition:
  */
 static int mark_lock(struct task_struct *curr, struct held_lock *this,
-                    enum lock_usage_bit new_bit, unsigned long ip)
+                    enum lock_usage_bit new_bit)
 {
        unsigned int new_mask = 1 << new_bit, ret = 1;
 
@@ -1600,14 +1597,6 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
 
        this->class->usage_mask |= new_mask;
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-       if (new_bit == LOCK_ENABLED_HARDIRQS ||
-                       new_bit == LOCK_ENABLED_HARDIRQS_READ)
-               ip = curr->hardirq_enable_ip;
-       else if (new_bit == LOCK_ENABLED_SOFTIRQS ||
-                       new_bit == LOCK_ENABLED_SOFTIRQS_READ)
-               ip = curr->softirq_enable_ip;
-#endif
        if (!save_trace(this->class->usage_traces + new_bit))
                return 0;
 
@@ -1806,7 +1795,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
  * Mark all held locks with a usage bit:
  */
 static int
-mark_held_locks(struct task_struct *curr, int hardirq, unsigned long ip)
+mark_held_locks(struct task_struct *curr, int hardirq)
 {
        enum lock_usage_bit usage_bit;
        struct held_lock *hlock;
@@ -1826,7 +1815,7 @@ mark_held_locks(struct task_struct *curr, int hardirq, unsigned long ip)
                        else
                                usage_bit = LOCK_ENABLED_SOFTIRQS;
                }
-               if (!mark_lock(curr, hlock, usage_bit, ip))
+               if (!mark_lock(curr, hlock, usage_bit))
                        return 0;
        }
 
@@ -1879,7 +1868,7 @@ void trace_hardirqs_on(void)
         * We are going to turn hardirqs on, so set the
         * usage bit for all held locks:
         */
-       if (!mark_held_locks(curr, 1, ip))
+       if (!mark_held_locks(curr, 1))
                return;
        /*
         * If we have softirqs enabled, then set the usage
@@ -1887,7 +1876,7 @@ void trace_hardirqs_on(void)
         * this bit from being set before)
         */
        if (curr->softirqs_enabled)
-               if (!mark_held_locks(curr, 0, ip))
+               if (!mark_held_locks(curr, 0))
                        return;
 
        curr->hardirq_enable_ip = ip;
@@ -1955,7 +1944,7 @@ void trace_softirqs_on(unsigned long ip)
         * enabled too:
         */
        if (curr->hardirqs_enabled)
-               mark_held_locks(curr, 0, ip);
+               mark_held_locks(curr, 0);
 }
 
 /*
@@ -2093,43 +2082,43 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                if (read) {
                        if (curr->hardirq_context)
                                if (!mark_lock(curr, hlock,
-                                               LOCK_USED_IN_HARDIRQ_READ, ip))
+                                               LOCK_USED_IN_HARDIRQ_READ))
                                        return 0;
                        if (curr->softirq_context)
                                if (!mark_lock(curr, hlock,
-                                               LOCK_USED_IN_SOFTIRQ_READ, ip))
+                                               LOCK_USED_IN_SOFTIRQ_READ))
                                        return 0;
                } else {
                        if (curr->hardirq_context)
-                               if (!mark_lock(curr, hlock, LOCK_USED_IN_HARDIRQ, ip))
+                               if (!mark_lock(curr, hlock, LOCK_USED_IN_HARDIRQ))
                                        return 0;
                        if (curr->softirq_context)
-                               if (!mark_lock(curr, hlock, LOCK_USED_IN_SOFTIRQ, ip))
+                               if (!mark_lock(curr, hlock, LOCK_USED_IN_SOFTIRQ))
                                        return 0;
                }
        }
        if (!hardirqs_off) {
                if (read) {
                        if (!mark_lock(curr, hlock,
-                                       LOCK_ENABLED_HARDIRQS_READ, ip))
+                                       LOCK_ENABLED_HARDIRQS_READ))
                                return 0;
                        if (curr->softirqs_enabled)
                                if (!mark_lock(curr, hlock,
-                                               LOCK_ENABLED_SOFTIRQS_READ, ip))
+                                               LOCK_ENABLED_SOFTIRQS_READ))
                                        return 0;
                } else {
                        if (!mark_lock(curr, hlock,
-                                       LOCK_ENABLED_HARDIRQS, ip))
+                                       LOCK_ENABLED_HARDIRQS))
                                return 0;
                        if (curr->softirqs_enabled)
                                if (!mark_lock(curr, hlock,
-                                               LOCK_ENABLED_SOFTIRQS, ip))
+                                               LOCK_ENABLED_SOFTIRQS))
                                        return 0;
                }
        }
 #endif
        /* mark it as used: */
-       if (!mark_lock(curr, hlock, LOCK_USED, ip))
+       if (!mark_lock(curr, hlock, LOCK_USED))
                return 0;
 out_calc_hash:
        /*
index 1eb8ca565ba0422810f7ad833981a22064483965..9bd93de01f4a95ab6abb0729401bf424cf5fab21 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/init.h>
+#include <linux/kallsyms.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -95,9 +96,9 @@ static inline void add_taint_module(struct module *mod, unsigned flag)
        mod->taints |= flag;
 }
 
-/* A thread that wants to hold a reference to a module only while it
- * is running can call ths to safely exit.
- * nfsd and lockd use this.
+/*
+ * A thread that wants to hold a reference to a module only while it
+ * is running can call this to safely exit.  nfsd and lockd use this.
  */
 void __module_put_and_exit(struct module *mod, long code)
 {
@@ -310,14 +311,14 @@ static int split_block(unsigned int i, unsigned short size)
 {
        /* Reallocation required? */
        if (pcpu_num_used + 1 > pcpu_num_allocated) {
-               int *new = kmalloc(sizeof(new[0]) * pcpu_num_allocated*2,
-                                  GFP_KERNEL);
+               int *new;
+
+               new = krealloc(pcpu_size, sizeof(new[0])*pcpu_num_allocated*2,
+                              GFP_KERNEL);
                if (!new)
                        return 0;
 
-               memcpy(new, pcpu_size, sizeof(new[0])*pcpu_num_allocated);
                pcpu_num_allocated *= 2;
-               kfree(pcpu_size);
                pcpu_size = new;
        }
 
@@ -1198,7 +1199,7 @@ static int __unlink_module(void *_mod)
        return 0;
 }
 
-/* Free a module, remove from lists, etc (must hold module mutex). */
+/* Free a module, remove from lists, etc (must hold module_mutex). */
 static void free_module(struct module *mod)
 {
        /* Delete from various lists */
@@ -1245,7 +1246,7 @@ EXPORT_SYMBOL_GPL(__symbol_get);
 
 /*
  * Ensure that an exported symbol [global namespace] does not already exist
- * in the Kernel or in some other modules exported symbol table.
+ * in the kernel or in some other module's exported symbol table.
  */
 static int verify_export_symbols(struct module *mod)
 {
@@ -1471,7 +1472,7 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
 }
 
 #ifdef CONFIG_KALLSYMS
-int is_exported(const char *name, const struct module *mod)
+static int is_exported(const char *name, const struct module *mod)
 {
        if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
                return 1;
@@ -2097,8 +2098,10 @@ static const char *get_ksymbol(struct module *mod,
        if (!best)
                return NULL;
 
-       *size = nextval - mod->symtab[best].st_value;
-       *offset = addr - mod->symtab[best].st_value;
+       if (size)
+               *size = nextval - mod->symtab[best].st_value;
+       if (offset)
+               *offset = addr - mod->symtab[best].st_value;
        return mod->strtab + mod->symtab[best].st_name;
 }
 
@@ -2123,8 +2126,58 @@ const char *module_address_lookup(unsigned long addr,
        return NULL;
 }
 
-struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
-                               char *type, char *name, size_t namelen)
+int lookup_module_symbol_name(unsigned long addr, char *symname)
+{
+       struct module *mod;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(mod, &modules, list) {
+               if (within(addr, mod->module_init, mod->init_size) ||
+                   within(addr, mod->module_core, mod->core_size)) {
+                       const char *sym;
+
+                       sym = get_ksymbol(mod, addr, NULL, NULL);
+                       if (!sym)
+                               goto out;
+                       strlcpy(symname, sym, KSYM_NAME_LEN + 1);
+                       mutex_unlock(&module_mutex);
+                       return 0;
+               }
+       }
+out:
+       mutex_unlock(&module_mutex);
+       return -ERANGE;
+}
+
+int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
+                       unsigned long *offset, char *modname, char *name)
+{
+       struct module *mod;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(mod, &modules, list) {
+               if (within(addr, mod->module_init, mod->init_size) ||
+                   within(addr, mod->module_core, mod->core_size)) {
+                       const char *sym;
+
+                       sym = get_ksymbol(mod, addr, size, offset);
+                       if (!sym)
+                               goto out;
+                       if (modname)
+                               strlcpy(modname, mod->name, MODULE_NAME_LEN + 1);
+                       if (name)
+                               strlcpy(name, sym, KSYM_NAME_LEN + 1);
+                       mutex_unlock(&module_mutex);
+                       return 0;
+               }
+       }
+out:
+       mutex_unlock(&module_mutex);
+       return -ERANGE;
+}
+
+int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+                       char *name, char *module_name, int *exported)
 {
        struct module *mod;
 
@@ -2134,14 +2187,16 @@ struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
                        *value = mod->symtab[symnum].st_value;
                        *type = mod->symtab[symnum].st_info;
                        strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
-                               namelen);
+                               KSYM_NAME_LEN + 1);
+                       strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
+                       *exported = is_exported(name, mod);
                        mutex_unlock(&module_mutex);
-                       return mod;
+                       return 0;
                }
                symnum -= mod->num_symtab;
        }
        mutex_unlock(&module_mutex);
-       return NULL;
+       return -ERANGE;
 }
 
 static unsigned long mod_find_symname(struct module *mod, const char *name)
index e7cbbb82765b4f66348e927fd2911ac4d9078078..303eab18484b1c63b7a678bf2b24a928cfc847fa 100644 (file)
@@ -133,7 +133,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass)
 
        debug_mutex_lock_common(lock, &waiter);
        mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
-       debug_mutex_add_waiter(lock, &waiter, task->thread_info);
+       debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
 
        /* add waiting tasks to the end of the waitqueue (FIFO): */
        list_add_tail(&waiter.list, &lock->wait_list);
@@ -159,7 +159,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass)
                 */
                if (unlikely(state == TASK_INTERRUPTIBLE &&
                                                signal_pending(task))) {
-                       mutex_remove_waiter(lock, &waiter, task->thread_info);
+                       mutex_remove_waiter(lock, &waiter, task_thread_info(task));
                        mutex_release(&lock->dep_map, 1, _RET_IP_);
                        spin_unlock_mutex(&lock->wait_lock, flags);
 
@@ -175,8 +175,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass)
        }
 
        /* got the lock - rejoice! */
-       mutex_remove_waiter(lock, &waiter, task->thread_info);
-       debug_mutex_set_owner(lock, task->thread_info);
+       mutex_remove_waiter(lock, &waiter, task_thread_info(task));
+       debug_mutex_set_owner(lock, task_thread_info(task));
 
        /* set it to 0 if there are no waiters left: */
        if (likely(list_empty(&lock->wait_list)))
index f5b9ee6f6bbb02733cef1e64fabe4dc521efc767..1bc4b55241a8c720e16a5ed12efd108875229dcc 100644 (file)
@@ -38,10 +38,8 @@ void get_task_namespaces(struct task_struct *tsk)
 
 /*
  * creates a copy of "orig" with refcount 1.
- * This does not grab references to the contained namespaces,
- * so that needs to be done by dup_namespaces.
  */
-static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
+static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
 {
        struct nsproxy *ns;
 
@@ -52,26 +50,49 @@ static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
 }
 
 /*
- * copies the nsproxy, setting refcount to 1, and grabbing a
- * reference to all contained namespaces.  Called from
- * sys_unshare()
+ * Create new nsproxy and all of its the associated namespaces.
+ * Return the newly created nsproxy.  Do not attach this to the task,
+ * leave it to the caller to do proper locking and attach it to task.
  */
-struct nsproxy *dup_namespaces(struct nsproxy *orig)
+static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
+                       struct fs_struct *new_fs)
 {
-       struct nsproxy *ns = clone_namespaces(orig);
+       struct nsproxy *new_nsp;
 
-       if (ns) {
-               if (ns->mnt_ns)
-                       get_mnt_ns(ns->mnt_ns);
-               if (ns->uts_ns)
-                       get_uts_ns(ns->uts_ns);
-               if (ns->ipc_ns)
-                       get_ipc_ns(ns->ipc_ns);
-               if (ns->pid_ns)
-                       get_pid_ns(ns->pid_ns);
-       }
+       new_nsp = clone_nsproxy(tsk->nsproxy);
+       if (!new_nsp)
+               return ERR_PTR(-ENOMEM);
 
-       return ns;
+       new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
+       if (IS_ERR(new_nsp->mnt_ns))
+               goto out_ns;
+
+       new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
+       if (IS_ERR(new_nsp->uts_ns))
+               goto out_uts;
+
+       new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
+       if (IS_ERR(new_nsp->ipc_ns))
+               goto out_ipc;
+
+       new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
+       if (IS_ERR(new_nsp->pid_ns))
+               goto out_pid;
+
+       return new_nsp;
+
+out_pid:
+       if (new_nsp->ipc_ns)
+               put_ipc_ns(new_nsp->ipc_ns);
+out_ipc:
+       if (new_nsp->uts_ns)
+               put_uts_ns(new_nsp->uts_ns);
+out_uts:
+       if (new_nsp->mnt_ns)
+               put_mnt_ns(new_nsp->mnt_ns);
+out_ns:
+       kfree(new_nsp);
+       return ERR_PTR(-ENOMEM);
 }
 
 /*
@@ -92,47 +113,21 @@ int copy_namespaces(int flags, struct task_struct *tsk)
        if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
                return 0;
 
-       new_ns = clone_namespaces(old_ns);
-       if (!new_ns) {
-               err = -ENOMEM;
+       if (!capable(CAP_SYS_ADMIN)) {
+               err = -EPERM;
                goto out;
        }
 
-       tsk->nsproxy = new_ns;
-
-       err = copy_mnt_ns(flags, tsk);
-       if (err)
-               goto out_ns;
-
-       err = copy_utsname(flags, tsk);
-       if (err)
-               goto out_uts;
-
-       err = copy_ipcs(flags, tsk);
-       if (err)
-               goto out_ipc;
-
-       err = copy_pid_ns(flags, tsk);
-       if (err)
-               goto out_pid;
+       new_ns = create_new_namespaces(flags, tsk, tsk->fs);
+       if (IS_ERR(new_ns)) {
+               err = PTR_ERR(new_ns);
+               goto out;
+       }
 
+       tsk->nsproxy = new_ns;
 out:
        put_nsproxy(old_ns);
        return err;
-
-out_pid:
-       if (new_ns->ipc_ns)
-               put_ipc_ns(new_ns->ipc_ns);
-out_ipc:
-       if (new_ns->uts_ns)
-               put_uts_ns(new_ns->uts_ns);
-out_uts:
-       if (new_ns->mnt_ns)
-               put_mnt_ns(new_ns->mnt_ns);
-out_ns:
-       tsk->nsproxy = old_ns;
-       kfree(new_ns);
-       goto out;
 }
 
 void free_nsproxy(struct nsproxy *ns)
@@ -147,3 +142,41 @@ void free_nsproxy(struct nsproxy *ns)
                put_pid_ns(ns->pid_ns);
        kfree(ns);
 }
+
+/*
+ * Called from unshare. Unshare all the namespaces part of nsproxy.
+ * On sucess, returns the new nsproxy and a reference to old nsproxy
+ * to make sure it stays around.
+ */
+int unshare_nsproxy_namespaces(unsigned long unshare_flags,
+               struct nsproxy **new_nsp, struct fs_struct *new_fs)
+{
+       struct nsproxy *old_ns = current->nsproxy;
+       int err = 0;
+
+       if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+               return 0;
+
+#ifndef CONFIG_IPC_NS
+       if (unshare_flags & CLONE_NEWIPC)
+               return -EINVAL;
+#endif
+
+#ifndef CONFIG_UTS_NS
+       if (unshare_flags & CLONE_NEWUTS)
+               return -EINVAL;
+#endif
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       get_nsproxy(old_ns);
+
+       *new_nsp = create_new_namespaces(unshare_flags, current,
+                               new_fs ? new_fs : current->fs);
+       if (IS_ERR(*new_nsp)) {
+               err = PTR_ERR(*new_nsp);
+               put_nsproxy(old_ns);
+       }
+       return err;
+}
index 312172320b4ccc8e76959cda55b2852ecfee6f82..e61c46c97ce72ec1fb9615783e02dd4afb7c9990 100644 (file)
@@ -269,7 +269,7 @@ int param_get_invbool(char *buffer, struct kernel_param *kp)
        return param_get_bool(buffer, &dummy);
 }
 
-/* We cheat here and temporarily mangle the string. */
+/* We break the rule and mangle the string. */
 static int param_array(const char *name,
                       const char *val,
                       unsigned int min, unsigned int max,
index 9c80bc23d6b8551c41fffffe1fb92e1711ce3547..d3ad724afa8305548ff5c11b830032366a0592d2 100644 (file)
@@ -360,16 +360,11 @@ struct pid *find_ge_pid(int nr)
 }
 EXPORT_SYMBOL_GPL(find_get_pid);
 
-int copy_pid_ns(int flags, struct task_struct *tsk)
+struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
 {
-       struct pid_namespace *old_ns = tsk->nsproxy->pid_ns;
-       int err = 0;
-
-       if (!old_ns)
-               return 0;
-
+       BUG_ON(!old_ns);
        get_pid_ns(old_ns);
-       return err;
+       return old_ns;
 }
 
 void free_pid_ns(struct kref *kref)
index 657f77697415b2879c07b85e759e8d19b0880b93..1de710e183734b6e47bd7aa4819bd5b3c54deeb2 100644 (file)
@@ -971,7 +971,7 @@ static void check_thread_timers(struct task_struct *tsk,
        maxfire = 20;
        tsk->it_prof_expires = cputime_zero;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
@@ -986,7 +986,7 @@ static void check_thread_timers(struct task_struct *tsk,
        maxfire = 20;
        tsk->it_virt_expires = cputime_zero;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
@@ -1001,7 +1001,7 @@ static void check_thread_timers(struct task_struct *tsk,
        maxfire = 20;
        tsk->it_sched_expires = 0;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || tsk->sched_time < t->expires.sched) {
@@ -1057,7 +1057,7 @@ static void check_process_timers(struct task_struct *tsk,
        maxfire = 20;
        prof_expires = cputime_zero;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) {
@@ -1072,7 +1072,7 @@ static void check_process_timers(struct task_struct *tsk,
        maxfire = 20;
        virt_expires = cputime_zero;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || cputime_lt(utime, t->expires.cpu)) {
@@ -1087,7 +1087,7 @@ static void check_process_timers(struct task_struct *tsk,
        maxfire = 20;
        sched_expires = 0;
        while (!list_empty(timers)) {
-               struct cpu_timer_list *t = list_entry(timers->next,
+               struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
                if (!--maxfire || sched_time < t->expires.sched) {
@@ -1400,7 +1400,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
         */
        head = &tsk->signal->cpu_timers[clock_idx];
        if (list_empty(head) ||
-           cputime_ge(list_entry(head->next,
+           cputime_ge(list_first_entry(head,
                                  struct cpu_timer_list, entry)->expires.cpu,
                       *newval)) {
                /*
index 44318ca71978d9afae52c6149153d323e08a06b5..588c99da030792babb3c643b89e645c8abebdb2b 100644 (file)
@@ -31,7 +31,6 @@
  * POSIX clocks & timers
  */
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/time.h>
index 877721708fa4135e4340311e4640c535ecb83038..495b7d4dd3304d650bb5c540b29a868eb0fce88a 100644 (file)
@@ -79,7 +79,7 @@ config PM_SYSFS_DEPRECATED
 
 config SOFTWARE_SUSPEND
        bool "Software Suspend (Hibernation)"
-       depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
+       depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
        ---help---
          Enable the suspend to disk (STD) functionality, which is usually
          called "hibernation" in user interfaces.  STD checkpoints the
@@ -139,7 +139,7 @@ config PM_STD_PARTITION
 
 config SUSPEND_SMP
        bool
-       depends on HOTPLUG_CPU && X86 && PM
+       depends on HOTPLUG_CPU && (X86 || PPC64) && PM
        default y
 
 config APM_EMULATION
index 06331374d8624627e4071ca5df6b70cdf16c190b..b5f0543ed84d38bd44ceb96cb5efe3d0330d15e8 100644 (file)
@@ -30,30 +30,69 @@ char resume_file[256] = CONFIG_PM_STD_PARTITION;
 dev_t swsusp_resume_device;
 sector_t swsusp_resume_block;
 
+enum {
+       HIBERNATION_INVALID,
+       HIBERNATION_PLATFORM,
+       HIBERNATION_TEST,
+       HIBERNATION_TESTPROC,
+       HIBERNATION_SHUTDOWN,
+       HIBERNATION_REBOOT,
+       /* keep last */
+       __HIBERNATION_AFTER_LAST
+};
+#define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1)
+#define HIBERNATION_FIRST (HIBERNATION_INVALID + 1)
+
+static int hibernation_mode = HIBERNATION_SHUTDOWN;
+
+struct hibernation_ops *hibernation_ops;
+
+/**
+ * hibernation_set_ops - set the global hibernate operations
+ * @ops: the hibernation operations to use in subsequent hibernation transitions
+ */
+
+void hibernation_set_ops(struct hibernation_ops *ops)
+{
+       if (ops && !(ops->prepare && ops->enter && ops->finish)) {
+               WARN_ON(1);
+               return;
+       }
+       mutex_lock(&pm_mutex);
+       hibernation_ops = ops;
+       if (ops)
+               hibernation_mode = HIBERNATION_PLATFORM;
+       else if (hibernation_mode == HIBERNATION_PLATFORM)
+               hibernation_mode = HIBERNATION_SHUTDOWN;
+
+       mutex_unlock(&pm_mutex);
+}
+
+
 /**
  *     platform_prepare - prepare the machine for hibernation using the
  *     platform driver if so configured and return an error code if it fails
  */
 
-static inline int platform_prepare(void)
+static int platform_prepare(void)
 {
-       int error = 0;
+       return (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops) ?
+               hibernation_ops->prepare() : 0;
+}
 
-       switch (pm_disk_mode) {
-       case PM_DISK_TEST:
-       case PM_DISK_TESTPROC:
-       case PM_DISK_SHUTDOWN:
-       case PM_DISK_REBOOT:
-               break;
-       default:
-               if (pm_ops && pm_ops->prepare)
-                       error = pm_ops->prepare(PM_SUSPEND_DISK);
-       }
-       return error;
+/**
+ *     platform_finish - switch the machine to the normal mode of operation
+ *     using the platform driver (must be called after platform_prepare())
+ */
+
+static void platform_finish(void)
+{
+       if (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops)
+               hibernation_ops->finish();
 }
 
 /**
- *     power_down - Shut machine down for hibernate.
+ *     power_down - Shut the machine down for hibernation.
  *
  *     Use the platform driver, if configured so; otherwise try
  *     to power off or reboot.
@@ -61,20 +100,20 @@ static inline int platform_prepare(void)
 
 static void power_down(void)
 {
-       switch (pm_disk_mode) {
-       case PM_DISK_TEST:
-       case PM_DISK_TESTPROC:
+       switch (hibernation_mode) {
+       case HIBERNATION_TEST:
+       case HIBERNATION_TESTPROC:
                break;
-       case PM_DISK_SHUTDOWN:
+       case HIBERNATION_SHUTDOWN:
                kernel_power_off();
                break;
-       case PM_DISK_REBOOT:
+       case HIBERNATION_REBOOT:
                kernel_restart(NULL);
                break;
-       default:
-               if (pm_ops && pm_ops->enter) {
+       case HIBERNATION_PLATFORM:
+               if (hibernation_ops) {
                        kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-                       pm_ops->enter(PM_SUSPEND_DISK);
+                       hibernation_ops->enter();
                        break;
                }
        }
@@ -87,20 +126,6 @@ static void power_down(void)
        while(1);
 }
 
-static inline void platform_finish(void)
-{
-       switch (pm_disk_mode) {
-       case PM_DISK_TEST:
-       case PM_DISK_TESTPROC:
-       case PM_DISK_SHUTDOWN:
-       case PM_DISK_REBOOT:
-               break;
-       default:
-               if (pm_ops && pm_ops->finish)
-                       pm_ops->finish(PM_SUSPEND_DISK);
-       }
-}
-
 static void unprepare_processes(void)
 {
        thaw_processes();
@@ -120,13 +145,10 @@ static int prepare_processes(void)
 }
 
 /**
- *     pm_suspend_disk - The granpappy of hibernation power management.
- *
- *     If not, then call swsusp to do its thing, then figure out how
- *     to power down the system.
+ *     hibernate - The granpappy of the built-in hibernation management
  */
 
-int pm_suspend_disk(void)
+int hibernate(void)
 {
        int error;
 
@@ -143,7 +165,8 @@ int pm_suspend_disk(void)
        if (error)
                goto Finish;
 
-       if (pm_disk_mode == PM_DISK_TESTPROC) {
+       mutex_lock(&pm_mutex);
+       if (hibernation_mode == HIBERNATION_TESTPROC) {
                printk("swsusp debug: Waiting for 5 seconds.\n");
                mdelay(5000);
                goto Thaw;
@@ -168,7 +191,7 @@ int pm_suspend_disk(void)
        if (error)
                goto Enable_cpus;
 
-       if (pm_disk_mode == PM_DISK_TEST) {
+       if (hibernation_mode == HIBERNATION_TEST) {
                printk("swsusp debug: Waiting for 5 seconds.\n");
                mdelay(5000);
                goto Enable_cpus;
@@ -205,6 +228,7 @@ int pm_suspend_disk(void)
        device_resume();
        resume_console();
  Thaw:
+       mutex_unlock(&pm_mutex);
        unprepare_processes();
  Finish:
        free_basic_memory_bitmaps();
@@ -220,7 +244,7 @@ int pm_suspend_disk(void)
  *     Called as a late_initcall (so all devices are discovered and
  *     initialized), we call swsusp to see if we have a saved image or not.
  *     If so, we quiesce devices, the restore the saved image. We will
- *     return above (in pm_suspend_disk() ) if everything goes well.
+ *     return above (in hibernate() ) if everything goes well.
  *     Otherwise, we fail gracefully and return to the normally
  *     scheduled program.
  *
@@ -315,25 +339,26 @@ static int software_resume(void)
 late_initcall(software_resume);
 
 
-static const char * const pm_disk_modes[] = {
-       [PM_DISK_PLATFORM]      = "platform",
-       [PM_DISK_SHUTDOWN]      = "shutdown",
-       [PM_DISK_REBOOT]        = "reboot",
-       [PM_DISK_TEST]          = "test",
-       [PM_DISK_TESTPROC]      = "testproc",
+static const char * const hibernation_modes[] = {
+       [HIBERNATION_PLATFORM]  = "platform",
+       [HIBERNATION_SHUTDOWN]  = "shutdown",
+       [HIBERNATION_REBOOT]    = "reboot",
+       [HIBERNATION_TEST]      = "test",
+       [HIBERNATION_TESTPROC]  = "testproc",
 };
 
 /**
- *     disk - Control suspend-to-disk mode
+ *     disk - Control hibernation mode
  *
  *     Suspend-to-disk can be handled in several ways. We have a few options
  *     for putting the system to sleep - using the platform driver (e.g. ACPI
- *     or other pm_ops), powering off the system or rebooting the system
- *     (for testing) as well as the two test modes.
+ *     or other hibernation_ops), powering off the system or rebooting the
+ *     system (for testing) as well as the two test modes.
  *
  *     The system can support 'platform', and that is known a priori (and
- *     encoded in pm_ops). However, the user may choose 'shutdown' or 'reboot'
- *     as alternatives, as well as the test modes 'test' and 'testproc'.
+ *     encoded by the presence of hibernation_ops). However, the user may
+ *     choose 'shutdown' or 'reboot' as alternatives, as well as one fo the
+ *     test modes, 'test' or 'testproc'.
  *
  *     show() will display what the mode is currently set to.
  *     store() will accept one of
@@ -345,7 +370,7 @@ static const char * const pm_disk_modes[] = {
  *     'testproc'
  *
  *     It will only change to 'platform' if the system
- *     supports it (as determined from pm_ops->pm_disk_mode).
+ *     supports it (as determined by having hibernation_ops).
  */
 
 static ssize_t disk_show(struct kset *kset, char *buf)
@@ -353,28 +378,25 @@ static ssize_t disk_show(struct kset *kset, char *buf)
        int i;
        char *start = buf;
 
-       for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) {
-               if (!pm_disk_modes[i])
+       for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
+               if (!hibernation_modes[i])
                        continue;
                switch (i) {
-               case PM_DISK_SHUTDOWN:
-               case PM_DISK_REBOOT:
-               case PM_DISK_TEST:
-               case PM_DISK_TESTPROC:
+               case HIBERNATION_SHUTDOWN:
+               case HIBERNATION_REBOOT:
+               case HIBERNATION_TEST:
+               case HIBERNATION_TESTPROC:
                        break;
-               default:
-                       if (pm_ops && pm_ops->enter &&
-                           (i == pm_ops->pm_disk_mode))
+               case HIBERNATION_PLATFORM:
+                       if (hibernation_ops)
                                break;
                        /* not a valid mode, continue with loop */
                        continue;
                }
-               if (i == pm_disk_mode)
-                       buf += sprintf(buf, "[%s]", pm_disk_modes[i]);
+               if (i == hibernation_mode)
+                       buf += sprintf(buf, "[%s] ", hibernation_modes[i]);
                else
-                       buf += sprintf(buf, "%s", pm_disk_modes[i]);
-               if (i+1 != PM_DISK_MAX)
-                       buf += sprintf(buf, " ");
+                       buf += sprintf(buf, "%s ", hibernation_modes[i]);
        }
        buf += sprintf(buf, "\n");
        return buf-start;
@@ -387,39 +409,38 @@ static ssize_t disk_store(struct kset *kset, const char *buf, size_t n)
        int i;
        int len;
        char *p;
-       suspend_disk_method_t mode = 0;
+       int mode = HIBERNATION_INVALID;
 
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
 
        mutex_lock(&pm_mutex);
-       for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) {
-               if (!strncmp(buf, pm_disk_modes[i], len)) {
+       for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
+               if (!strncmp(buf, hibernation_modes[i], len)) {
                        mode = i;
                        break;
                }
        }
-       if (mode) {
+       if (mode != HIBERNATION_INVALID) {
                switch (mode) {
-               case PM_DISK_SHUTDOWN:
-               case PM_DISK_REBOOT:
-               case PM_DISK_TEST:
-               case PM_DISK_TESTPROC:
-                       pm_disk_mode = mode;
+               case HIBERNATION_SHUTDOWN:
+               case HIBERNATION_REBOOT:
+               case HIBERNATION_TEST:
+               case HIBERNATION_TESTPROC:
+                       hibernation_mode = mode;
                        break;
-               default:
-                       if (pm_ops && pm_ops->enter &&
-                           (mode == pm_ops->pm_disk_mode))
-                               pm_disk_mode = mode;
+               case HIBERNATION_PLATFORM:
+                       if (hibernation_ops)
+                               hibernation_mode = mode;
                        else
                                error = -EINVAL;
                }
-       } else {
+       } else
                error = -EINVAL;
-       }
 
-       pr_debug("PM: suspend-to-disk mode set to '%s'\n",
-                pm_disk_modes[mode]);
+       if (!error)
+               pr_debug("PM: suspend-to-disk mode set to '%s'\n",
+                        hibernation_modes[mode]);
        mutex_unlock(&pm_mutex);
        return error ? error : n;
 }
index f6dda685e7e2b06bd0eb27631dd84dbf33e8c0ef..40d56a31245e96e7e70557faaea98de382286614 100644 (file)
@@ -30,7 +30,6 @@
 DEFINE_MUTEX(pm_mutex);
 
 struct pm_ops *pm_ops;
-suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
 
 /**
  *     pm_set_ops - Set the global power method table. 
@@ -41,10 +40,6 @@ void pm_set_ops(struct pm_ops * ops)
 {
        mutex_lock(&pm_mutex);
        pm_ops = ops;
-       if (ops && ops->pm_disk_mode != PM_DISK_INVALID) {
-               pm_disk_mode = ops->pm_disk_mode;
-       } else
-               pm_disk_mode = PM_DISK_SHUTDOWN;
        mutex_unlock(&pm_mutex);
 }
 
@@ -184,24 +179,12 @@ static void suspend_finish(suspend_state_t state)
 static const char * const pm_states[PM_SUSPEND_MAX] = {
        [PM_SUSPEND_STANDBY]    = "standby",
        [PM_SUSPEND_MEM]        = "mem",
-       [PM_SUSPEND_DISK]       = "disk",
 };
 
 static inline int valid_state(suspend_state_t state)
 {
-       /* Suspend-to-disk does not really need low-level support.
-        * It can work with shutdown/reboot if needed. If it isn't
-        * configured, then it cannot be supported.
-        */
-       if (state == PM_SUSPEND_DISK)
-#ifdef CONFIG_SOFTWARE_SUSPEND
-               return 1;
-#else
-               return 0;
-#endif
-
-       /* all other states need lowlevel support and need to be
-        * valid to the lowlevel implementation, no valid callback
+       /* All states need lowlevel support and need to be valid
+        * to the lowlevel implementation, no valid callback
         * implies that none are valid. */
        if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state))
                return 0;
@@ -229,11 +212,6 @@ static int enter_state(suspend_state_t state)
        if (!mutex_trylock(&pm_mutex))
                return -EBUSY;
 
-       if (state == PM_SUSPEND_DISK) {
-               error = pm_suspend_disk();
-               goto Unlock;
-       }
-
        pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
        if ((error = suspend_prepare(state)))
                goto Unlock;
@@ -251,7 +229,7 @@ static int enter_state(suspend_state_t state)
 
 /**
  *     pm_suspend - Externally visible function for suspending system.
- *     @state:         Enumarted value of state to enter.
+ *     @state:         Enumerated value of state to enter.
  *
  *     Determine whether or not value is within range, get state 
  *     structure, and enter (above).
@@ -289,7 +267,13 @@ static ssize_t state_show(struct kset *kset, char *buf)
                if (pm_states[i] && valid_state(i))
                        s += sprintf(s,"%s ", pm_states[i]);
        }
-       s += sprintf(s,"\n");
+#ifdef CONFIG_SOFTWARE_SUSPEND
+       s += sprintf(s, "%s\n", "disk");
+#else
+       if (s != buf)
+               /* convert the last space to a newline */
+               *(s-1) = '\n';
+#endif
        return (s - buf);
 }
 
@@ -304,6 +288,12 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
 
+       /* First, check if we are requested to hibernate */
+       if (!strncmp(buf, "disk", len)) {
+               error = hibernate();
+               return error ? error : n;
+       }
+
        for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
                if (*s && !strncmp(buf, *s, len))
                        break;
index 34b43542785a3859d8e954858346aeb8d409f367..51381487103ff405263cb48983db8102ce7f73f8 100644 (file)
@@ -25,12 +25,7 @@ struct swsusp_info {
  */
 #define SPARE_PAGES    ((1024 * 1024) >> PAGE_SHIFT)
 
-extern int pm_suspend_disk(void);
-#else
-static inline int pm_suspend_disk(void)
-{
-       return -EPERM;
-}
+extern struct hibernation_ops *hibernation_ops;
 #endif
 
 extern int pfn_is_nosave(unsigned long);
index 0eb5c420e8edfdba4fe04adea60608e0be6357be..088419387388ca181d6e855a8aa98be97e930025 100644 (file)
@@ -8,7 +8,6 @@
 
 #undef DEBUG
 
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
 
 static inline int freezeable(struct task_struct * p)
 {
-       if ((p == current) || 
+       if ((p == current) ||
            (p->flags & PF_NOFREEZE) ||
-           (p->exit_state == EXIT_ZOMBIE) ||
-           (p->exit_state == EXIT_DEAD))
+           (p->exit_state != 0))
                return 0;
        return 1;
 }
index 128da11f01c2678aedb77854af1f910870a9d7c3..a3b7854b8f7c8ea2de21e8940e0f2f3be4ba50ca 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/suspend.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
@@ -608,7 +607,8 @@ static LIST_HEAD(nosave_regions);
  */
 
 void __init
-register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+__register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
+                        int use_kmalloc)
 {
        struct nosave_region *region;
 
@@ -624,8 +624,13 @@ register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
                        goto Report;
                }
        }
-       /* This allocation cannot fail */
-       region = alloc_bootmem_low(sizeof(struct nosave_region));
+       if (use_kmalloc) {
+               /* during init, this shouldn't fail */
+               region = kmalloc(sizeof(struct nosave_region), GFP_KERNEL);
+               BUG_ON(!region);
+       } else
+               /* This allocation cannot fail */
+               region = alloc_bootmem_low(sizeof(struct nosave_region));
        region->start_pfn = start_pfn;
        region->end_pfn = end_pfn;
        list_add_tail(&region->list, &nosave_regions);
@@ -1228,7 +1233,7 @@ asmlinkage int swsusp_save(void)
        nr_copy_pages = nr_pages;
        nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
 
-       printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages);
+       printk("swsusp: critical section: done (%d pages copied)\n", nr_pages);
 
        return 0;
 }
index e83ed9945a807634a4a12d6753f1adacdb110a62..b8b235cc19d1591077f7cda71175ec2c152ff808 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
 #include <linux/version.h>
index 040560d9c3123b50502fdfd3dd0518e822086060..24d7d78e6f42ff71e95401b82460924709346f1a 100644 (file)
@@ -130,16 +130,16 @@ static inline int platform_prepare(void)
 {
        int error = 0;
 
-       if (pm_ops && pm_ops->prepare)
-               error = pm_ops->prepare(PM_SUSPEND_DISK);
+       if (hibernation_ops)
+               error = hibernation_ops->prepare();
 
        return error;
 }
 
 static inline void platform_finish(void)
 {
-       if (pm_ops && pm_ops->finish)
-               pm_ops->finish(PM_SUSPEND_DISK);
+       if (hibernation_ops)
+               hibernation_ops->finish();
 }
 
 static inline int snapshot_suspend(int platform_suspend)
@@ -384,7 +384,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                switch (arg) {
 
                case PMOPS_PREPARE:
-                       if (pm_ops && pm_ops->enter) {
+                       if (hibernation_ops) {
                                data->platform_suspend = 1;
                                error = 0;
                        } else {
@@ -395,8 +395,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                case PMOPS_ENTER:
                        if (data->platform_suspend) {
                                kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-                               error = pm_ops->enter(PM_SUSPEND_DISK);
-                               error = 0;
+                               error = hibernation_ops->enter();
                        }
                        break;
 
index 4b47e59248df00375ce5fda81e760f89e14f9a22..0bbdeac2810cb53c4960cb303f4b396d29cbb341 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
-#include <linux/smp_lock.h>
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -931,8 +930,16 @@ void register_console(struct console *console)
 {
        int i;
        unsigned long flags;
+       struct console *bootconsole = NULL;
 
-       if (preferred_console < 0)
+       if (console_drivers) {
+               if (console->flags & CON_BOOT)
+                       return;
+               if (console_drivers->flags & CON_BOOT)
+                       bootconsole = console_drivers;
+       }
+
+       if (preferred_console < 0 || bootconsole || !console_drivers)
                preferred_console = selected_console;
 
        /*
@@ -978,8 +985,11 @@ void register_console(struct console *console)
        if (!(console->flags & CON_ENABLED))
                return;
 
-       if (console_drivers && (console_drivers->flags & CON_BOOT)) {
-               unregister_console(console_drivers);
+       if (bootconsole) {
+               printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
+                      bootconsole->name, bootconsole->index,
+                      console->name, console->index);
+               unregister_console(bootconsole);
                console->flags &= ~CON_PRINTBUFFER;
        }
 
@@ -1030,16 +1040,11 @@ int unregister_console(struct console *console)
                }
        }
 
-       /* If last console is removed, we re-enable picking the first
-        * one that gets registered. Without that, pmac early boot console
-        * would prevent fbcon from taking over.
-        *
+       /*
         * If this isn't the last console and it has CON_CONSDEV set, we
         * need to set it on the next preferred console.
         */
-       if (console_drivers == NULL)
-               preferred_console = selected_console;
-       else if (console->flags & CON_CONSDEV)
+       if (console_drivers != NULL && console->flags & CON_CONSDEV)
                console_drivers->flags |= CON_CONSDEV;
 
        release_console_sem();
index 9bfadb248dd877b009e49710db79957f13188c5d..cc91b9bf759dc5723037d8ac4e2ab2e765372b16 100644 (file)
@@ -340,6 +340,7 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                node = cpu_to_node(cpu);
                per_cpu(cpu_profile_flip, cpu) = 0;
                if (!per_cpu(cpu_profile_hits, cpu)[1]) {
@@ -365,10 +366,13 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
                __free_page(page);
                return NOTIFY_BAD;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cpu_set(cpu, prof_cpu_mask);
                break;
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                cpu_clear(cpu, prof_cpu_mask);
                if (per_cpu(cpu_profile_hits, cpu)[0]) {
                        page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]);
index 3554b76da84cf08ebc2808b5f2a237a362e52330..2c2dd8410dc4fd8b27d0e66dcd31daceb56ff027 100644 (file)
@@ -558,9 +558,11 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
        long cpu = (long)hcpu;
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                rcu_online_cpu(cpu);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                rcu_offline_cpu(cpu);
                break;
        default:
index bcd14e83ef39c44dbf77eb1d6cc89a2a34b3e55b..55ba82a85a66c65605994ec685a2ce1918efdfc9 100644 (file)
@@ -502,10 +502,6 @@ static struct rcu_torture_ops sched_ops = {
        .name = "sched"
 };
 
-static struct rcu_torture_ops *torture_ops[] =
-       { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, &srcu_ops,
-         &sched_ops, NULL };
-
 /*
  * RCU torture writer kthread.  Repeatedly substitutes a new structure
  * for that pointed to by rcu_torture_current, freeing the old structure
@@ -534,7 +530,7 @@ rcu_torture_writer(void *arg)
                rp->rtort_mbtest = 1;
                rcu_assign_pointer(rcu_torture_current, rp);
                smp_wmb();
-               if (old_rp != NULL) {
+               if (old_rp) {
                        i = old_rp->rtort_pipe_count;
                        if (i > RCU_TORTURE_PIPE_LEN)
                                i = RCU_TORTURE_PIPE_LEN;
@@ -685,7 +681,7 @@ rcu_torture_printk(char *page)
                               atomic_read(&rcu_torture_wcount[i]));
        }
        cnt += sprintf(&page[cnt], "\n");
-       if (cur_ops->stats != NULL)
+       if (cur_ops->stats)
                cnt += cur_ops->stats(&page[cnt]);
        return cnt;
 }
@@ -749,13 +745,13 @@ static void rcu_torture_shuffle_tasks(void)
 
        set_cpus_allowed(current, tmp_mask);
 
-       if (reader_tasks != NULL) {
+       if (reader_tasks) {
                for (i = 0; i < nrealreaders; i++)
                        if (reader_tasks[i])
                                set_cpus_allowed(reader_tasks[i], tmp_mask);
        }
 
-       if (fakewriter_tasks != NULL) {
+       if (fakewriter_tasks) {
                for (i = 0; i < nfakewriters; i++)
                        if (fakewriter_tasks[i])
                                set_cpus_allowed(fakewriter_tasks[i], tmp_mask);
@@ -808,21 +804,21 @@ rcu_torture_cleanup(void)
        int i;
 
        fullstop = 1;
-       if (shuffler_task != NULL) {
+       if (shuffler_task) {
                VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
                kthread_stop(shuffler_task);
        }
        shuffler_task = NULL;
 
-       if (writer_task != NULL) {
+       if (writer_task) {
                VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
                kthread_stop(writer_task);
        }
        writer_task = NULL;
 
-       if (reader_tasks != NULL) {
+       if (reader_tasks) {
                for (i = 0; i < nrealreaders; i++) {
-                       if (reader_tasks[i] != NULL) {
+                       if (reader_tasks[i]) {
                                VERBOSE_PRINTK_STRING(
                                        "Stopping rcu_torture_reader task");
                                kthread_stop(reader_tasks[i]);
@@ -834,9 +830,9 @@ rcu_torture_cleanup(void)
        }
        rcu_torture_current = NULL;
 
-       if (fakewriter_tasks != NULL) {
+       if (fakewriter_tasks) {
                for (i = 0; i < nfakewriters; i++) {
-                       if (fakewriter_tasks[i] != NULL) {
+                       if (fakewriter_tasks[i]) {
                                VERBOSE_PRINTK_STRING(
                                        "Stopping rcu_torture_fakewriter task");
                                kthread_stop(fakewriter_tasks[i]);
@@ -847,7 +843,7 @@ rcu_torture_cleanup(void)
                fakewriter_tasks = NULL;
        }
 
-       if (stats_task != NULL) {
+       if (stats_task) {
                VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
                kthread_stop(stats_task);
        }
@@ -858,7 +854,7 @@ rcu_torture_cleanup(void)
 
        rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
 
-       if (cur_ops->cleanup != NULL)
+       if (cur_ops->cleanup)
                cur_ops->cleanup();
        if (atomic_read(&n_rcu_torture_error))
                rcu_torture_print_module_parms("End of test: FAILURE");
@@ -866,27 +862,28 @@ rcu_torture_cleanup(void)
                rcu_torture_print_module_parms("End of test: SUCCESS");
 }
 
-static int
+static int __init
 rcu_torture_init(void)
 {
        int i;
        int cpu;
        int firsterr = 0;
+       static struct rcu_torture_ops *torture_ops[] =
+               { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops,
+                 &srcu_ops, &sched_ops, };
 
        /* Process args and tell the world that the torturer is on the job. */
-
-       for (i = 0; cur_ops = torture_ops[i], cur_ops != NULL; i++) {
+       for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
                cur_ops = torture_ops[i];
-               if (strcmp(torture_type, cur_ops->name) == 0) {
+               if (strcmp(torture_type, cur_ops->name) == 0)
                        break;
-               }
        }
-       if (cur_ops == NULL) {
+       if (i == ARRAY_SIZE(torture_ops)) {
                printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n",
                       torture_type);
                return (-EINVAL);
        }
-       if (cur_ops->init != NULL)
+       if (cur_ops->init)
                cur_ops->init(); /* no "goto unwind" prior to this point!!! */
 
        if (nreaders >= 0)
@@ -899,7 +896,7 @@ rcu_torture_init(void)
        /* Set up the freelist. */
 
        INIT_LIST_HEAD(&rcu_torture_freelist);
-       for (i = 0; i < sizeof(rcu_tortures) / sizeof(rcu_tortures[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(rcu_tortures); i++) {
                rcu_tortures[i].rtort_mbtest = 0;
                list_add_tail(&rcu_tortures[i].rtort_free,
                              &rcu_torture_freelist);
index 577f251c7e28104f621d542a199169053a589c8b..4311101b0ca75a46206a2e9a50f82bffd5683fa5 100644 (file)
@@ -310,16 +310,13 @@ static struct rchan_callbacks default_channel_callbacks = {
 
 /**
  *     wakeup_readers - wake up readers waiting on a channel
- *     @work: work struct that contains the the channel buffer
+ *     @data: contains 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.
+ *     This is the timer function used to defer reader waking.
  */
-static void wakeup_readers(struct work_struct *work)
+static void wakeup_readers(unsigned long data)
 {
-       struct rchan_buf *buf =
-               container_of(work, struct rchan_buf, wake_readers.work);
+       struct rchan_buf *buf = (struct rchan_buf *)data;
        wake_up_interruptible(&buf->read_wait);
 }
 
@@ -337,11 +334,9 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
        if (init) {
                init_waitqueue_head(&buf->read_wait);
                kref_init(&buf->kref);
-               INIT_DELAYED_WORK(&buf->wake_readers, NULL);
-       } else {
-               cancel_delayed_work(&buf->wake_readers);
-               flush_scheduled_work();
-       }
+               setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf);
+       } else
+               del_timer_sync(&buf->timer);
 
        buf->subbufs_produced = 0;
        buf->subbufs_consumed = 0;
@@ -447,8 +442,7 @@ end:
 static void relay_close_buf(struct rchan_buf *buf)
 {
        buf->finalized = 1;
-       cancel_delayed_work(&buf->wake_readers);
-       flush_scheduled_work();
+       del_timer_sync(&buf->timer);
        kref_put(&buf->kref, relay_remove_buf);
 }
 
@@ -490,6 +484,7 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
 
        switch(action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                mutex_lock(&relay_channels_mutex);
                list_for_each_entry(chan, &relay_channels, list) {
                        if (chan->buf[hotcpu])
@@ -506,6 +501,7 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
                mutex_unlock(&relay_channels_mutex);
                break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                /* No need to flush the cpu : will be flushed upon
                 * final relay_flush() call. */
                break;
@@ -608,11 +604,14 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                buf->dentry->d_inode->i_size += buf->chan->subbuf_size -
                        buf->padding[old_subbuf];
                smp_mb();
-               if (waitqueue_active(&buf->read_wait)) {
-                       PREPARE_DELAYED_WORK(&buf->wake_readers,
-                                            wakeup_readers);
-                       schedule_delayed_work(&buf->wake_readers, 1);
-               }
+               if (waitqueue_active(&buf->read_wait))
+                       /*
+                        * Calling wake_up_interruptible() from here
+                        * will deadlock if we happen to be logging
+                        * from the scheduler (trying to re-grab
+                        * rq->lock), so defer it.
+                        */
+                       __mod_timer(&buf->timer, jiffies + 1);
        }
 
        old = buf->data;
index 180978cb2f7524b180863967be0391d32f47783d..12879f6c1ec3b9a53069690f0205082ea581565c 100644 (file)
@@ -56,7 +56,7 @@
  * state.
  */
 
-static void
+void
 rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
                   unsigned long mask)
 {
@@ -80,29 +80,6 @@ static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
                clear_rt_mutex_waiters(lock);
 }
 
-/*
- * We can speed up the acquire/release, if the architecture
- * supports cmpxchg and if there's no debugging state to be set up
- */
-#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
-# define rt_mutex_cmpxchg(l,c,n)       (cmpxchg(&l->owner, c, n) == c)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
-       unsigned long owner, *p = (unsigned long *) &lock->owner;
-
-       do {
-               owner = *p;
-       } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
-}
-#else
-# define rt_mutex_cmpxchg(l,c,n)       (0)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
-       lock->owner = (struct task_struct *)
-                       ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
-}
-#endif
-
 /*
  * Calculate task priority from the waiter list priority
  *
@@ -123,7 +100,7 @@ int rt_mutex_getprio(struct task_struct *task)
  *
  * This can be both boosting and unboosting. task->pi_lock must be held.
  */
-static void __rt_mutex_adjust_prio(struct task_struct *task)
+void __rt_mutex_adjust_prio(struct task_struct *task)
 {
        int prio = rt_mutex_getprio(task);
 
@@ -159,11 +136,11 @@ int max_lock_depth = 1024;
  * Decreases task's usage by one - may thus free the task.
  * Returns 0 or -EDEADLK.
  */
-static int rt_mutex_adjust_prio_chain(struct task_struct *task,
-                                     int deadlock_detect,
-                                     struct rt_mutex *orig_lock,
-                                     struct rt_mutex_waiter *orig_waiter,
-                                     struct task_struct *top_task)
+int rt_mutex_adjust_prio_chain(struct task_struct *task,
+                              int deadlock_detect,
+                              struct rt_mutex *orig_lock,
+                              struct rt_mutex_waiter *orig_waiter,
+                              struct task_struct *top_task)
 {
        struct rt_mutex *lock;
        struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter;
@@ -524,8 +501,8 @@ static void wakeup_next_waiter(struct rt_mutex *lock)
  *
  * Must be called with lock->wait_lock held
  */
-static void remove_waiter(struct rt_mutex *lock,
-                         struct rt_mutex_waiter *waiter)
+void remove_waiter(struct rt_mutex *lock,
+                  struct rt_mutex_waiter *waiter)
 {
        int first = (waiter == rt_mutex_top_waiter(lock));
        struct task_struct *owner = rt_mutex_owner(lock);
index 9c75856e791ee91a0e34dbdc0079a8297c9574ff..242ec7ee740b0aae5b624c89df610084667c28b1 100644 (file)
@@ -112,6 +112,29 @@ static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock)
        return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING;
 }
 
+/*
+ * We can speed up the acquire/release, if the architecture
+ * supports cmpxchg and if there's no debugging state to be set up
+ */
+#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
+# define rt_mutex_cmpxchg(l,c,n)       (cmpxchg(&l->owner, c, n) == c)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+       do {
+               owner = *p;
+       } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
+}
+#else
+# define rt_mutex_cmpxchg(l,c,n)       (0)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       lock->owner = (struct task_struct *)
+                       ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
+}
+#endif
+
 /*
  * PI-futex support (proxy locking functions, etc.):
  */
@@ -120,4 +143,15 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
                                       struct task_struct *proxy_owner);
 extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
                                  struct task_struct *proxy_owner);
+
+extern void rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
+                              unsigned long mask);
+extern void __rt_mutex_adjust_prio(struct task_struct *task);
+extern int rt_mutex_adjust_prio_chain(struct task_struct *task,
+                                     int deadlock_detect,
+                                     struct rt_mutex *orig_lock,
+                                     struct rt_mutex_waiter *orig_waiter,
+                                     struct task_struct *top_task);
+extern void remove_waiter(struct rt_mutex *lock,
+                         struct rt_mutex_waiter *waiter);
 #endif
index 291ded556aa034fffb7bf7c25799e9d7bb95eaf2..9a87886b022eb42ab486cd4749a5da1043a91c36 100644 (file)
@@ -60,7 +60,7 @@ int down_write_trylock(struct rw_semaphore *sem)
        int ret = __down_write_trylock(sem);
 
        if (ret == 1)
-               rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
+               rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_);
        return ret;
 }
 
index 0227f1625a75d9cf0831138856ba7250b895d04d..799d23b4e35dacf56e118d82953102db54c0fdfb 100644 (file)
@@ -52,8 +52,9 @@
 #include <linux/tsacct_kern.h>
 #include <linux/kprobes.h>
 #include <linux/delayacct.h>
-#include <asm/tlb.h>
+#include <linux/reciprocal_div.h>
 
+#include <asm/tlb.h>
 #include <asm/unistd.h>
 
 /*
@@ -181,6 +182,27 @@ static unsigned int static_prio_timeslice(int static_prio)
                return SCALE_PRIO(DEF_TIMESLICE, static_prio);
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
+ * Since cpu_power is a 'constant', we can use a reciprocal divide.
+ */
+static inline u32 sg_div_cpu_power(const struct sched_group *sg, u32 load)
+{
+       return reciprocal_divide(load, sg->reciprocal_cpu_power);
+}
+
+/*
+ * Each time a sched group cpu_power is changed,
+ * we must compute its reciprocal value
+ */
+static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val)
+{
+       sg->__cpu_power += val;
+       sg->reciprocal_cpu_power = reciprocal_value(sg->__cpu_power);
+}
+#endif
+
 /*
  * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
  * to time slice values: [800ms ... 100ms ... 5ms]
@@ -223,6 +245,10 @@ struct rq {
        unsigned long raw_weighted_load;
 #ifdef CONFIG_SMP
        unsigned long cpu_load[3];
+       unsigned char idle_at_tick;
+#ifdef CONFIG_NO_HZ
+       unsigned char in_nohz_recently;
+#endif
 #endif
        unsigned long long nr_switches;
 
@@ -278,7 +304,8 @@ struct rq {
        struct lock_class_key rq_lock_key;
 };
 
-static DEFINE_PER_CPU(struct rq, runqueues);
+static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
+static DEFINE_MUTEX(sched_hotcpu_mutex);
 
 static inline int cpu_of(struct rq *rq)
 {
@@ -1049,6 +1076,17 @@ static void resched_task(struct task_struct *p)
        if (!tsk_is_polling(p))
                smp_send_reschedule(cpu);
 }
+
+static void resched_cpu(int cpu)
+{
+       struct rq *rq = cpu_rq(cpu);
+       unsigned long flags;
+
+       if (!spin_trylock_irqsave(&rq->lock, flags))
+               return;
+       resched_task(cpu_curr(cpu));
+       spin_unlock_irqrestore(&rq->lock, flags);
+}
 #else
 static inline void resched_task(struct task_struct *p)
 {
@@ -1241,7 +1279,8 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
                }
 
                /* Adjust by relative CPU power of the group */
-               avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
+               avg_load = sg_div_cpu_power(group,
+                               avg_load * SCHED_LOAD_SCALE);
 
                if (local_group) {
                        this_load = avg_load;
@@ -1368,7 +1407,16 @@ static int wake_idle(int cpu, struct task_struct *p)
        struct sched_domain *sd;
        int i;
 
-       if (idle_cpu(cpu))
+       /*
+        * If it is idle, then it is the best cpu to run this task.
+        *
+        * This cpu is also the best, if it has more than one task already.
+        * Siblings must be also busy(in most cases) as they didn't already
+        * pickup the extra load from this cpu and hence we need not check
+        * sibling runqueue info. This will avoid the checks and cache miss
+        * penalities associated with that.
+        */
+       if (idle_cpu(cpu) || cpu_rq(cpu)->nr_running > 1)
                return cpu;
 
        for_each_domain(cpu, sd) {
@@ -2352,12 +2400,13 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                }
 
                total_load += avg_load;
-               total_pwr += group->cpu_power;
+               total_pwr += group->__cpu_power;
 
                /* Adjust by relative CPU power of the group */
-               avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
+               avg_load = sg_div_cpu_power(group,
+                               avg_load * SCHED_LOAD_SCALE);
 
-               group_capacity = group->cpu_power / SCHED_LOAD_SCALE;
+               group_capacity = group->__cpu_power / SCHED_LOAD_SCALE;
 
                if (local_group) {
                        this_load = avg_load;
@@ -2468,8 +2517,8 @@ group_next:
        max_pull = min(max_load - avg_load, max_load - busiest_load_per_task);
 
        /* How much load to actually move to equalise the imbalance */
-       *imbalance = min(max_pull * busiest->cpu_power,
-                               (avg_load - this_load) * this->cpu_power)
+       *imbalance = min(max_pull * busiest->__cpu_power,
+                               (avg_load - this_load) * this->__cpu_power)
                        / SCHED_LOAD_SCALE;
 
        /*
@@ -2503,28 +2552,29 @@ small_imbalance:
                 * moving them.
                 */
 
-               pwr_now += busiest->cpu_power *
-                       min(busiest_load_per_task, max_load);
-               pwr_now += this->cpu_power *
-                       min(this_load_per_task, this_load);
+               pwr_now += busiest->__cpu_power *
+                               min(busiest_load_per_task, max_load);
+               pwr_now += this->__cpu_power *
+                               min(this_load_per_task, this_load);
                pwr_now /= SCHED_LOAD_SCALE;
 
                /* Amount of load we'd subtract */
-               tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
-                       busiest->cpu_power;
+               tmp = sg_div_cpu_power(busiest,
+                               busiest_load_per_task * SCHED_LOAD_SCALE);
                if (max_load > tmp)
-                       pwr_move += busiest->cpu_power *
+                       pwr_move += busiest->__cpu_power *
                                min(busiest_load_per_task, max_load - tmp);
 
                /* Amount of load we'd add */
-               if (max_load * busiest->cpu_power <
+               if (max_load * busiest->__cpu_power <
                                busiest_load_per_task * SCHED_LOAD_SCALE)
-                       tmp = max_load * busiest->cpu_power / this->cpu_power;
+                       tmp = sg_div_cpu_power(this,
+                                       max_load * busiest->__cpu_power);
                else
-                       tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
-                               this->cpu_power;
-               pwr_move += this->cpu_power *
-                       min(this_load_per_task, this_load + tmp);
+                       tmp = sg_div_cpu_power(this,
+                               busiest_load_per_task * SCHED_LOAD_SCALE);
+               pwr_move += this->__cpu_power *
+                               min(this_load_per_task, this_load + tmp);
                pwr_move /= SCHED_LOAD_SCALE;
 
                /* Move if we gain throughput */
@@ -2657,6 +2707,12 @@ redo:
                double_rq_unlock(this_rq, busiest);
                local_irq_restore(flags);
 
+               /*
+                * some other cpu did the load balance for us.
+                */
+               if (nr_moved && this_cpu != smp_processor_id())
+                       resched_cpu(this_cpu);
+
                /* All tasks on this runqueue were pinned by CPU affinity */
                if (unlikely(all_pinned)) {
                        cpu_clear(cpu_of(busiest), cpus);
@@ -2927,32 +2983,98 @@ static void update_load(struct rq *this_rq)
        }
 }
 
+#ifdef CONFIG_NO_HZ
+static struct {
+       atomic_t load_balancer;
+       cpumask_t  cpu_mask;
+} nohz ____cacheline_aligned = {
+       .load_balancer = ATOMIC_INIT(-1),
+       .cpu_mask = CPU_MASK_NONE,
+};
+
 /*
- * run_rebalance_domains is triggered when needed from the scheduler tick.
+ * This routine will try to nominate the ilb (idle load balancing)
+ * owner among the cpus whose ticks are stopped. ilb owner will do the idle
+ * load balancing on behalf of all those cpus. If all the cpus in the system
+ * go into this tickless mode, then there will be no ilb owner (as there is
+ * no need for one) and all the cpus will sleep till the next wakeup event
+ * arrives...
  *
+ * For the ilb owner, tick is not stopped. And this tick will be used
+ * for idle load balancing. ilb owner will still be part of
+ * nohz.cpu_mask..
+ *
+ * While stopping the tick, this cpu will become the ilb owner if there
+ * is no other owner. And will be the owner till that cpu becomes busy
+ * or if all cpus in the system stop their ticks at which point
+ * there is no need for ilb owner.
+ *
+ * When the ilb owner becomes busy, it nominates another owner, during the
+ * next busy scheduler_tick()
+ */
+int select_nohz_load_balancer(int stop_tick)
+{
+       int cpu = smp_processor_id();
+
+       if (stop_tick) {
+               cpu_set(cpu, nohz.cpu_mask);
+               cpu_rq(cpu)->in_nohz_recently = 1;
+
+               /*
+                * If we are going offline and still the leader, give up!
+                */
+               if (cpu_is_offline(cpu) &&
+                   atomic_read(&nohz.load_balancer) == cpu) {
+                       if (atomic_cmpxchg(&nohz.load_balancer, cpu, -1) != cpu)
+                               BUG();
+                       return 0;
+               }
+
+               /* time for ilb owner also to sleep */
+               if (cpus_weight(nohz.cpu_mask) == num_online_cpus()) {
+                       if (atomic_read(&nohz.load_balancer) == cpu)
+                               atomic_set(&nohz.load_balancer, -1);
+                       return 0;
+               }
+
+               if (atomic_read(&nohz.load_balancer) == -1) {
+                       /* make me the ilb owner */
+                       if (atomic_cmpxchg(&nohz.load_balancer, -1, cpu) == -1)
+                               return 1;
+               } else if (atomic_read(&nohz.load_balancer) == cpu)
+                       return 1;
+       } else {
+               if (!cpu_isset(cpu, nohz.cpu_mask))
+                       return 0;
+
+               cpu_clear(cpu, nohz.cpu_mask);
+
+               if (atomic_read(&nohz.load_balancer) == cpu)
+                       if (atomic_cmpxchg(&nohz.load_balancer, cpu, -1) != cpu)
+                               BUG();
+       }
+       return 0;
+}
+#endif
+
+static DEFINE_SPINLOCK(balancing);
+
+/*
  * It checks each scheduling domain to see if it is due to be balanced,
  * and initiates a balancing operation if so.
  *
  * Balancing parameters are set up in arch_init_sched_domains.
  */
-static DEFINE_SPINLOCK(balancing);
-
-static void run_rebalance_domains(struct softirq_action *h)
+static inline void rebalance_domains(int cpu, enum idle_type idle)
 {
-       int this_cpu = smp_processor_id(), balance = 1;
-       struct rq *this_rq = cpu_rq(this_cpu);
+       int balance = 1;
+       struct rq *rq = cpu_rq(cpu);
        unsigned long interval;
        struct sched_domain *sd;
-       /*
-        * We are idle if there are no processes running. This
-        * is valid even if we are the idle process (SMT).
-        */
-       enum idle_type idle = !this_rq->nr_running ?
-                               SCHED_IDLE : NOT_IDLE;
-       /* Earliest time when we have to call run_rebalance_domains again */
+       /* Earliest time when we have to do rebalance again */
        unsigned long next_balance = jiffies + 60*HZ;
 
-       for_each_domain(this_cpu, sd) {
+       for_each_domain(cpu, sd) {
                if (!(sd->flags & SD_LOAD_BALANCE))
                        continue;
 
@@ -2971,7 +3093,7 @@ static void run_rebalance_domains(struct softirq_action *h)
                }
 
                if (time_after_eq(jiffies, sd->last_balance + interval)) {
-                       if (load_balance(this_cpu, this_rq, sd, idle, &balance)) {
+                       if (load_balance(cpu, rq, sd, idle, &balance)) {
                                /*
                                 * We've pulled tasks over so either we're no
                                 * longer idle, or one of our SMT siblings is
@@ -2995,7 +3117,114 @@ out:
                if (!balance)
                        break;
        }
-       this_rq->next_balance = next_balance;
+       rq->next_balance = next_balance;
+}
+
+/*
+ * run_rebalance_domains is triggered when needed from the scheduler tick.
+ * In CONFIG_NO_HZ case, the idle load balance owner will do the
+ * rebalancing for all the cpus for whom scheduler ticks are stopped.
+ */
+static void run_rebalance_domains(struct softirq_action *h)
+{
+       int local_cpu = smp_processor_id();
+       struct rq *local_rq = cpu_rq(local_cpu);
+       enum idle_type idle = local_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE;
+
+       rebalance_domains(local_cpu, idle);
+
+#ifdef CONFIG_NO_HZ
+       /*
+        * If this cpu is the owner for idle load balancing, then do the
+        * balancing on behalf of the other idle cpus whose ticks are
+        * stopped.
+        */
+       if (local_rq->idle_at_tick &&
+           atomic_read(&nohz.load_balancer) == local_cpu) {
+               cpumask_t cpus = nohz.cpu_mask;
+               struct rq *rq;
+               int balance_cpu;
+
+               cpu_clear(local_cpu, cpus);
+               for_each_cpu_mask(balance_cpu, cpus) {
+                       /*
+                        * If this cpu gets work to do, stop the load balancing
+                        * work being done for other cpus. Next load
+                        * balancing owner will pick it up.
+                        */
+                       if (need_resched())
+                               break;
+
+                       rebalance_domains(balance_cpu, SCHED_IDLE);
+
+                       rq = cpu_rq(balance_cpu);
+                       if (time_after(local_rq->next_balance, rq->next_balance))
+                               local_rq->next_balance = rq->next_balance;
+               }
+       }
+#endif
+}
+
+/*
+ * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.
+ *
+ * In case of CONFIG_NO_HZ, this is the place where we nominate a new
+ * idle load balancing owner or decide to stop the periodic load balancing,
+ * if the whole system is idle.
+ */
+static inline void trigger_load_balance(int cpu)
+{
+       struct rq *rq = cpu_rq(cpu);
+#ifdef CONFIG_NO_HZ
+       /*
+        * If we were in the nohz mode recently and busy at the current
+        * scheduler tick, then check if we need to nominate new idle
+        * load balancer.
+        */
+       if (rq->in_nohz_recently && !rq->idle_at_tick) {
+               rq->in_nohz_recently = 0;
+
+               if (atomic_read(&nohz.load_balancer) == cpu) {
+                       cpu_clear(cpu, nohz.cpu_mask);
+                       atomic_set(&nohz.load_balancer, -1);
+               }
+
+               if (atomic_read(&nohz.load_balancer) == -1) {
+                       /*
+                        * simple selection for now: Nominate the
+                        * first cpu in the nohz list to be the next
+                        * ilb owner.
+                        *
+                        * TBD: Traverse the sched domains and nominate
+                        * the nearest cpu in the nohz.cpu_mask.
+                        */
+                       int ilb = first_cpu(nohz.cpu_mask);
+
+                       if (ilb != NR_CPUS)
+                               resched_cpu(ilb);
+               }
+       }
+
+       /*
+        * If this cpu is idle and doing idle load balancing for all the
+        * cpus with ticks stopped, is it time for that to stop?
+        */
+       if (rq->idle_at_tick && atomic_read(&nohz.load_balancer) == cpu &&
+           cpus_weight(nohz.cpu_mask) == num_online_cpus()) {
+               resched_cpu(cpu);
+               return;
+       }
+
+       /*
+        * If this cpu is idle and the idle load balancing is done by
+        * someone else, then no need raise the SCHED_SOFTIRQ
+        */
+       if (rq->idle_at_tick && atomic_read(&nohz.load_balancer) != cpu &&
+           cpu_isset(cpu, nohz.cpu_mask))
+               return;
+#endif
+       if (time_after_eq(jiffies, rq->next_balance))
+               raise_softirq(SCHED_SOFTIRQ);
 }
 #else
 /*
@@ -3218,16 +3447,17 @@ void scheduler_tick(void)
        unsigned long long now = sched_clock();
        struct task_struct *p = current;
        int cpu = smp_processor_id();
+       int idle_at_tick = idle_cpu(cpu);
        struct rq *rq = cpu_rq(cpu);
 
        update_cpu_clock(p, rq, now);
 
-       if (p != rq->idle)
+       if (!idle_at_tick)
                task_running_tick(rq, p);
 #ifdef CONFIG_SMP
        update_load(rq);
-       if (time_after_eq(jiffies, rq->next_balance))
-               raise_softirq(SCHED_SOFTIRQ);
+       rq->idle_at_tick = idle_at_tick;
+       trigger_load_balance(cpu);
 #endif
 }
 
@@ -4291,13 +4521,13 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
        struct task_struct *p;
        int retval;
 
-       lock_cpu_hotplug();
+       mutex_lock(&sched_hotcpu_mutex);
        read_lock(&tasklist_lock);
 
        p = find_process_by_pid(pid);
        if (!p) {
                read_unlock(&tasklist_lock);
-               unlock_cpu_hotplug();
+               mutex_unlock(&sched_hotcpu_mutex);
                return -ESRCH;
        }
 
@@ -4324,7 +4554,7 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
 
 out_unlock:
        put_task_struct(p);
-       unlock_cpu_hotplug();
+       mutex_unlock(&sched_hotcpu_mutex);
        return retval;
 }
 
@@ -4381,7 +4611,7 @@ long sched_getaffinity(pid_t pid, cpumask_t *mask)
        struct task_struct *p;
        int retval;
 
-       lock_cpu_hotplug();
+       mutex_lock(&sched_hotcpu_mutex);
        read_lock(&tasklist_lock);
 
        retval = -ESRCH;
@@ -4397,7 +4627,7 @@ long sched_getaffinity(pid_t pid, cpumask_t *mask)
 
 out_unlock:
        read_unlock(&tasklist_lock);
-       unlock_cpu_hotplug();
+       mutex_unlock(&sched_hotcpu_mutex);
        if (retval)
                return retval;
 
@@ -4750,6 +4980,8 @@ void show_state_filter(unsigned long state_filter)
                        show_task(p);
        } while_each_thread(g, p);
 
+       touch_all_softlockup_watchdogs();
+
        read_unlock(&tasklist_lock);
        /*
         * Only show locks if all tasks are dumped:
@@ -5157,7 +5389,12 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
        struct rq *rq;
 
        switch (action) {
+       case CPU_LOCK_ACQUIRE:
+               mutex_lock(&sched_hotcpu_mutex);
+               break;
+
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
                if (IS_ERR(p))
                        return NOTIFY_BAD;
@@ -5171,12 +5408,14 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                break;
 
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                /* Strictly unneccessary, as first user will wake it. */
                wake_up_process(cpu_rq(cpu)->migration_thread);
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                if (!cpu_rq(cpu)->migration_thread)
                        break;
                /* Unbind it from offline cpu so it can run.  Fall thru. */
@@ -5187,6 +5426,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                break;
 
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                migrate_live_tasks(cpu);
                rq = cpu_rq(cpu);
                kthread_stop(rq->migration_thread);
@@ -5202,7 +5442,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                BUG_ON(rq->nr_running != 0);
 
                /* No need to migrate the tasks: it was best-effort if
-                * they didn't do lock_cpu_hotplug().  Just wake up
+                * they didn't take sched_hotcpu_mutex.  Just wake up
                 * the requestors. */
                spin_lock_irq(&rq->lock);
                while (!list_empty(&rq->migration_queue)) {
@@ -5216,6 +5456,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                spin_unlock_irq(&rq->lock);
                break;
 #endif
+       case CPU_LOCK_RELEASE:
+               mutex_unlock(&sched_hotcpu_mutex);
+               break;
        }
        return NOTIFY_OK;
 }
@@ -5304,7 +5547,7 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
                                break;
                        }
 
-                       if (!group->cpu_power) {
+                       if (!group->__cpu_power) {
                                printk("\n");
                                printk(KERN_ERR "ERROR: domain->cpu_power not "
                                                "set\n");
@@ -5481,7 +5724,7 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
                        continue;
 
                sg->cpumask = CPU_MASK_NONE;
-               sg->cpu_power = 0;
+               sg->__cpu_power = 0;
 
                for_each_cpu_mask(j, span) {
                        if (group_fn(j, cpu_map, NULL) != group)
@@ -6170,7 +6413,7 @@ next_sg:
                        continue;
                }
 
-               sg->cpu_power += sd->groups->cpu_power;
+               sg_inc_cpu_power(sg, sd->groups->__cpu_power);
        }
        sg = sg->next;
        if (sg != group_head)
@@ -6245,6 +6488,8 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
 
        child = sd->child;
 
+       sd->groups->__cpu_power = 0;
+
        /*
         * For perf policy, if the groups in child domain share resources
         * (for example cores sharing some portions of the cache hierarchy
@@ -6255,18 +6500,16 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
        if (!child || (!(sd->flags & SD_POWERSAVINGS_BALANCE) &&
                       (child->flags &
                        (SD_SHARE_CPUPOWER | SD_SHARE_PKG_RESOURCES)))) {
-               sd->groups->cpu_power = SCHED_LOAD_SCALE;
+               sg_inc_cpu_power(sd->groups, SCHED_LOAD_SCALE);
                return;
        }
 
-       sd->groups->cpu_power = 0;
-
        /*
         * add cpu_power of each child group to this groups cpu_power
         */
        group = child->groups;
        do {
-               sd->groups->cpu_power += group->cpu_power;
+               sg_inc_cpu_power(sd->groups, group->__cpu_power);
                group = group->next;
        } while (group != child->groups);
 }
@@ -6426,7 +6669,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
                        sd = &per_cpu(node_domains, j);
                        sd->groups = sg;
                }
-               sg->cpu_power = 0;
+               sg->__cpu_power = 0;
                sg->cpumask = nodemask;
                sg->next = sg;
                cpus_or(covered, covered, nodemask);
@@ -6454,7 +6697,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
                                "Can not alloc domain group for node %d\n", j);
                                goto error;
                        }
-                       sg->cpu_power = 0;
+                       sg->__cpu_power = 0;
                        sg->cpumask = tmp;
                        sg->next = prev->next;
                        cpus_or(covered, covered, tmp);
@@ -6591,10 +6834,10 @@ int arch_reinit_sched_domains(void)
 {
        int err;
 
-       lock_cpu_hotplug();
+       mutex_lock(&sched_hotcpu_mutex);
        detach_destroy_domains(&cpu_online_map);
        err = arch_init_sched_domains(&cpu_online_map);
-       unlock_cpu_hotplug();
+       mutex_unlock(&sched_hotcpu_mutex);
 
        return err;
 }
@@ -6673,14 +6916,20 @@ static int update_sched_domains(struct notifier_block *nfb,
 {
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                detach_destroy_domains(&cpu_online_map);
                return NOTIFY_OK;
 
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                /*
                 * Fall through and re-initialise the domains.
                 */
@@ -6699,12 +6948,12 @@ void __init sched_init_smp(void)
 {
        cpumask_t non_isolated_cpus;
 
-       lock_cpu_hotplug();
+       mutex_lock(&sched_hotcpu_mutex);
        arch_init_sched_domains(&cpu_online_map);
        cpus_andnot(non_isolated_cpus, cpu_possible_map, cpu_isolated_map);
        if (cpus_empty(non_isolated_cpus))
                cpu_set(smp_processor_id(), non_isolated_cpus);
-       unlock_cpu_hotplug();
+       mutex_unlock(&sched_hotcpu_mutex);
        /* XXX: Theoretical race here - CPU may be hotplugged now */
        hotcpu_notifier(update_sched_domains, 0);
 
index 2b4087d545a35cee2c3840801867458da4ee79e5..2ac3a668d9dd6adf8fb943ab8a0894f6b486e3fb 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 
 static struct kmem_cache *sigqueue_cachep;
 
-/*
- * In POSIX a signal is sent either to a specific thread (Linux task)
- * or to the process as a whole (Linux thread group).  How the signal
- * is sent determines whether it's to one thread or the whole group,
- * which determines which signal mask(s) are involved in blocking it
- * from being delivered until later.  When the signal is delivered,
- * either it's caught or ignored by a user handler or it has a default
- * effect that applies to the whole thread group (POSIX process).
- *
- * The possible effects an unblocked signal set to SIG_DFL can have are:
- *   ignore    - Nothing Happens
- *   terminate - kill the process, i.e. all threads in the group,
- *               similar to exit_group.  The group leader (only) reports
- *               WIFSIGNALED status to its parent.
- *   coredump  - write a core dump file describing all threads using
- *               the same mm and then kill all those threads
- *   stop      - stop all the threads in the group, i.e. TASK_STOPPED state
- *
- * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
- * Other signals when not blocked and set to SIG_DFL behaves as follows.
- * The job control signals also have other special effects.
- *
- *     +--------------------+------------------+
- *     |  POSIX signal      |  default action  |
- *     +--------------------+------------------+
- *     |  SIGHUP            |  terminate       |
- *     |  SIGINT            |  terminate       |
- *     |  SIGQUIT           |  coredump        |
- *     |  SIGILL            |  coredump        |
- *     |  SIGTRAP           |  coredump        |
- *     |  SIGABRT/SIGIOT    |  coredump        |
- *     |  SIGBUS            |  coredump        |
- *     |  SIGFPE            |  coredump        |
- *     |  SIGKILL           |  terminate(+)    |
- *     |  SIGUSR1           |  terminate       |
- *     |  SIGSEGV           |  coredump        |
- *     |  SIGUSR2           |  terminate       |
- *     |  SIGPIPE           |  terminate       |
- *     |  SIGALRM           |  terminate       |
- *     |  SIGTERM           |  terminate       |
- *     |  SIGCHLD           |  ignore          |
- *     |  SIGCONT           |  ignore(*)       |
- *     |  SIGSTOP           |  stop(*)(+)      |
- *     |  SIGTSTP           |  stop(*)         |
- *     |  SIGTTIN           |  stop(*)         |
- *     |  SIGTTOU           |  stop(*)         |
- *     |  SIGURG            |  ignore          |
- *     |  SIGXCPU           |  coredump        |
- *     |  SIGXFSZ           |  coredump        |
- *     |  SIGVTALRM         |  terminate       |
- *     |  SIGPROF           |  terminate       |
- *     |  SIGPOLL/SIGIO     |  terminate       |
- *     |  SIGSYS/SIGUNUSED  |  coredump        |
- *     |  SIGSTKFLT         |  terminate       |
- *     |  SIGWINCH          |  ignore          |
- *     |  SIGPWR            |  terminate       |
- *     |  SIGRTMIN-SIGRTMAX |  terminate       |
- *     +--------------------+------------------+
- *     |  non-POSIX signal  |  default action  |
- *     +--------------------+------------------+
- *     |  SIGEMT            |  coredump        |
- *     +--------------------+------------------+
- *
- * (+) For SIGKILL and SIGSTOP the action is "always", not just "default".
- * (*) Special job control effects:
- * When SIGCONT is sent, it resumes the process (all threads in the group)
- * from TASK_STOPPED state and also clears any pending/queued stop signals
- * (any of those marked with "stop(*)").  This happens regardless of blocking,
- * catching, or ignoring SIGCONT.  When any stop signal is sent, it clears
- * any pending/queued SIGCONT signals; this happens regardless of blocking,
- * catching, or ignored the stop signal, though (except for SIGSTOP) the
- * default action of stopping the process may happen later or never.
- */
-
-#ifdef SIGEMT
-#define M_SIGEMT       M(SIGEMT)
-#else
-#define M_SIGEMT       0
-#endif
-
-#if SIGRTMIN > BITS_PER_LONG
-#define M(sig) (1ULL << ((sig)-1))
-#else
-#define M(sig) (1UL << ((sig)-1))
-#endif
-#define T(sig, mask) (M(sig) & (mask))
-
-#define SIG_KERNEL_ONLY_MASK (\
-       M(SIGKILL)   |  M(SIGSTOP)                                   )
-
-#define SIG_KERNEL_STOP_MASK (\
-       M(SIGSTOP)   |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   )
-
-#define SIG_KERNEL_COREDUMP_MASK (\
-        M(SIGQUIT)   |  M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   | \
-        M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGBUS)    |  M(SIGSYS)    | \
-        M(SIGXCPU)   |  M(SIGXFSZ)   |  M_SIGEMT                     )
-
-#define SIG_KERNEL_IGNORE_MASK (\
-        M(SIGCONT)   |  M(SIGCHLD)   |  M(SIGWINCH)  |  M(SIGURG)    )
-
-#define sig_kernel_only(sig) \
-               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_ONLY_MASK))
-#define sig_kernel_coredump(sig) \
-               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_COREDUMP_MASK))
-#define sig_kernel_ignore(sig) \
-               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_IGNORE_MASK))
-#define sig_kernel_stop(sig) \
-               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_STOP_MASK))
-
-#define sig_needs_tasklist(sig)        ((sig) == SIGCONT)
-
-#define sig_user_defined(t, signr) \
-       (((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) &&  \
-        ((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
-
-#define sig_fatal(t, signr) \
-       (!T(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \
-        (t)->sighand->action[(signr)-1].sa.sa_handler == SIG_DFL)
 
 static int sig_ignored(struct task_struct *t, int sig)
 {
@@ -329,6 +209,16 @@ void flush_signals(struct task_struct *t)
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 }
 
+void ignore_signals(struct task_struct *t)
+{
+       int i;
+
+       for (i = 0; i < _NSIG; ++i)
+               t->sighand->action[i].sa.sa_handler = SIG_IGN;
+
+       flush_signals(t);
+}
+
 /*
  * Flush all handlers for a task.
  */
@@ -1033,17 +923,6 @@ void zap_other_threads(struct task_struct *p)
                if (t->exit_state)
                        continue;
 
-               /*
-                * We don't want to notify the parent, since we are
-                * killed as part of a thread group due to another
-                * thread doing an execve() or similar. So set the
-                * exit signal to -1 to allow immediate reaping of
-                * the process.  But don't detach the thread group
-                * leader.
-                */
-               if (t != p->group_leader)
-                       t->exit_signal = -1;
-
                /* SIGKILL will be handled before any pending SIGSTOP */
                sigaddset(&t->pending.signal, SIGKILL);
                signal_wake_up(t, 1);
index 8b75008e2bd84bc91db15681896ab1a631091378..0b9886a00e74ba33ed59cafb8b02bc9d01570575 100644 (file)
@@ -593,6 +593,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
                if (IS_ERR(p)) {
                        printk("ksoftirqd for %i failed\n", hotcpu);
@@ -602,16 +603,19 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
                per_cpu(ksoftirqd, hotcpu) = p;
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                wake_up_process(per_cpu(ksoftirqd, hotcpu));
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                if (!per_cpu(ksoftirqd, hotcpu))
                        break;
                /* Unbind so it can run.  Fall thru. */
                kthread_bind(per_cpu(ksoftirqd, hotcpu),
                             any_online_cpu(cpu_online_map));
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                p = per_cpu(ksoftirqd, hotcpu);
                per_cpu(ksoftirqd, hotcpu) = NULL;
                kthread_stop(p);
index 50afeb813305d76435e8c6852a80b5b9dc5c8cd9..0131e296ffb416435f7c54a935657c624a09d0c5 100644 (file)
@@ -34,12 +34,32 @@ static struct notifier_block panic_block = {
        .notifier_call = softlock_panic,
 };
 
+/*
+ * Returns seconds, approximately.  We don't need nanosecond
+ * resolution, and we don't need to waste time with a big divide when
+ * 2^30ns == 1.074s.
+ */
+static unsigned long get_timestamp(void)
+{
+       return sched_clock() >> 30;  /* 2^30 ~= 10^9 */
+}
+
 void touch_softlockup_watchdog(void)
 {
-       __raw_get_cpu_var(touch_timestamp) = jiffies;
+       __raw_get_cpu_var(touch_timestamp) = get_timestamp();
 }
 EXPORT_SYMBOL(touch_softlockup_watchdog);
 
+void touch_all_softlockup_watchdogs(void)
+{
+       int cpu;
+
+       /* Cause each CPU to re-update its timestamp rather than complain */
+       for_each_online_cpu(cpu)
+               per_cpu(touch_timestamp, cpu) = 0;
+}
+EXPORT_SYMBOL(touch_all_softlockup_watchdogs);
+
 /*
  * This callback runs from the timer interrupt, and checks
  * whether the watchdog thread has hung or not:
@@ -48,9 +68,18 @@ void softlockup_tick(void)
 {
        int this_cpu = smp_processor_id();
        unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
+       unsigned long print_timestamp;
+       unsigned long now;
+
+       if (touch_timestamp == 0) {
+               touch_softlockup_watchdog();
+               return;
+       }
+
+       print_timestamp = per_cpu(print_timestamp, this_cpu);
 
-       /* prevent double reports: */
-       if (per_cpu(print_timestamp, this_cpu) == touch_timestamp ||
+       /* report at most once a second */
+       if (print_timestamp < (touch_timestamp + 1) ||
                did_panic ||
                        !per_cpu(watchdog_task, this_cpu))
                return;
@@ -61,12 +90,14 @@ void softlockup_tick(void)
                return;
        }
 
+       now = get_timestamp();
+
        /* Wake up the high-prio watchdog task every second: */
-       if (time_after(jiffies, touch_timestamp + HZ))
+       if (now > (touch_timestamp + 1))
                wake_up_process(per_cpu(watchdog_task, this_cpu));
 
        /* Warn about unreasonable 10+ seconds delays: */
-       if (time_after(jiffies, touch_timestamp + 10*HZ)) {
+       if (now > (touch_timestamp + 10)) {
                per_cpu(print_timestamp, this_cpu) = touch_timestamp;
 
                spin_lock(&print_lock);
@@ -82,11 +113,14 @@ void softlockup_tick(void)
  */
 static int watchdog(void * __bind_cpu)
 {
-       struct sched_param param = { .sched_priority = 99 };
+       struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
        sched_setscheduler(current, SCHED_FIFO, &param);
        current->flags |= PF_NOFREEZE;
 
+       /* initialize timestamp */
+       touch_softlockup_watchdog();
+
        /*
         * Run briefly once per second to reset the softlockup timestamp.
         * If this gets delayed for more than 10 seconds then the
@@ -112,27 +146,31 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                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(touch_timestamp, hotcpu) = jiffies;
+               per_cpu(touch_timestamp, hotcpu) = 0;
                per_cpu(watchdog_task, hotcpu) = p;
                kthread_bind(p, hotcpu);
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                wake_up_process(per_cpu(watchdog_task, hotcpu));
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                if (!per_cpu(watchdog_task, hotcpu))
                        break;
                /* Unbind so it can run.  Fall thru. */
                kthread_bind(per_cpu(watchdog_task, hotcpu),
                             any_online_cpu(cpu_online_map));
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                p = per_cpu(watchdog_task, hotcpu);
                per_cpu(watchdog_task, hotcpu) = NULL;
                kthread_stop(p);
index 12458040e66500aec1040b91448c458972d08d69..daabb74ee0bc2648dda71286eb0331074af5f28b 100644 (file)
@@ -1,11 +1,12 @@
 /* Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation.
  * GPL v2 and any later version.
  */
-#include <linux/stop_machine.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/stop_machine.h>
 #include <linux/syscalls.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
@@ -208,3 +209,4 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(stop_machine_run);
index fe1f3ab204772a6b4f6aabfe62375554b30d39bb..cdb7e9457ba6596336b2618282f418bf13626e30 100644 (file)
@@ -134,19 +134,39 @@ static int notifier_chain_unregister(struct notifier_block **nl,
        return -ENOENT;
 }
 
+/**
+ * notifier_call_chain - Informs the registered notifiers about an event.
+ *     @nl:            Pointer to head of the blocking notifier chain
+ *     @val:           Value passed unmodified to notifier function
+ *     @v:             Pointer passed unmodified to notifier function
+ *     @nr_to_call:    Number of notifier functions to be called. Don't care
+ *                     value of this parameter is -1.
+ *     @nr_calls:      Records the number of notifications sent. Don't care
+ *                     value of this field is NULL.
+ *     @returns:       notifier_call_chain returns the value returned by the
+ *                     last notifier function called.
+ */
+
 static int __kprobes notifier_call_chain(struct notifier_block **nl,
-               unsigned long val, void *v)
+                                       unsigned long val, void *v,
+                                       int nr_to_call, int *nr_calls)
 {
        int ret = NOTIFY_DONE;
        struct notifier_block *nb, *next_nb;
 
        nb = rcu_dereference(*nl);
-       while (nb) {
+
+       while (nb && nr_to_call) {
                next_nb = rcu_dereference(nb->next);
                ret = nb->notifier_call(nb, val, v);
+
+               if (nr_calls)
+                       (*nr_calls)++;
+
                if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
                        break;
                nb = next_nb;
+               nr_to_call--;
        }
        return ret;
 }
@@ -205,10 +225,12 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
 
 /**
- *     atomic_notifier_call_chain - Call functions in an atomic notifier chain
+ *     __atomic_notifier_call_chain - Call functions in an atomic notifier chain
  *     @nh: Pointer to head of the atomic notifier chain
  *     @val: Value passed unmodified to notifier function
  *     @v: Pointer passed unmodified to notifier function
+ *     @nr_to_call: See the comment for notifier_call_chain.
+ *     @nr_calls: See the comment for notifier_call_chain.
  *
  *     Calls each function in a notifier chain in turn.  The functions
  *     run in an atomic context, so they must not block.
@@ -222,19 +244,27 @@ EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
  *     of the last notifier function called.
  */
  
-int __kprobes atomic_notifier_call_chain(struct atomic_notifier_head *nh,
-               unsigned long val, void *v)
+int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+                                       unsigned long val, void *v,
+                                       int nr_to_call, int *nr_calls)
 {
        int ret;
 
        rcu_read_lock();
-       ret = notifier_call_chain(&nh->head, val, v);
+       ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
        rcu_read_unlock();
        return ret;
 }
 
-EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
+EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
 
+int __kprobes atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+               unsigned long val, void *v)
+{
+       return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
+}
+
+EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
 /*
  *     Blocking notifier chain routines.  All access to the chain is
  *     synchronized by an rwsem.
@@ -304,10 +334,12 @@ int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
 EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
 
 /**
- *     blocking_notifier_call_chain - Call functions in a blocking notifier chain
+ *     __blocking_notifier_call_chain - Call functions in a blocking notifier chain
  *     @nh: Pointer to head of the blocking notifier chain
  *     @val: Value passed unmodified to notifier function
  *     @v: Pointer passed unmodified to notifier function
+ *     @nr_to_call: See comment for notifier_call_chain.
+ *     @nr_calls: See comment for notifier_call_chain.
  *
  *     Calls each function in a notifier chain in turn.  The functions
  *     run in a process context, so they are allowed to block.
@@ -320,8 +352,9 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
  *     of the last notifier function called.
  */
  
-int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
-               unsigned long val, void *v)
+int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+                                  unsigned long val, void *v,
+                                  int nr_to_call, int *nr_calls)
 {
        int ret = NOTIFY_DONE;
 
@@ -332,12 +365,19 @@ int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
         */
        if (rcu_dereference(nh->head)) {
                down_read(&nh->rwsem);
-               ret = notifier_call_chain(&nh->head, val, v);
+               ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
+                                       nr_calls);
                up_read(&nh->rwsem);
        }
        return ret;
 }
+EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
 
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+               unsigned long val, void *v)
+{
+       return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
+}
 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
 
 /*
@@ -383,10 +423,12 @@ int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
 EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
 
 /**
- *     raw_notifier_call_chain - Call functions in a raw notifier chain
+ *     __raw_notifier_call_chain - Call functions in a raw notifier chain
  *     @nh: Pointer to head of the raw notifier chain
  *     @val: Value passed unmodified to notifier function
  *     @v: Pointer passed unmodified to notifier function
+ *     @nr_to_call: See comment for notifier_call_chain.
+ *     @nr_calls: See comment for notifier_call_chain
  *
  *     Calls each function in a notifier chain in turn.  The functions
  *     run in an undefined context.
@@ -400,10 +442,19 @@ EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
  *     of the last notifier function called.
  */
 
+int __raw_notifier_call_chain(struct raw_notifier_head *nh,
+                             unsigned long val, void *v,
+                             int nr_to_call, int *nr_calls)
+{
+       return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+}
+
+EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
+
 int raw_notifier_call_chain(struct raw_notifier_head *nh,
                unsigned long val, void *v)
 {
-       return notifier_call_chain(&nh->head, val, v);
+       return __raw_notifier_call_chain(nh, val, v, -1, NULL);
 }
 
 EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
@@ -478,10 +529,12 @@ int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
 EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
 
 /**
- *     srcu_notifier_call_chain - Call functions in an SRCU notifier chain
+ *     __srcu_notifier_call_chain - Call functions in an SRCU notifier chain
  *     @nh: Pointer to head of the SRCU notifier chain
  *     @val: Value passed unmodified to notifier function
  *     @v: Pointer passed unmodified to notifier function
+ *     @nr_to_call: See comment for notifier_call_chain.
+ *     @nr_calls: See comment for notifier_call_chain
  *
  *     Calls each function in a notifier chain in turn.  The functions
  *     run in a process context, so they are allowed to block.
@@ -494,18 +547,25 @@ EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
  *     of the last notifier function called.
  */
 
-int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
-               unsigned long val, void *v)
+int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+                              unsigned long val, void *v,
+                              int nr_to_call, int *nr_calls)
 {
        int ret;
        int idx;
 
        idx = srcu_read_lock(&nh->srcu);
-       ret = notifier_call_chain(&nh->head, val, v);
+       ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
        srcu_read_unlock(&nh->srcu, idx);
        return ret;
 }
+EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
 
+int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+               unsigned long val, void *v)
+{
+       return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
+}
 EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
 
 /**
@@ -881,7 +941,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
 #ifdef CONFIG_SOFTWARE_SUSPEND
        case LINUX_REBOOT_CMD_SW_SUSPEND:
                {
-                       int ret = pm_suspend(PM_SUSPEND_DISK);
+                       int ret = hibernate();
                        unlock_kernel();
                        return ret;
                }
@@ -1292,7 +1352,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
 }
 
 /*
- * Samma på svenska..
+ * Samma på svenska..
  */
 asmlinkage long sys_setfsgid(gid_t gid)
 {
@@ -1923,6 +1983,16 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
        if (retval)
                return retval;
 
+       if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) {
+               /*
+                * The caller is asking for an immediate RLIMIT_CPU
+                * expiry.  But we use the zero value to mean "it was
+                * never set".  So let's cheat and make it one second
+                * instead
+                */
+               new_rlim.rlim_cur = 1;
+       }
+
        task_lock(current->group_leader);
        *old_rlim = new_rlim;
        task_unlock(current->group_leader);
@@ -1944,15 +2014,6 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
                unsigned long rlim_cur = new_rlim.rlim_cur;
                cputime_t cputime;
 
-               if (rlim_cur == 0) {
-                       /*
-                        * The caller is asking for an immediate RLIMIT_CPU
-                        * expiry.  But we use the zero value to mean "it was
-                        * never set".  So let's cheat and make it one second
-                        * instead
-                        */
-                       rlim_cur = 1;
-               }
                cputime = secs_to_cputime(rlim_cur);
                read_lock(&tasklist_lock);
                spin_lock_irq(&current->sighand->siglock);
index c904748f2290d8c48edca2dd451e1d71f4593b49..4073353abd4f8d05a017931ce6119dc552238237 100644 (file)
@@ -76,6 +76,8 @@ extern int pid_max_min, pid_max_max;
 extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
 extern int compat_log;
+extern int maps_protect;
+extern int sysctl_stat_interval;
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
@@ -603,6 +605,16 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
+#ifdef CONFIG_PROC_FS
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "maps_protect",
+               .data           = &maps_protect,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
 
        { .ctl_name = 0 }
 };
@@ -846,6 +858,17 @@ static ctl_table vm_table[] = {
                .extra2         = &one_hundred,
        },
 #endif
+#ifdef CONFIG_SMP
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "stat_interval",
+               .data           = &sysctl_stat_interval,
+               .maxlen         = sizeof(sysctl_stat_interval),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+#endif
 #if defined(CONFIG_X86_32) || \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
        {
index ba18ec4899bd92fe23a93716daf495bd2876025e..f04791f694081d16dab799ae16f5b3f405683e4d 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/timex.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/security.h>
 #include <linux/fs.h>
@@ -247,6 +246,36 @@ struct timespec current_fs_time(struct super_block *sb)
 }
 EXPORT_SYMBOL(current_fs_time);
 
+/*
+ * Convert jiffies to milliseconds and back.
+ *
+ * Avoid unnecessary multiplications/divisions in the
+ * two most common HZ cases:
+ */
+unsigned int inline jiffies_to_msecs(const unsigned long j)
+{
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+       return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+       return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
+#else
+       return (j * MSEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_msecs);
+
+unsigned int inline jiffies_to_usecs(const unsigned long j)
+{
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+       return (USEC_PER_SEC / HZ) * j;
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+       return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
+#else
+       return (j * USEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_usecs);
+
 /**
  * timespec_trunc - Truncate timespec to a granularity
  * @t: Timespec
@@ -472,36 +501,6 @@ struct timeval ns_to_timeval(const s64 nsec)
 }
 EXPORT_SYMBOL(ns_to_timeval);
 
-/*
- * Convert jiffies to milliseconds and back.
- *
- * Avoid unnecessary multiplications/divisions in the
- * two most common HZ cases:
- */
-unsigned int jiffies_to_msecs(const unsigned long j)
-{
-#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
-       return (MSEC_PER_SEC / HZ) * j;
-#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
-       return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
-#else
-       return (j * MSEC_PER_SEC) / HZ;
-#endif
-}
-EXPORT_SYMBOL(jiffies_to_msecs);
-
-unsigned int jiffies_to_usecs(const unsigned long j)
-{
-#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
-       return (USEC_PER_SEC / HZ) * j;
-#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
-       return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
-#else
-       return (j * USEC_PER_SEC) / HZ;
-#endif
-}
-EXPORT_SYMBOL(jiffies_to_usecs);
-
 /*
  * When we convert to jiffies then we interpret incoming values
  * the following way:
index 93bccba1f265e3b49df7d5bc54810ec5e3e39b2d..99b6034fc86b40defbc2ecde23647c014eedcd9c 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += ntp.o clocksource.o jiffies.o timer_list.o
+obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += tick-common.o
index fe5c7db2424700f8587284950cf8aecd926c06c6..3db5c3c460d74a845aa6f3ce0074cbd72a29f837 100644 (file)
@@ -74,15 +74,17 @@ static struct clocksource *watchdog;
 static struct timer_list watchdog_timer;
 static DEFINE_SPINLOCK(watchdog_lock);
 static cycle_t watchdog_last;
+static int watchdog_resumed;
+
 /*
- * Interval: 0.5sec Treshold: 0.0625s
+ * Interval: 0.5sec Threshold: 0.0625s
  */
 #define WATCHDOG_INTERVAL (HZ >> 1)
-#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
+#define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4)
 
 static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
 {
-       if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
+       if (delta > -WATCHDOG_THRESHOLD && delta < WATCHDOG_THRESHOLD)
                return;
 
        printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
@@ -98,15 +100,26 @@ static void clocksource_watchdog(unsigned long data)
        struct clocksource *cs, *tmp;
        cycle_t csnow, wdnow;
        int64_t wd_nsec, cs_nsec;
+       int resumed;
 
        spin_lock(&watchdog_lock);
 
+       resumed = watchdog_resumed;
+       if (unlikely(resumed))
+               watchdog_resumed = 0;
+
        wdnow = watchdog->read();
        wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask);
        watchdog_last = wdnow;
 
        list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
                csnow = cs->read();
+
+               if (unlikely(resumed)) {
+                       cs->wd_last = csnow;
+                       continue;
+               }
+
                /* Initialized ? */
                if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
                        if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
@@ -136,6 +149,13 @@ static void clocksource_watchdog(unsigned long data)
        }
        spin_unlock(&watchdog_lock);
 }
+static void clocksource_resume_watchdog(void)
+{
+       spin_lock(&watchdog_lock);
+       watchdog_resumed = 1;
+       spin_unlock(&watchdog_lock);
+}
+
 static void clocksource_check_watchdog(struct clocksource *cs)
 {
        struct clocksource *cse;
@@ -182,8 +202,33 @@ static void clocksource_check_watchdog(struct clocksource *cs)
        if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
                cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
 }
+
+static inline void clocksource_resume_watchdog(void) { }
 #endif
 
+/**
+ * clocksource_resume - resume the clocksource(s)
+ */
+void clocksource_resume(void)
+{
+       struct list_head *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocksource_lock, flags);
+
+       list_for_each(tmp, &clocksource_list) {
+               struct clocksource *cs;
+
+               cs = list_entry(tmp, struct clocksource, list);
+               if (cs->resume)
+                       cs->resume();
+       }
+
+       clocksource_resume_watchdog();
+
+       spin_unlock_irqrestore(&clocksource_lock, flags);
+}
+
 /**
  * clocksource_get_next - Returns the selected clocksource
  *
index bfda3f7f0716a9ad4915dd2191390f8bbf59ddd8..a96ec9ab3454e57acf53f4fa70b48ed84e634b8d 100644 (file)
@@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  */
 ktime_t tick_next_period;
 ktime_t tick_period;
-static int tick_do_timer_cpu = -1;
+int tick_do_timer_cpu __read_mostly = -1;
 DEFINE_SPINLOCK(tick_device_lock);
 
 /*
@@ -295,6 +295,12 @@ static void tick_shutdown(unsigned int *cpup)
                clockevents_exchange_device(dev, NULL);
                td->evtdev = NULL;
        }
+       /* Transfer the do_timer job away from this cpu */
+       if (*cpup == tick_do_timer_cpu) {
+               int cpu = first_cpu(cpu_online_map);
+
+               tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : -1;
+       }
        spin_unlock_irqrestore(&tick_device_lock, flags);
 }
 
index c9d203bde5182a116260819b440768d69b31da2e..bb13f2724905de18829636053518cee424e1191d 100644 (file)
@@ -5,6 +5,7 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
 extern spinlock_t tick_device_lock;
 extern ktime_t tick_next_period;
 extern ktime_t tick_period;
+extern int tick_do_timer_cpu __read_mostly;
 
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
index 51556b95f60f0db395cd7cdaf6a840479625fe1c..3483e6cb9549c26e17d1985c2700737914871779 100644 (file)
@@ -217,10 +217,30 @@ void tick_nohz_stop_sched_tick(void)
                 * the scheduler tick in nohz_restart_sched_tick.
                 */
                if (!ts->tick_stopped) {
+                       if (select_nohz_load_balancer(1)) {
+                               /*
+                                * sched tick not stopped!
+                                */
+                               cpu_clear(cpu, nohz_cpu_mask);
+                               goto out;
+                       }
+
                        ts->idle_tick = ts->sched_timer.expires;
                        ts->tick_stopped = 1;
                        ts->idle_jiffies = last_jiffies;
                }
+
+               /*
+                * If this cpu is the one which updates jiffies, then
+                * give up the assignment and let it be taken by the
+                * cpu which runs the tick timer next, which might be
+                * this cpu as well. If we don't drop this here the
+                * jiffies might be stale and do_timer() never
+                * invoked.
+                */
+               if (cpu == tick_do_timer_cpu)
+                       tick_do_timer_cpu = -1;
+
                /*
                 * calculate the expiry time for the next timer wheel
                 * timer
@@ -273,6 +293,7 @@ void tick_nohz_restart_sched_tick(void)
        now = ktime_get();
 
        local_irq_disable();
+       select_nohz_load_balancer(0);
        tick_do_update_jiffies64(now);
        cpu_clear(cpu, nohz_cpu_mask);
 
@@ -338,12 +359,24 @@ static void tick_nohz_handler(struct clock_event_device *dev)
 {
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        struct pt_regs *regs = get_irq_regs();
+       int cpu = smp_processor_id();
        ktime_t now = ktime_get();
 
        dev->next_event.tv64 = KTIME_MAX;
 
+       /*
+        * Check if the do_timer duty was dropped. We don't care about
+        * concurrency: This happens only when the cpu in charge went
+        * into a long sleep. If two cpus happen to assign themself to
+        * this duty, then the jiffies update is still serialized by
+        * xtime_lock.
+        */
+       if (unlikely(tick_do_timer_cpu == -1))
+               tick_do_timer_cpu = cpu;
+
        /* Check, if the jiffies need an update */
-       tick_do_update_jiffies64(now);
+       if (tick_do_timer_cpu == cpu)
+               tick_do_update_jiffies64(now);
 
        /*
         * When we are idle and the tick is stopped, we have to touch
@@ -431,9 +464,23 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
        struct hrtimer_cpu_base *base = timer->base->cpu_base;
        struct pt_regs *regs = get_irq_regs();
        ktime_t now = ktime_get();
+       int cpu = smp_processor_id();
+
+#ifdef CONFIG_NO_HZ
+       /*
+        * Check if the do_timer duty was dropped. We don't care about
+        * concurrency: This happens only when the cpu in charge went
+        * into a long sleep. If two cpus happen to assign themself to
+        * this duty, then the jiffies update is still serialized by
+        * xtime_lock.
+        */
+       if (unlikely(tick_do_timer_cpu == -1))
+               tick_do_timer_cpu = cpu;
+#endif
 
        /* Check, if the jiffies need an update */
-       tick_do_update_jiffies64(now);
+       if (tick_do_timer_cpu == cpu)
+               tick_do_update_jiffies64(now);
 
        /*
         * Do not call, when we are not in irq context and have
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
new file mode 100644 (file)
index 0000000..f9217bf
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ *  linux/kernel/time/timekeeping.c
+ *
+ *  Kernel timekeeping code and accessor functions
+ *
+ *  This code was moved from linux/kernel/timer.c.
+ *  Please see that file for copyright and history logs.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sysdev.h>
+#include <linux/clocksource.h>
+#include <linux/jiffies.h>
+#include <linux/time.h>
+#include <linux/tick.h>
+
+
+/*
+ * This read-write spinlock protects us from races in SMP while
+ * playing with xtime and avenrun.
+ */
+__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
+
+EXPORT_SYMBOL(xtime_lock);
+
+
+/*
+ * The current time
+ * wall_to_monotonic is what we need to add to xtime (or xtime corrected
+ * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
+ * at zero at system boot time, so wall_to_monotonic will be negative,
+ * however, we will ALWAYS keep the tv_nsec part positive so we can use
+ * the usual normalization.
+ */
+struct timespec xtime __attribute__ ((aligned (16)));
+struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+
+EXPORT_SYMBOL(xtime);
+
+
+static struct clocksource *clock; /* pointer to current clocksource */
+
+
+#ifdef CONFIG_GENERIC_TIME
+/**
+ * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
+ *
+ * private function, must hold xtime_lock lock when being
+ * called. Returns the number of nanoseconds since the
+ * last call to update_wall_time() (adjusted by NTP scaling)
+ */
+static inline s64 __get_nsec_offset(void)
+{
+       cycle_t cycle_now, cycle_delta;
+       s64 ns_offset;
+
+       /* read clocksource: */
+       cycle_now = clocksource_read(clock);
+
+       /* calculate the delta since the last update_wall_time: */
+       cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
+
+       /* convert to nanoseconds: */
+       ns_offset = cyc2ns(clock, cycle_delta);
+
+       return ns_offset;
+}
+
+/**
+ * __get_realtime_clock_ts - Returns the time of day in a timespec
+ * @ts:                pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec. Used by
+ * do_gettimeofday() and get_realtime_clock_ts().
+ */
+static inline void __get_realtime_clock_ts(struct timespec *ts)
+{
+       unsigned long seq;
+       s64 nsecs;
+
+       do {
+               seq = read_seqbegin(&xtime_lock);
+
+               *ts = xtime;
+               nsecs = __get_nsec_offset();
+
+       } while (read_seqretry(&xtime_lock, seq));
+
+       timespec_add_ns(ts, nsecs);
+}
+
+/**
+ * getnstimeofday - Returns the time of day in a timespec
+ * @ts:                pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ */
+void getnstimeofday(struct timespec *ts)
+{
+       __get_realtime_clock_ts(ts);
+}
+
+EXPORT_SYMBOL(getnstimeofday);
+
+/**
+ * do_gettimeofday - Returns the time of day in a timeval
+ * @tv:                pointer to the timeval to be set
+ *
+ * NOTE: Users should be converted to using get_realtime_clock_ts()
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+       struct timespec now;
+
+       __get_realtime_clock_ts(&now);
+       tv->tv_sec = now.tv_sec;
+       tv->tv_usec = now.tv_nsec/1000;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+/**
+ * do_settimeofday - Sets the time of day
+ * @tv:                pointer to the timespec variable containing the new time
+ *
+ * Sets the time of day to the new time and update NTP and notify hrtimers
+ */
+int do_settimeofday(struct timespec *tv)
+{
+       unsigned long flags;
+       time_t wtm_sec, sec = tv->tv_sec;
+       long wtm_nsec, nsec = tv->tv_nsec;
+
+       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+               return -EINVAL;
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+
+       nsec -= __get_nsec_offset();
+
+       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+       set_normalized_timespec(&xtime, sec, nsec);
+       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+       clock->error = 0;
+       ntp_clear();
+
+       update_vsyscall(&xtime, clock);
+
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       /* signal hrtimers about time change */
+       clock_was_set();
+
+       return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/**
+ * change_clocksource - Swaps clocksources if a new one is available
+ *
+ * Accumulates current time interval and initializes new clocksource
+ */
+static void change_clocksource(void)
+{
+       struct clocksource *new;
+       cycle_t now;
+       u64 nsec;
+
+       new = clocksource_get_next();
+
+       if (clock == new)
+               return;
+
+       now = clocksource_read(new);
+       nsec =  __get_nsec_offset();
+       timespec_add_ns(&xtime, nsec);
+
+       clock = new;
+       clock->cycle_last = now;
+
+       clock->error = 0;
+       clock->xtime_nsec = 0;
+       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+
+       tick_clock_notify();
+
+       printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+              clock->name);
+}
+#else
+static inline void change_clocksource(void) { }
+#endif
+
+/**
+ * timekeeping_is_continuous - check to see if timekeeping is free running
+ */
+int timekeeping_is_continuous(void)
+{
+       unsigned long seq;
+       int ret;
+
+       do {
+               seq = read_seqbegin(&xtime_lock);
+
+               ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
+
+       } while (read_seqretry(&xtime_lock, seq));
+
+       return ret;
+}
+
+/**
+ * read_persistent_clock -  Return time in seconds from the persistent clock.
+ *
+ * Weak dummy function for arches that do not yet support it.
+ * Returns seconds from epoch using the battery backed persistent clock.
+ * Returns zero if unsupported.
+ *
+ *  XXX - Do be sure to remove it once all arches implement it.
+ */
+unsigned long __attribute__((weak)) read_persistent_clock(void)
+{
+       return 0;
+}
+
+/*
+ * timekeeping_init - Initializes the clocksource and common timekeeping values
+ */
+void __init timekeeping_init(void)
+{
+       unsigned long flags;
+       unsigned long sec = read_persistent_clock();
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+
+       ntp_clear();
+
+       clock = clocksource_get_next();
+       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+       clock->cycle_last = clocksource_read(clock);
+
+       xtime.tv_sec = sec;
+       xtime.tv_nsec = 0;
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+/* flag for if timekeeping is suspended */
+static int timekeeping_suspended;
+/* time in seconds when suspend began */
+static unsigned long timekeeping_suspend_time;
+
+/**
+ * timekeeping_resume - Resumes the generic timekeeping subsystem.
+ * @dev:       unused
+ *
+ * This is for the generic clocksource timekeeping.
+ * xtime/wall_to_monotonic/jiffies/etc are
+ * still managed by arch specific suspend/resume code.
+ */
+static int timekeeping_resume(struct sys_device *dev)
+{
+       unsigned long flags;
+       unsigned long now = read_persistent_clock();
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+
+       if (now && (now > timekeeping_suspend_time)) {
+               unsigned long sleep_length = now - timekeeping_suspend_time;
+
+               xtime.tv_sec += sleep_length;
+               wall_to_monotonic.tv_sec -= sleep_length;
+       }
+       /* re-base the last cycle value */
+       clock->cycle_last = clocksource_read(clock);
+       clock->error = 0;
+       timekeeping_suspended = 0;
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       touch_softlockup_watchdog();
+
+       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
+
+       /* Resume hrtimers */
+       hres_timers_resume();
+
+       return 0;
+}
+
+static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
+{
+       unsigned long flags;
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+       timekeeping_suspended = 1;
+       timekeeping_suspend_time = read_persistent_clock();
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+
+       return 0;
+}
+
+/* sysfs resume/suspend bits for timekeeping */
+static struct sysdev_class timekeeping_sysclass = {
+       .resume         = timekeeping_resume,
+       .suspend        = timekeeping_suspend,
+       set_kset_name("timekeeping"),
+};
+
+static struct sys_device device_timer = {
+       .id             = 0,
+       .cls            = &timekeeping_sysclass,
+};
+
+static int __init timekeeping_init_device(void)
+{
+       int error = sysdev_class_register(&timekeeping_sysclass);
+       if (!error)
+               error = sysdev_register(&device_timer);
+       return error;
+}
+
+device_initcall(timekeeping_init_device);
+
+/*
+ * If the error is already larger, we look ahead even further
+ * to compensate for late or lost adjustments.
+ */
+static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
+                                                s64 *offset)
+{
+       s64 tick_error, i;
+       u32 look_ahead, adj;
+       s32 error2, mult;
+
+       /*
+        * Use the current error value to determine how much to look ahead.
+        * The larger the error the slower we adjust for it to avoid problems
+        * with losing too many ticks, otherwise we would overadjust and
+        * produce an even larger error.  The smaller the adjustment the
+        * faster we try to adjust for it, as lost ticks can do less harm
+        * here.  This is tuned so that an error of about 1 msec is adusted
+        * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
+        */
+       error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
+       error2 = abs(error2);
+       for (look_ahead = 0; error2 > 0; look_ahead++)
+               error2 >>= 2;
+
+       /*
+        * Now calculate the error in (1 << look_ahead) ticks, but first
+        * remove the single look ahead already included in the error.
+        */
+       tick_error = current_tick_length() >>
+               (TICK_LENGTH_SHIFT - clock->shift + 1);
+       tick_error -= clock->xtime_interval >> 1;
+       error = ((error - tick_error) >> look_ahead) + tick_error;
+
+       /* Finally calculate the adjustment shift value.  */
+       i = *interval;
+       mult = 1;
+       if (error < 0) {
+               error = -error;
+               *interval = -*interval;
+               *offset = -*offset;
+               mult = -1;
+       }
+       for (adj = 0; error > i; adj++)
+               error >>= 1;
+
+       *interval <<= adj;
+       *offset <<= adj;
+       return mult << adj;
+}
+
+/*
+ * Adjust the multiplier to reduce the error value,
+ * this is optimized for the most common adjustments of -1,0,1,
+ * for other values we can do a bit more work.
+ */
+static void clocksource_adjust(struct clocksource *clock, s64 offset)
+{
+       s64 error, interval = clock->cycle_interval;
+       int adj;
+
+       error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
+       if (error > interval) {
+               error >>= 2;
+               if (likely(error <= interval))
+                       adj = 1;
+               else
+                       adj = clocksource_bigadjust(error, &interval, &offset);
+       } else if (error < -interval) {
+               error >>= 2;
+               if (likely(error >= -interval)) {
+                       adj = -1;
+                       interval = -interval;
+                       offset = -offset;
+               } else
+                       adj = clocksource_bigadjust(error, &interval, &offset);
+       } else
+               return;
+
+       clock->mult += adj;
+       clock->xtime_interval += interval;
+       clock->xtime_nsec -= offset;
+       clock->error -= (interval - offset) <<
+                       (TICK_LENGTH_SHIFT - clock->shift);
+}
+
+/**
+ * update_wall_time - Uses the current clocksource to increment the wall time
+ *
+ * Called from the timer interrupt, must hold a write on xtime_lock.
+ */
+void update_wall_time(void)
+{
+       cycle_t offset;
+
+       /* Make sure we're fully resumed: */
+       if (unlikely(timekeeping_suspended))
+               return;
+
+#ifdef CONFIG_GENERIC_TIME
+       offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
+#else
+       offset = clock->cycle_interval;
+#endif
+       clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
+
+       /* normally this loop will run just once, however in the
+        * case of lost or late ticks, it will accumulate correctly.
+        */
+       while (offset >= clock->cycle_interval) {
+               /* accumulate one interval */
+               clock->xtime_nsec += clock->xtime_interval;
+               clock->cycle_last += clock->cycle_interval;
+               offset -= clock->cycle_interval;
+
+               if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
+                       clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
+                       xtime.tv_sec++;
+                       second_overflow();
+               }
+
+               /* interpolator bits */
+               time_interpolator_update(clock->xtime_interval
+                                               >> clock->shift);
+
+               /* accumulate error between NTP and clock interval */
+               clock->error += current_tick_length();
+               clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
+       }
+
+       /* correct the clock when NTP error is too big */
+       clocksource_adjust(clock, offset);
+
+       /* store full nanoseconds into xtime */
+       xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
+       clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
+
+       /* check to see if there is a new clocksource to use */
+       change_clocksource();
+       update_vsyscall(&xtime, clock);
+}
index 59df5e8555a8a40d25321bb9569612e8a29f68b2..8bbcfb77f7d22acb65caa4343bffe3df573a4bcf 100644 (file)
@@ -38,17 +38,12 @@ DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
 
 static void print_name_offset(struct seq_file *m, void *sym)
 {
-       unsigned long addr = (unsigned long)sym;
-       char namebuf[KSYM_NAME_LEN+1];
-       unsigned long size, offset;
-       const char *sym_name;
-       char *modname;
-
-       sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
-       if (sym_name)
-               SEQ_printf(m, "%s", sym_name);
-       else
+       char symname[KSYM_NAME_LEN+1];
+
+       if (lookup_symbol_name((unsigned long)sym, symname) < 0)
                SEQ_printf(m, "<%p>", sym);
+       else
+               SEQ_printf(m, "%s", symname);
 }
 
 static void
@@ -70,7 +65,7 @@ print_timer(struct seq_file *m, struct hrtimer *timer, int idx, u64 now)
        SEQ_printf(m, ", %s/%d", tmp, timer->start_pid);
 #endif
        SEQ_printf(m, "\n");
-       SEQ_printf(m, " # expires at %Ld nsecs [in %Ld nsecs]\n",
+       SEQ_printf(m, " # expires at %Lu nsecs [in %Lu nsecs]\n",
                (unsigned long long)ktime_to_ns(timer->expires),
                (unsigned long long)(ktime_to_ns(timer->expires) - now));
 }
@@ -116,14 +111,14 @@ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
 {
        SEQ_printf(m, "  .index:      %d\n",
                        base->index);
-       SEQ_printf(m, "  .resolution: %Ld nsecs\n",
+       SEQ_printf(m, "  .resolution: %Lu nsecs\n",
                        (unsigned long long)ktime_to_ns(base->resolution));
        SEQ_printf(m,   "  .get_time:   ");
        print_name_offset(m, base->get_time);
        SEQ_printf(m,   "\n");
 #ifdef CONFIG_HIGH_RES_TIMERS
-       SEQ_printf(m, "  .offset:     %Ld nsecs\n",
-                       ktime_to_ns(base->offset));
+       SEQ_printf(m, "  .offset:     %Lu nsecs\n",
+                  (unsigned long long) ktime_to_ns(base->offset));
 #endif
        SEQ_printf(m,   "active timers:\n");
        print_active_timers(m, base, now);
@@ -140,10 +135,11 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
                print_base(m, cpu_base->clock_base + i, now);
        }
 #define P(x) \
-       SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(cpu_base->x))
+       SEQ_printf(m, "  .%-15s: %Lu\n", #x, \
+                  (unsigned long long)(cpu_base->x))
 #define P_ns(x) \
-       SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
-               (u64)(ktime_to_ns(cpu_base->x)))
+       SEQ_printf(m, "  .%-15s: %Lu nsecs\n", #x, \
+                  (unsigned long long)(ktime_to_ns(cpu_base->x)))
 
 #ifdef CONFIG_HIGH_RES_TIMERS
        P_ns(expires_next);
@@ -155,10 +151,11 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
 
 #ifdef CONFIG_TICK_ONESHOT
 # define P(x) \
-       SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(ts->x))
+       SEQ_printf(m, "  .%-15s: %Lu\n", #x, \
+                  (unsigned long long)(ts->x))
 # define P_ns(x) \
-       SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
-               (u64)(ktime_to_ns(ts->x)))
+       SEQ_printf(m, "  .%-15s: %Lu nsecs\n", #x, \
+                  (unsigned long long)(ktime_to_ns(ts->x)))
        {
                struct tick_sched *ts = tick_get_tick_sched(cpu);
                P(nohz_mode);
@@ -172,7 +169,8 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
                P(last_jiffies);
                P(next_jiffies);
                P_ns(idle_expires);
-               SEQ_printf(m, "jiffies: %Ld\n", (u64)jiffies);
+               SEQ_printf(m, "jiffies: %Lu\n",
+                          (unsigned long long)jiffies);
        }
 #endif
 
index 1bc4882e28e03ac4150a467efe3afa6410ea3a61..868f1bceb07ff60bfb87ec2be8d5729a70ece0bd 100644 (file)
@@ -257,16 +257,12 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
 
 static void print_name_offset(struct seq_file *m, unsigned long addr)
 {
-       char namebuf[KSYM_NAME_LEN+1];
-       unsigned long size, offset;
-       const char *sym_name;
-       char *modname;
-
-       sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
-       if (sym_name)
-               seq_printf(m, "%s", sym_name);
-       else
+       char symname[KSYM_NAME_LEN+1];
+
+       if (lookup_symbol_name(addr, symname) < 0)
                seq_printf(m, "<%p>", (void *)addr);
+       else
+               seq_printf(m, "%s", symname);
 }
 
 static int tstats_show(struct seq_file *m, void *v)
index b22bd39740dd2e44a603deae1951e4c2be3cb415..59a28b1752f801355fccb68f5b94ca4758cf9958 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/timer.c
  *
- *  Kernel internal timers, kernel timekeeping, basic process system calls
+ *  Kernel internal timers, basic process system calls
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
@@ -74,7 +74,7 @@ struct tvec_t_base_s {
        tvec_t tv3;
        tvec_t tv4;
        tvec_t tv5;
-} ____cacheline_aligned_in_smp;
+} ____cacheline_aligned;
 
 typedef struct tvec_t_base_s tvec_base_t;
 
@@ -82,6 +82,37 @@ tvec_base_t boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
 static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 
+/*
+ * Note that all tvec_bases is 2 byte aligned and lower bit of
+ * base in timer_list is guaranteed to be zero. Use the LSB for
+ * the new flag to indicate whether the timer is deferrable
+ */
+#define TBASE_DEFERRABLE_FLAG          (0x1)
+
+/* Functions below help us manage 'deferrable' flag */
+static inline unsigned int tbase_get_deferrable(tvec_base_t *base)
+{
+       return (unsigned int)((unsigned long)base & TBASE_DEFERRABLE_FLAG);
+}
+
+static inline tvec_base_t *tbase_get_base(tvec_base_t *base)
+{
+       return (tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG);
+}
+
+static inline void timer_set_deferrable(struct timer_list *timer)
+{
+       timer->base = (tvec_base_t *)((unsigned long)timer->base |
+                                      TBASE_DEFERRABLE_FLAG);
+}
+
+static inline void
+timer_set_base(struct timer_list *timer, tvec_base_t *new_base)
+{
+       timer->base = (tvec_base_t *)((unsigned long)new_base |
+                                     tbase_get_deferrable(timer->base));
+}
+
 /**
  * __round_jiffies - function to round jiffies to a full second
  * @j: the time in (absolute) jiffies that should be rounded
@@ -295,6 +326,13 @@ void fastcall init_timer(struct timer_list *timer)
 }
 EXPORT_SYMBOL(init_timer);
 
+void fastcall init_timer_deferrable(struct timer_list *timer)
+{
+       init_timer(timer);
+       timer_set_deferrable(timer);
+}
+EXPORT_SYMBOL(init_timer_deferrable);
+
 static inline void detach_timer(struct timer_list *timer,
                                int clear_pending)
 {
@@ -325,10 +363,11 @@ static tvec_base_t *lock_timer_base(struct timer_list *timer,
        tvec_base_t *base;
 
        for (;;) {
-               base = timer->base;
+               tvec_base_t *prelock_base = timer->base;
+               base = tbase_get_base(prelock_base);
                if (likely(base != NULL)) {
                        spin_lock_irqsave(&base->lock, *flags);
-                       if (likely(base == timer->base))
+                       if (likely(prelock_base == timer->base))
                                return base;
                        /* The timer has migrated to another CPU */
                        spin_unlock_irqrestore(&base->lock, *flags);
@@ -365,11 +404,11 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
                 */
                if (likely(base->running_timer != timer)) {
                        /* See the comment in lock_timer_base() */
-                       timer->base = NULL;
+                       timer_set_base(timer, NULL);
                        spin_unlock(&base->lock);
                        base = new_base;
                        spin_lock(&base->lock);
-                       timer->base = base;
+                       timer_set_base(timer, base);
                }
        }
 
@@ -397,7 +436,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
        timer_stats_timer_set_start_info(timer);
        BUG_ON(timer_pending(timer) || !timer->function);
        spin_lock_irqsave(&base->lock, flags);
-       timer->base = base;
+       timer_set_base(timer, base);
        internal_add_timer(base, timer);
        spin_unlock_irqrestore(&base->lock, flags);
 }
@@ -550,7 +589,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
         * don't have to detach them individually.
         */
        list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
-               BUG_ON(timer->base != base);
+               BUG_ON(tbase_get_base(timer->base) != base);
                internal_add_timer(base, timer);
        }
 
@@ -590,7 +629,7 @@ static inline void __run_timers(tvec_base_t *base)
                        void (*fn)(unsigned long);
                        unsigned long data;
 
-                       timer = list_entry(head->next,struct timer_list,entry);
+                       timer = list_first_entry(head, struct timer_list,entry);
                        fn = timer->function;
                        data = timer->data;
 
@@ -636,6 +675,9 @@ static unsigned long __next_timer_interrupt(tvec_base_t *base)
        index = slot = timer_jiffies & TVR_MASK;
        do {
                list_for_each_entry(nte, base->tv1.vec + slot, entry) {
+                       if (tbase_get_deferrable(nte->base))
+                               continue;
+
                        found = 1;
                        expires = nte->expires;
                        /* Look at the cascade bucket(s)? */
@@ -752,455 +794,6 @@ unsigned long next_timer_interrupt(void)
 
 #endif
 
-/******************************************************************/
-
-/* 
- * The current time 
- * wall_to_monotonic is what we need to add to xtime (or xtime corrected 
- * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
- * at zero at system boot time, so wall_to_monotonic will be negative,
- * however, we will ALWAYS keep the tv_nsec part positive so we can use
- * the usual normalization.
- */
-struct timespec xtime __attribute__ ((aligned (16)));
-struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
-
-EXPORT_SYMBOL(xtime);
-
-
-/* XXX - all of this timekeeping code should be later moved to time.c */
-#include <linux/clocksource.h>
-static struct clocksource *clock; /* pointer to current clocksource */
-
-#ifdef CONFIG_GENERIC_TIME
-/**
- * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
- *
- * private function, must hold xtime_lock lock when being
- * called. Returns the number of nanoseconds since the
- * last call to update_wall_time() (adjusted by NTP scaling)
- */
-static inline s64 __get_nsec_offset(void)
-{
-       cycle_t cycle_now, cycle_delta;
-       s64 ns_offset;
-
-       /* read clocksource: */
-       cycle_now = clocksource_read(clock);
-
-       /* calculate the delta since the last update_wall_time: */
-       cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
-
-       /* convert to nanoseconds: */
-       ns_offset = cyc2ns(clock, cycle_delta);
-
-       return ns_offset;
-}
-
-/**
- * __get_realtime_clock_ts - Returns the time of day in a timespec
- * @ts:                pointer to the timespec to be set
- *
- * Returns the time of day in a timespec. Used by
- * do_gettimeofday() and get_realtime_clock_ts().
- */
-static inline void __get_realtime_clock_ts(struct timespec *ts)
-{
-       unsigned long seq;
-       s64 nsecs;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-
-               *ts = xtime;
-               nsecs = __get_nsec_offset();
-
-       } while (read_seqretry(&xtime_lock, seq));
-
-       timespec_add_ns(ts, nsecs);
-}
-
-/**
- * getnstimeofday - Returns the time of day in a timespec
- * @ts:                pointer to the timespec to be set
- *
- * Returns the time of day in a timespec.
- */
-void getnstimeofday(struct timespec *ts)
-{
-       __get_realtime_clock_ts(ts);
-}
-
-EXPORT_SYMBOL(getnstimeofday);
-
-/**
- * do_gettimeofday - Returns the time of day in a timeval
- * @tv:                pointer to the timeval to be set
- *
- * NOTE: Users should be converted to using get_realtime_clock_ts()
- */
-void do_gettimeofday(struct timeval *tv)
-{
-       struct timespec now;
-
-       __get_realtime_clock_ts(&now);
-       tv->tv_sec = now.tv_sec;
-       tv->tv_usec = now.tv_nsec/1000;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-/**
- * do_settimeofday - Sets the time of day
- * @tv:                pointer to the timespec variable containing the new time
- *
- * Sets the time of day to the new time and update NTP and notify hrtimers
- */
-int do_settimeofday(struct timespec *tv)
-{
-       unsigned long flags;
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
-
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       nsec -= __get_nsec_offset();
-
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-       clock->error = 0;
-       ntp_clear();
-
-       update_vsyscall(&xtime, clock);
-
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       /* signal hrtimers about time change */
-       clock_was_set();
-
-       return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/**
- * change_clocksource - Swaps clocksources if a new one is available
- *
- * Accumulates current time interval and initializes new clocksource
- */
-static void change_clocksource(void)
-{
-       struct clocksource *new;
-       cycle_t now;
-       u64 nsec;
-
-       new = clocksource_get_next();
-
-       if (clock == new)
-               return;
-
-       now = clocksource_read(new);
-       nsec =  __get_nsec_offset();
-       timespec_add_ns(&xtime, nsec);
-
-       clock = new;
-       clock->cycle_last = now;
-
-       clock->error = 0;
-       clock->xtime_nsec = 0;
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-
-       tick_clock_notify();
-
-       printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-              clock->name);
-}
-#else
-static inline void change_clocksource(void) { }
-#endif
-
-/**
- * timekeeping_is_continuous - check to see if timekeeping is free running
- */
-int timekeeping_is_continuous(void)
-{
-       unsigned long seq;
-       int ret;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-
-               ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
-
-       } while (read_seqretry(&xtime_lock, seq));
-
-       return ret;
-}
-
-/**
- * read_persistent_clock -  Return time in seconds from the persistent clock.
- *
- * Weak dummy function for arches that do not yet support it.
- * Returns seconds from epoch using the battery backed persistent clock.
- * Returns zero if unsupported.
- *
- *  XXX - Do be sure to remove it once all arches implement it.
- */
-unsigned long __attribute__((weak)) read_persistent_clock(void)
-{
-       return 0;
-}
-
-/*
- * timekeeping_init - Initializes the clocksource and common timekeeping values
- */
-void __init timekeeping_init(void)
-{
-       unsigned long flags;
-       unsigned long sec = read_persistent_clock();
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       ntp_clear();
-
-       clock = clocksource_get_next();
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-       clock->cycle_last = clocksource_read(clock);
-
-       xtime.tv_sec = sec;
-       xtime.tv_nsec = 0;
-       set_normalized_timespec(&wall_to_monotonic,
-               -xtime.tv_sec, -xtime.tv_nsec);
-
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-}
-
-/* flag for if timekeeping is suspended */
-static int timekeeping_suspended;
-/* time in seconds when suspend began */
-static unsigned long timekeeping_suspend_time;
-
-/**
- * timekeeping_resume - Resumes the generic timekeeping subsystem.
- * @dev:       unused
- *
- * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/etc are
- * still managed by arch specific suspend/resume code.
- */
-static int timekeeping_resume(struct sys_device *dev)
-{
-       unsigned long flags;
-       unsigned long now = read_persistent_clock();
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       if (now && (now > timekeeping_suspend_time)) {
-               unsigned long sleep_length = now - timekeeping_suspend_time;
-
-               xtime.tv_sec += sleep_length;
-               wall_to_monotonic.tv_sec -= sleep_length;
-       }
-       /* re-base the last cycle value */
-       clock->cycle_last = clocksource_read(clock);
-       clock->error = 0;
-       timekeeping_suspended = 0;
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       touch_softlockup_watchdog();
-
-       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-       /* Resume hrtimers */
-       hres_timers_resume();
-
-       return 0;
-}
-
-static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
-{
-       unsigned long flags;
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-       timekeeping_suspended = 1;
-       timekeeping_suspend_time = read_persistent_clock();
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
-
-       return 0;
-}
-
-/* sysfs resume/suspend bits for timekeeping */
-static struct sysdev_class timekeeping_sysclass = {
-       .resume         = timekeeping_resume,
-       .suspend        = timekeeping_suspend,
-       set_kset_name("timekeeping"),
-};
-
-static struct sys_device device_timer = {
-       .id             = 0,
-       .cls            = &timekeeping_sysclass,
-};
-
-static int __init timekeeping_init_device(void)
-{
-       int error = sysdev_class_register(&timekeeping_sysclass);
-       if (!error)
-               error = sysdev_register(&device_timer);
-       return error;
-}
-
-device_initcall(timekeeping_init_device);
-
-/*
- * If the error is already larger, we look ahead even further
- * to compensate for late or lost adjustments.
- */
-static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
-                                                s64 *offset)
-{
-       s64 tick_error, i;
-       u32 look_ahead, adj;
-       s32 error2, mult;
-
-       /*
-        * Use the current error value to determine how much to look ahead.
-        * The larger the error the slower we adjust for it to avoid problems
-        * with losing too many ticks, otherwise we would overadjust and
-        * produce an even larger error.  The smaller the adjustment the
-        * faster we try to adjust for it, as lost ticks can do less harm
-        * here.  This is tuned so that an error of about 1 msec is adusted
-        * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
-        */
-       error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
-       error2 = abs(error2);
-       for (look_ahead = 0; error2 > 0; look_ahead++)
-               error2 >>= 2;
-
-       /*
-        * Now calculate the error in (1 << look_ahead) ticks, but first
-        * remove the single look ahead already included in the error.
-        */
-       tick_error = current_tick_length() >>
-               (TICK_LENGTH_SHIFT - clock->shift + 1);
-       tick_error -= clock->xtime_interval >> 1;
-       error = ((error - tick_error) >> look_ahead) + tick_error;
-
-       /* Finally calculate the adjustment shift value.  */
-       i = *interval;
-       mult = 1;
-       if (error < 0) {
-               error = -error;
-               *interval = -*interval;
-               *offset = -*offset;
-               mult = -1;
-       }
-       for (adj = 0; error > i; adj++)
-               error >>= 1;
-
-       *interval <<= adj;
-       *offset <<= adj;
-       return mult << adj;
-}
-
-/*
- * Adjust the multiplier to reduce the error value,
- * this is optimized for the most common adjustments of -1,0,1,
- * for other values we can do a bit more work.
- */
-static void clocksource_adjust(struct clocksource *clock, s64 offset)
-{
-       s64 error, interval = clock->cycle_interval;
-       int adj;
-
-       error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
-       if (error > interval) {
-               error >>= 2;
-               if (likely(error <= interval))
-                       adj = 1;
-               else
-                       adj = clocksource_bigadjust(error, &interval, &offset);
-       } else if (error < -interval) {
-               error >>= 2;
-               if (likely(error >= -interval)) {
-                       adj = -1;
-                       interval = -interval;
-                       offset = -offset;
-               } else
-                       adj = clocksource_bigadjust(error, &interval, &offset);
-       } else
-               return;
-
-       clock->mult += adj;
-       clock->xtime_interval += interval;
-       clock->xtime_nsec -= offset;
-       clock->error -= (interval - offset) <<
-                       (TICK_LENGTH_SHIFT - clock->shift);
-}
-
-/**
- * update_wall_time - Uses the current clocksource to increment the wall time
- *
- * Called from the timer interrupt, must hold a write on xtime_lock.
- */
-static void update_wall_time(void)
-{
-       cycle_t offset;
-
-       /* Make sure we're fully resumed: */
-       if (unlikely(timekeeping_suspended))
-               return;
-
-#ifdef CONFIG_GENERIC_TIME
-       offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
-#else
-       offset = clock->cycle_interval;
-#endif
-       clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
-
-       /* normally this loop will run just once, however in the
-        * case of lost or late ticks, it will accumulate correctly.
-        */
-       while (offset >= clock->cycle_interval) {
-               /* accumulate one interval */
-               clock->xtime_nsec += clock->xtime_interval;
-               clock->cycle_last += clock->cycle_interval;
-               offset -= clock->cycle_interval;
-
-               if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
-                       clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
-                       xtime.tv_sec++;
-                       second_overflow();
-               }
-
-               /* interpolator bits */
-               time_interpolator_update(clock->xtime_interval
-                                               >> clock->shift);
-
-               /* accumulate error between NTP and clock interval */
-               clock->error += current_tick_length();
-               clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
-       }
-
-       /* correct the clock when NTP error is too big */
-       clocksource_adjust(clock, offset);
-
-       /* store full nanoseconds into xtime */
-       xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
-       clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
-
-       /* check to see if there is a new clocksource to use */
-       change_clocksource();
-       update_vsyscall(&xtime, clock);
-}
-
 /*
  * Called from the timer interrupt handler to charge one tick to the current 
  * process.  user_tick is 1 if the tick is user time, 0 for system.
@@ -1263,14 +856,6 @@ static inline void calc_load(unsigned long ticks)
        }
 }
 
-/*
- * This read-write spinlock protects us from races in SMP while
- * playing with xtime and avenrun.
- */
-__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
-
-EXPORT_SYMBOL(xtime_lock);
-
 /*
  * This function runs timers and the timer-tq in bottom half context.
  */
@@ -1617,6 +1202,13 @@ static int __devinit init_timers_cpu(int cpu)
                                                cpu_to_node(cpu));
                        if (!base)
                                return -ENOMEM;
+
+                       /* Make sure that tvec_base is 2 byte aligned */
+                       if (tbase_get_deferrable(base)) {
+                               WARN_ON(1);
+                               kfree(base);
+                               return -ENOMEM;
+                       }
                        memset(base, 0, sizeof(*base));
                        per_cpu(tvec_bases, cpu) = base;
                } else {
@@ -1656,9 +1248,9 @@ static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
        struct timer_list *timer;
 
        while (!list_empty(head)) {
-               timer = list_entry(head->next, struct timer_list, entry);
+               timer = list_first_entry(head, struct timer_list, entry);
                detach_timer(timer, 0);
-               timer->base = new_base;
+               timer_set_base(timer, new_base);
                internal_add_timer(new_base, timer);
        }
 }
@@ -1701,11 +1293,13 @@ static int __cpuinit timer_cpu_notify(struct notifier_block *self,
        long cpu = (long)hcpu;
        switch(action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                if (init_timers_cpu(cpu) < 0)
                        return NOTIFY_BAD;
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                migrate_timers(cpu);
                break;
 #endif
@@ -1905,6 +1499,8 @@ unregister_time_interpolator(struct time_interpolator *ti)
                prev = &curr->next;
        }
 
+       clocksource_resume();
+
        write_seqlock_irqsave(&xtime_lock, flags);
        if (ti == time_interpolator) {
                /* we lost the best time-interpolator: */
index 187e2a423878229b53e7c5310946621274901bf7..dd308ba4e03b90ce07e85c35a8f9be4e2d5365d0 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/mman.h>
-#include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
index c859164a699311a10021f37f06c369e34ac4f4d5..160c8c5136bd6a6607ccfae5cfc2e285fe5791c6 100644 (file)
@@ -31,59 +31,26 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
        return ns;
 }
 
-/*
- * unshare the current process' utsname namespace.
- * called only in sys_unshare()
- */
-int unshare_utsname(unsigned long unshare_flags, struct uts_namespace **new_uts)
-{
-       if (unshare_flags & CLONE_NEWUTS) {
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
-               *new_uts = clone_uts_ns(current->nsproxy->uts_ns);
-               if (!*new_uts)
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 /*
  * Copy task tsk's utsname namespace, or clone it if flags
  * specifies CLONE_NEWUTS.  In latter case, changes to the
  * utsname of this process won't be seen by parent, and vice
  * versa.
  */
-int copy_utsname(int flags, struct task_struct *tsk)
+struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
 {
-       struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
        struct uts_namespace *new_ns;
-       int err = 0;
-
-       if (!old_ns)
-               return 0;
 
+       BUG_ON(!old_ns);
        get_uts_ns(old_ns);
 
        if (!(flags & CLONE_NEWUTS))
-               return 0;
-
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
+               return old_ns;
 
        new_ns = clone_uts_ns(old_ns);
-       if (!new_ns) {
-               err = -ENOMEM;
-               goto out;
-       }
-       tsk->nsproxy->uts_ns = new_ns;
 
-out:
        put_uts_ns(old_ns);
-       return err;
+       return new_ns;
 }
 
 void free_uts_ns(struct kref *kref)
index 59a82f63275df037dd5bfb1062cffe317a698383..444ddbfaefc490839e2cf913cb688c7ebb9f0df9 100644 (file)
@@ -61,7 +61,7 @@ EXPORT_SYMBOL(remove_wait_queue);
  * The spin_unlock() itself is semi-permeable and only protects
  * one way (it only protects stuff inside the critical region and
  * stops them from bleeding out - it would still allow subsequent
- * loads to move into the the critical region).
+ * loads to move into the critical region).
  */
 void fastcall
 prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
index b6fa5e63085d65b42f46fe97735751b6f402cab4..fb56fedd5c0274a3458bd0e7cbc8ae4e0d86cf6d 100644 (file)
 /*
  * The per-CPU workqueue (if single thread, we always use the first
  * possible cpu).
- *
- * The sequence counters are for flush_scheduled_work().  It wants to wait
- * until all currently-scheduled works are completed, but it doesn't
- * want to be livelocked by new, incoming ones.  So it waits until
- * remove_sequence is >= the insert_sequence which pertained when
- * flush_scheduled_work() was called.
  */
 struct cpu_workqueue_struct {
 
        spinlock_t lock;
 
-       long remove_sequence;   /* Least-recently added (next to run) */
-       long insert_sequence;   /* Next to add */
-
        struct list_head worklist;
        wait_queue_head_t more_work;
-       wait_queue_head_t work_done;
+       struct work_struct *current_work;
 
        struct workqueue_struct *wq;
        struct task_struct *thread;
+       int should_stop;
 
        int run_depth;          /* Detect run_workqueue() recursion depth */
-
-       int freezeable;         /* Freeze the thread during suspend */
 } ____cacheline_aligned;
 
 /*
@@ -68,8 +58,10 @@ struct cpu_workqueue_struct {
  */
 struct workqueue_struct {
        struct cpu_workqueue_struct *cpu_wq;
+       struct list_head list;
        const char *name;
-       struct list_head list;  /* Empty if single thread */
+       int singlethread;
+       int freezeable;         /* Freeze threads during suspend */
 };
 
 /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove
@@ -77,106 +69,68 @@ struct workqueue_struct {
 static DEFINE_MUTEX(workqueue_mutex);
 static LIST_HEAD(workqueues);
 
-static int singlethread_cpu;
+static int singlethread_cpu __read_mostly;
+static cpumask_t cpu_singlethread_map __read_mostly;
+/* optimization, we could use cpu_possible_map */
+static cpumask_t cpu_populated_map __read_mostly;
 
 /* If it's single threaded, it isn't in the list of workqueues. */
 static inline int is_single_threaded(struct workqueue_struct *wq)
 {
-       return list_empty(&wq->list);
+       return wq->singlethread;
+}
+
+static const cpumask_t *wq_cpu_map(struct workqueue_struct *wq)
+{
+       return is_single_threaded(wq)
+               ? &cpu_singlethread_map : &cpu_populated_map;
+}
+
+static
+struct cpu_workqueue_struct *wq_per_cpu(struct workqueue_struct *wq, int cpu)
+{
+       if (unlikely(is_single_threaded(wq)))
+               cpu = singlethread_cpu;
+       return per_cpu_ptr(wq->cpu_wq, cpu);
 }
 
 /*
  * Set the workqueue on which a work item is to be run
  * - Must *only* be called if the pending flag is set
  */
-static inline void set_wq_data(struct work_struct *work, void *wq)
+static inline void set_wq_data(struct work_struct *work,
+                               struct cpu_workqueue_struct *cwq)
 {
        unsigned long new;
 
        BUG_ON(!work_pending(work));
 
-       new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING);
+       new = (unsigned long) cwq | (1UL << WORK_STRUCT_PENDING);
        new |= WORK_STRUCT_FLAG_MASK & *work_data_bits(work);
        atomic_long_set(&work->data, new);
 }
 
-static inline void *get_wq_data(struct work_struct *work)
+static inline
+struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
 {
        return (void *) (atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK);
 }
 
-static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work)
+static void insert_work(struct cpu_workqueue_struct *cwq,
+                               struct work_struct *work, int tail)
 {
-       int ret = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&cwq->lock, flags);
+       set_wq_data(work, cwq);
        /*
-        * We need to re-validate the work info after we've gotten
-        * the cpu_workqueue lock. We can run the work now iff:
-        *
-        *  - the wq_data still matches the cpu_workqueue_struct
-        *  - AND the work is still marked pending
-        *  - AND the work is still on a list (which will be this
-        *    workqueue_struct list)
-        *
-        * All these conditions are important, because we
-        * need to protect against the work being run right
-        * now on another CPU (all but the last one might be
-        * true if it's currently running and has not been
-        * released yet, for example).
+        * Ensure that we get the right work->data if we see the
+        * result of list_add() below, see try_to_grab_pending().
         */
-       if (get_wq_data(work) == cwq
-           && work_pending(work)
-           && !list_empty(&work->entry)) {
-               work_func_t f = work->func;
-               list_del_init(&work->entry);
-               spin_unlock_irqrestore(&cwq->lock, flags);
-
-               if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
-                       work_release(work);
-               f(work);
-
-               spin_lock_irqsave(&cwq->lock, flags);
-               cwq->remove_sequence++;
-               wake_up(&cwq->work_done);
-               ret = 1;
-       }
-       spin_unlock_irqrestore(&cwq->lock, flags);
-       return ret;
-}
-
-/**
- * run_scheduled_work - run scheduled work synchronously
- * @work: work to run
- *
- * This checks if the work was pending, and runs it
- * synchronously if so. It returns a boolean to indicate
- * whether it had any scheduled work to run or not.
- *
- * NOTE! This _only_ works for normal work_structs. You
- * CANNOT use this for delayed work, because the wq data
- * for delayed work will not point properly to the per-
- * CPU workqueue struct, but will change!
- */
-int fastcall run_scheduled_work(struct work_struct *work)
-{
-       for (;;) {
-               struct cpu_workqueue_struct *cwq;
-
-               if (!work_pending(work))
-                       return 0;
-               if (list_empty(&work->entry))
-                       return 0;
-               /* NOTE! This depends intimately on __queue_work! */
-               cwq = get_wq_data(work);
-               if (!cwq)
-                       return 0;
-               if (__run_work(cwq, work))
-                       return 1;
-       }
+       smp_wmb();
+       if (tail)
+               list_add_tail(&work->entry, &cwq->worklist);
+       else
+               list_add(&work->entry, &cwq->worklist);
+       wake_up(&cwq->more_work);
 }
-EXPORT_SYMBOL(run_scheduled_work);
 
 /* Preempt must be disabled. */
 static void __queue_work(struct cpu_workqueue_struct *cwq,
@@ -185,10 +139,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
        unsigned long flags;
 
        spin_lock_irqsave(&cwq->lock, flags);
-       set_wq_data(work, cwq);
-       list_add_tail(&work->entry, &cwq->worklist);
-       cwq->insert_sequence++;
-       wake_up(&cwq->more_work);
+       insert_work(cwq, work, 1);
        spin_unlock_irqrestore(&cwq->lock, flags);
 }
 
@@ -204,16 +155,14 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
  */
 int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work)
 {
-       int ret = 0, cpu = get_cpu();
+       int ret = 0;
 
        if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
-               if (unlikely(is_single_threaded(wq)))
-                       cpu = singlethread_cpu;
                BUG_ON(!list_empty(&work->entry));
-               __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
+               __queue_work(wq_per_cpu(wq, get_cpu()), work);
+               put_cpu();
                ret = 1;
        }
-       put_cpu();
        return ret;
 }
 EXPORT_SYMBOL_GPL(queue_work);
@@ -221,13 +170,10 @@ EXPORT_SYMBOL_GPL(queue_work);
 void delayed_work_timer_fn(unsigned long __data)
 {
        struct delayed_work *dwork = (struct delayed_work *)__data;
-       struct workqueue_struct *wq = get_wq_data(&dwork->work);
-       int cpu = smp_processor_id();
+       struct cpu_workqueue_struct *cwq = get_wq_data(&dwork->work);
+       struct workqueue_struct *wq = cwq->wq;
 
-       if (unlikely(is_single_threaded(wq)))
-               cpu = singlethread_cpu;
-
-       __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), &dwork->work);
+       __queue_work(wq_per_cpu(wq, smp_processor_id()), &dwork->work);
 }
 
 /**
@@ -241,27 +187,11 @@ void delayed_work_timer_fn(unsigned long __data)
 int fastcall queue_delayed_work(struct workqueue_struct *wq,
                        struct delayed_work *dwork, unsigned long delay)
 {
-       int ret = 0;
-       struct timer_list *timer = &dwork->timer;
-       struct work_struct *work = &dwork->work;
-
-       timer_stats_timer_set_start_info(timer);
+       timer_stats_timer_set_start_info(&dwork->timer);
        if (delay == 0)
-               return queue_work(wq, work);
-
-       if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
-               BUG_ON(timer_pending(timer));
-               BUG_ON(!list_empty(&work->entry));
+               return queue_work(wq, &dwork->work);
 
-               /* This stores wq for the moment, for the timer_fn */
-               set_wq_data(work, wq);
-               timer->expires = jiffies + delay;
-               timer->data = (unsigned long)dwork;
-               timer->function = delayed_work_timer_fn;
-               add_timer(timer);
-               ret = 1;
-       }
-       return ret;
+       return queue_delayed_work_on(-1, wq, dwork, delay);
 }
 EXPORT_SYMBOL_GPL(queue_delayed_work);
 
@@ -285,12 +215,16 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
                BUG_ON(timer_pending(timer));
                BUG_ON(!list_empty(&work->entry));
 
-               /* This stores wq for the moment, for the timer_fn */
-               set_wq_data(work, wq);
+               /* This stores cwq for the moment, for the timer_fn */
+               set_wq_data(work, wq_per_cpu(wq, raw_smp_processor_id()));
                timer->expires = jiffies + delay;
                timer->data = (unsigned long)dwork;
                timer->function = delayed_work_timer_fn;
-               add_timer_on(timer, cpu);
+
+               if (unlikely(cpu >= 0))
+                       add_timer_on(timer, cpu);
+               else
+                       add_timer(timer);
                ret = 1;
        }
        return ret;
@@ -299,13 +233,7 @@ EXPORT_SYMBOL_GPL(queue_delayed_work_on);
 
 static void run_workqueue(struct cpu_workqueue_struct *cwq)
 {
-       unsigned long flags;
-
-       /*
-        * Keep taking off work from the queue until
-        * done.
-        */
-       spin_lock_irqsave(&cwq->lock, flags);
+       spin_lock_irq(&cwq->lock);
        cwq->run_depth++;
        if (cwq->run_depth > 3) {
                /* morton gets to eat his hat */
@@ -318,12 +246,12 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
                                                struct work_struct, entry);
                work_func_t f = work->func;
 
+               cwq->current_work = work;
                list_del_init(cwq->worklist.next);
-               spin_unlock_irqrestore(&cwq->lock, flags);
+               spin_unlock_irq(&cwq->lock);
 
                BUG_ON(get_wq_data(work) != cwq);
-               if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
-                       work_release(work);
+               work_clear_pending(work);
                f(work);
 
                if (unlikely(in_atomic() || lockdep_depth(current) > 0)) {
@@ -337,63 +265,81 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
                        dump_stack();
                }
 
-               spin_lock_irqsave(&cwq->lock, flags);
-               cwq->remove_sequence++;
-               wake_up(&cwq->work_done);
+               spin_lock_irq(&cwq->lock);
+               cwq->current_work = NULL;
        }
        cwq->run_depth--;
-       spin_unlock_irqrestore(&cwq->lock, flags);
+       spin_unlock_irq(&cwq->lock);
+}
+
+/*
+ * NOTE: the caller must not touch *cwq if this func returns true
+ */
+static int cwq_should_stop(struct cpu_workqueue_struct *cwq)
+{
+       int should_stop = cwq->should_stop;
+
+       if (unlikely(should_stop)) {
+               spin_lock_irq(&cwq->lock);
+               should_stop = cwq->should_stop && list_empty(&cwq->worklist);
+               if (should_stop)
+                       cwq->thread = NULL;
+               spin_unlock_irq(&cwq->lock);
+       }
+
+       return should_stop;
 }
 
 static int worker_thread(void *__cwq)
 {
        struct cpu_workqueue_struct *cwq = __cwq;
-       DECLARE_WAITQUEUE(wait, current);
-       struct k_sigaction sa;
-       sigset_t blocked;
+       DEFINE_WAIT(wait);
 
-       if (!cwq->freezeable)
+       if (!cwq->wq->freezeable)
                current->flags |= PF_NOFREEZE;
 
        set_user_nice(current, -5);
 
-       /* Block and flush all signals */
-       sigfillset(&blocked);
-       sigprocmask(SIG_BLOCK, &blocked, NULL);
-       flush_signals(current);
-
-       /*
-        * We inherited MPOL_INTERLEAVE from the booting kernel.
-        * Set MPOL_DEFAULT to insure node local allocations.
-        */
-       numa_default_policy();
-
-       /* SIG_IGN makes children autoreap: see do_notify_parent(). */
-       sa.sa.sa_handler = SIG_IGN;
-       sa.sa.sa_flags = 0;
-       siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
-       do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
+       for (;;) {
+               prepare_to_wait(&cwq->more_work, &wait, TASK_INTERRUPTIBLE);
+               if (!freezing(current) && !cwq->should_stop
+                   && list_empty(&cwq->worklist))
+                       schedule();
+               finish_wait(&cwq->more_work, &wait);
 
-       set_current_state(TASK_INTERRUPTIBLE);
-       while (!kthread_should_stop()) {
-               if (cwq->freezeable)
-                       try_to_freeze();
+               try_to_freeze();
 
-               add_wait_queue(&cwq->more_work, &wait);
-               if (list_empty(&cwq->worklist))
-                       schedule();
-               else
-                       __set_current_state(TASK_RUNNING);
-               remove_wait_queue(&cwq->more_work, &wait);
+               if (cwq_should_stop(cwq))
+                       break;
 
-               if (!list_empty(&cwq->worklist))
-                       run_workqueue(cwq);
-               set_current_state(TASK_INTERRUPTIBLE);
+               run_workqueue(cwq);
        }
-       __set_current_state(TASK_RUNNING);
+
        return 0;
 }
 
+struct wq_barrier {
+       struct work_struct      work;
+       struct completion       done;
+};
+
+static void wq_barrier_func(struct work_struct *work)
+{
+       struct wq_barrier *barr = container_of(work, struct wq_barrier, work);
+       complete(&barr->done);
+}
+
+static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
+                                       struct wq_barrier *barr, int tail)
+{
+       INIT_WORK(&barr->work, wq_barrier_func);
+       __set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work));
+
+       init_completion(&barr->done);
+
+       insert_work(cwq, &barr->work, tail);
+}
+
 static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
 {
        if (cwq->thread == current) {
@@ -403,21 +349,18 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
                 */
                run_workqueue(cwq);
        } else {
-               DEFINE_WAIT(wait);
-               long sequence_needed;
+               struct wq_barrier barr;
+               int active = 0;
 
                spin_lock_irq(&cwq->lock);
-               sequence_needed = cwq->insert_sequence;
-
-               while (sequence_needed - cwq->remove_sequence > 0) {
-                       prepare_to_wait(&cwq->work_done, &wait,
-                                       TASK_UNINTERRUPTIBLE);
-                       spin_unlock_irq(&cwq->lock);
-                       schedule();
-                       spin_lock_irq(&cwq->lock);
+               if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
+                       insert_wq_barrier(cwq, &barr, 1);
+                       active = 1;
                }
-               finish_wait(&cwq->work_done, &wait);
                spin_unlock_irq(&cwq->lock);
+
+               if (active)
+                       wait_for_completion(&barr.done);
        }
 }
 
@@ -428,151 +371,145 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
  * Forces execution of the workqueue and blocks until its completion.
  * This is typically used in driver shutdown handlers.
  *
- * This function will sample each workqueue's current insert_sequence number and
- * will sleep until the head sequence is greater than or equal to that.  This
- * means that we sleep until all works which were queued on entry have been
- * handled, but we are not livelocked by new incoming ones.
+ * We sleep until all works which were queued on entry have been handled,
+ * but we are not livelocked by new incoming ones.
  *
  * This function used to run the workqueues itself.  Now we just wait for the
  * helper threads to do it.
  */
 void fastcall flush_workqueue(struct workqueue_struct *wq)
 {
+       const cpumask_t *cpu_map = wq_cpu_map(wq);
+       int cpu;
+
        might_sleep();
+       for_each_cpu_mask(cpu, *cpu_map)
+               flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
+}
+EXPORT_SYMBOL_GPL(flush_workqueue);
 
-       if (is_single_threaded(wq)) {
-               /* Always use first cpu's area. */
-               flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
-       } else {
-               int cpu;
+/*
+ * Upon a successful return, the caller "owns" WORK_STRUCT_PENDING bit,
+ * so this work can't be re-armed in any way.
+ */
+static int try_to_grab_pending(struct work_struct *work)
+{
+       struct cpu_workqueue_struct *cwq;
+       int ret = 0;
 
-               mutex_lock(&workqueue_mutex);
-               for_each_online_cpu(cpu)
-                       flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
-               mutex_unlock(&workqueue_mutex);
+       if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work)))
+               return 1;
+
+       /*
+        * The queueing is in progress, or it is already queued. Try to
+        * steal it from ->worklist without clearing WORK_STRUCT_PENDING.
+        */
+
+       cwq = get_wq_data(work);
+       if (!cwq)
+               return ret;
+
+       spin_lock_irq(&cwq->lock);
+       if (!list_empty(&work->entry)) {
+               /*
+                * This work is queued, but perhaps we locked the wrong cwq.
+                * In that case we must see the new value after rmb(), see
+                * insert_work()->wmb().
+                */
+               smp_rmb();
+               if (cwq == get_wq_data(work)) {
+                       list_del_init(&work->entry);
+                       ret = 1;
+               }
        }
+       spin_unlock_irq(&cwq->lock);
+
+       return ret;
 }
-EXPORT_SYMBOL_GPL(flush_workqueue);
 
-static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
-                                                  int cpu, int freezeable)
+static void wait_on_cpu_work(struct cpu_workqueue_struct *cwq,
+                               struct work_struct *work)
 {
-       struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-       struct task_struct *p;
+       struct wq_barrier barr;
+       int running = 0;
 
-       spin_lock_init(&cwq->lock);
-       cwq->wq = wq;
-       cwq->thread = NULL;
-       cwq->insert_sequence = 0;
-       cwq->remove_sequence = 0;
-       cwq->freezeable = freezeable;
-       INIT_LIST_HEAD(&cwq->worklist);
-       init_waitqueue_head(&cwq->more_work);
-       init_waitqueue_head(&cwq->work_done);
+       spin_lock_irq(&cwq->lock);
+       if (unlikely(cwq->current_work == work)) {
+               insert_wq_barrier(cwq, &barr, 0);
+               running = 1;
+       }
+       spin_unlock_irq(&cwq->lock);
 
-       if (is_single_threaded(wq))
-               p = kthread_create(worker_thread, cwq, "%s", wq->name);
-       else
-               p = kthread_create(worker_thread, cwq, "%s/%d", wq->name, cpu);
-       if (IS_ERR(p))
-               return NULL;
-       cwq->thread = p;
-       return p;
+       if (unlikely(running))
+               wait_for_completion(&barr.done);
 }
 
-struct workqueue_struct *__create_workqueue(const char *name,
-                                           int singlethread, int freezeable)
+static void wait_on_work(struct work_struct *work)
 {
-       int cpu, destroy = 0;
+       struct cpu_workqueue_struct *cwq;
        struct workqueue_struct *wq;
-       struct task_struct *p;
+       const cpumask_t *cpu_map;
+       int cpu;
 
-       wq = kzalloc(sizeof(*wq), GFP_KERNEL);
-       if (!wq)
-               return NULL;
+       might_sleep();
 
-       wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
-       if (!wq->cpu_wq) {
-               kfree(wq);
-               return NULL;
-       }
+       cwq = get_wq_data(work);
+       if (!cwq)
+               return;
 
-       wq->name = name;
-       mutex_lock(&workqueue_mutex);
-       if (singlethread) {
-               INIT_LIST_HEAD(&wq->list);
-               p = create_workqueue_thread(wq, singlethread_cpu, freezeable);
-               if (!p)
-                       destroy = 1;
-               else
-                       wake_up_process(p);
-       } else {
-               list_add(&wq->list, &workqueues);
-               for_each_online_cpu(cpu) {
-                       p = create_workqueue_thread(wq, cpu, freezeable);
-                       if (p) {
-                               kthread_bind(p, cpu);
-                               wake_up_process(p);
-                       } else
-                               destroy = 1;
-               }
-       }
-       mutex_unlock(&workqueue_mutex);
+       wq = cwq->wq;
+       cpu_map = wq_cpu_map(wq);
 
-       /*
-        * Was there any error during startup? If yes then clean up:
-        */
-       if (destroy) {
-               destroy_workqueue(wq);
-               wq = NULL;
-       }
-       return wq;
+       for_each_cpu_mask(cpu, *cpu_map)
+               wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
-EXPORT_SYMBOL_GPL(__create_workqueue);
 
-static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)
+/**
+ * cancel_work_sync - block until a work_struct's callback has terminated
+ * @work: the work which is to be flushed
+ *
+ * cancel_work_sync() will cancel the work if it is queued. If the work's
+ * callback appears to be running, cancel_work_sync() will block until it
+ * has completed.
+ *
+ * It is possible to use this function if the work re-queues itself. It can
+ * cancel the work even if it migrates to another workqueue, however in that
+ * case it only guarantees that work->func() has completed on the last queued
+ * workqueue.
+ *
+ * cancel_work_sync(&delayed_work->work) should be used only if ->timer is not
+ * pending, otherwise it goes into a busy-wait loop until the timer expires.
+ *
+ * The caller must ensure that workqueue_struct on which this work was last
+ * queued can't be destroyed before this function returns.
+ */
+void cancel_work_sync(struct work_struct *work)
 {
-       struct cpu_workqueue_struct *cwq;
-       unsigned long flags;
-       struct task_struct *p;
-
-       cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-       spin_lock_irqsave(&cwq->lock, flags);
-       p = cwq->thread;
-       cwq->thread = NULL;
-       spin_unlock_irqrestore(&cwq->lock, flags);
-       if (p)
-               kthread_stop(p);
+       while (!try_to_grab_pending(work))
+               cpu_relax();
+       wait_on_work(work);
+       work_clear_pending(work);
 }
+EXPORT_SYMBOL_GPL(cancel_work_sync);
 
 /**
- * destroy_workqueue - safely terminate a workqueue
- * @wq: target workqueue
+ * cancel_rearming_delayed_work - reliably kill off a delayed work.
+ * @dwork: the delayed work struct
  *
- * Safely destroy a workqueue. All work currently pending will be done first.
+ * It is possible to use this function if @dwork rearms itself via queue_work()
+ * or queue_delayed_work(). See also the comment for cancel_work_sync().
  */
-void destroy_workqueue(struct workqueue_struct *wq)
+void cancel_rearming_delayed_work(struct delayed_work *dwork)
 {
-       int cpu;
-
-       flush_workqueue(wq);
-
-       /* We don't need the distraction of CPUs appearing and vanishing. */
-       mutex_lock(&workqueue_mutex);
-       if (is_single_threaded(wq))
-               cleanup_workqueue_thread(wq, singlethread_cpu);
-       else {
-               for_each_online_cpu(cpu)
-                       cleanup_workqueue_thread(wq, cpu);
-               list_del(&wq->list);
-       }
-       mutex_unlock(&workqueue_mutex);
-       free_percpu(wq->cpu_wq);
-       kfree(wq);
+       while (!del_timer(&dwork->timer) &&
+              !try_to_grab_pending(&dwork->work))
+               cpu_relax();
+       wait_on_work(&dwork->work);
+       work_clear_pending(&dwork->work);
 }
-EXPORT_SYMBOL_GPL(destroy_workqueue);
+EXPORT_SYMBOL(cancel_rearming_delayed_work);
 
-static struct workqueue_struct *keventd_wq;
+static struct workqueue_struct *keventd_wq __read_mostly;
 
 /**
  * schedule_work - put work task in global workqueue
@@ -638,7 +575,7 @@ int schedule_on_each_cpu(work_func_t func)
        if (!works)
                return -ENOMEM;
 
-       mutex_lock(&workqueue_mutex);
+       preempt_disable();              /* CPU hotplug */
        for_each_online_cpu(cpu) {
                struct work_struct *work = per_cpu_ptr(works, cpu);
 
@@ -646,7 +583,7 @@ int schedule_on_each_cpu(work_func_t func)
                set_bit(WORK_STRUCT_PENDING, work_data_bits(work));
                __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), work);
        }
-       mutex_unlock(&workqueue_mutex);
+       preempt_enable();
        flush_workqueue(keventd_wq);
        free_percpu(works);
        return 0;
@@ -658,29 +595,6 @@ void flush_scheduled_work(void)
 }
 EXPORT_SYMBOL(flush_scheduled_work);
 
-/**
- * cancel_rearming_delayed_workqueue - reliably kill off a delayed work whose handler rearms the delayed work.
- * @wq:   the controlling workqueue structure
- * @dwork: the delayed work struct
- */
-void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
-                                      struct delayed_work *dwork)
-{
-       while (!cancel_delayed_work(dwork))
-               flush_workqueue(wq);
-}
-EXPORT_SYMBOL(cancel_rearming_delayed_workqueue);
-
-/**
- * cancel_rearming_delayed_work - reliably kill off a delayed keventd work whose handler rearms the delayed work.
- * @dwork: the delayed work struct
- */
-void cancel_rearming_delayed_work(struct delayed_work *dwork)
-{
-       cancel_rearming_delayed_workqueue(keventd_wq, dwork);
-}
-EXPORT_SYMBOL(cancel_rearming_delayed_work);
-
 /**
  * execute_in_process_context - reliably execute the routine with user context
  * @fn:                the function to execute
@@ -728,94 +642,209 @@ int current_is_keventd(void)
 
 }
 
-/* Take the work from this (downed) CPU. */
-static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
+static struct cpu_workqueue_struct *
+init_cpu_workqueue(struct workqueue_struct *wq, int cpu)
 {
        struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-       struct list_head list;
-       struct work_struct *work;
 
-       spin_lock_irq(&cwq->lock);
-       list_replace_init(&cwq->worklist, &list);
+       cwq->wq = wq;
+       spin_lock_init(&cwq->lock);
+       INIT_LIST_HEAD(&cwq->worklist);
+       init_waitqueue_head(&cwq->more_work);
+
+       return cwq;
+}
+
+static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
+{
+       struct workqueue_struct *wq = cwq->wq;
+       const char *fmt = is_single_threaded(wq) ? "%s" : "%s/%d";
+       struct task_struct *p;
+
+       p = kthread_create(worker_thread, cwq, fmt, wq->name, cpu);
+       /*
+        * Nobody can add the work_struct to this cwq,
+        *      if (caller is __create_workqueue)
+        *              nobody should see this wq
+        *      else // caller is CPU_UP_PREPARE
+        *              cpu is not on cpu_online_map
+        * so we can abort safely.
+        */
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       cwq->thread = p;
+       cwq->should_stop = 0;
+
+       return 0;
+}
+
+static void start_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
+{
+       struct task_struct *p = cwq->thread;
 
-       while (!list_empty(&list)) {
-               printk("Taking work for %s\n", wq->name);
-               work = list_entry(list.next,struct work_struct,entry);
-               list_del(&work->entry);
-               __queue_work(per_cpu_ptr(wq->cpu_wq, smp_processor_id()), work);
+       if (p != NULL) {
+               if (cpu >= 0)
+                       kthread_bind(p, cpu);
+               wake_up_process(p);
        }
-       spin_unlock_irq(&cwq->lock);
 }
 
-/* We're holding the cpucontrol mutex here */
-static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
-                                 unsigned long action,
-                                 void *hcpu)
+struct workqueue_struct *__create_workqueue(const char *name,
+                                           int singlethread, int freezeable)
 {
-       unsigned int hotcpu = (unsigned long)hcpu;
        struct workqueue_struct *wq;
+       struct cpu_workqueue_struct *cwq;
+       int err = 0, cpu;
 
-       switch (action) {
-       case CPU_UP_PREPARE:
-               mutex_lock(&workqueue_mutex);
-               /* Create a new workqueue thread for it. */
-               list_for_each_entry(wq, &workqueues, list) {
-                       if (!create_workqueue_thread(wq, hotcpu, 0)) {
-                               printk("workqueue for %i failed\n", hotcpu);
-                               return NOTIFY_BAD;
-                       }
-               }
-               break;
+       wq = kzalloc(sizeof(*wq), GFP_KERNEL);
+       if (!wq)
+               return NULL;
 
-       case CPU_ONLINE:
-               /* Kick off worker threads. */
-               list_for_each_entry(wq, &workqueues, list) {
-                       struct cpu_workqueue_struct *cwq;
+       wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
+       if (!wq->cpu_wq) {
+               kfree(wq);
+               return NULL;
+       }
 
-                       cwq = per_cpu_ptr(wq->cpu_wq, hotcpu);
-                       kthread_bind(cwq->thread, hotcpu);
-                       wake_up_process(cwq->thread);
-               }
-               mutex_unlock(&workqueue_mutex);
-               break;
+       wq->name = name;
+       wq->singlethread = singlethread;
+       wq->freezeable = freezeable;
+       INIT_LIST_HEAD(&wq->list);
 
-       case CPU_UP_CANCELED:
-               list_for_each_entry(wq, &workqueues, list) {
-                       if (!per_cpu_ptr(wq->cpu_wq, hotcpu)->thread)
+       if (singlethread) {
+               cwq = init_cpu_workqueue(wq, singlethread_cpu);
+               err = create_workqueue_thread(cwq, singlethread_cpu);
+               start_workqueue_thread(cwq, -1);
+       } else {
+               mutex_lock(&workqueue_mutex);
+               list_add(&wq->list, &workqueues);
+
+               for_each_possible_cpu(cpu) {
+                       cwq = init_cpu_workqueue(wq, cpu);
+                       if (err || !cpu_online(cpu))
                                continue;
-                       /* Unbind so it can run. */
-                       kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread,
-                                    any_online_cpu(cpu_online_map));
-                       cleanup_workqueue_thread(wq, hotcpu);
+                       err = create_workqueue_thread(cwq, cpu);
+                       start_workqueue_thread(cwq, cpu);
                }
                mutex_unlock(&workqueue_mutex);
-               break;
+       }
+
+       if (err) {
+               destroy_workqueue(wq);
+               wq = NULL;
+       }
+       return wq;
+}
+EXPORT_SYMBOL_GPL(__create_workqueue);
+
+static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
+{
+       struct wq_barrier barr;
+       int alive = 0;
+
+       spin_lock_irq(&cwq->lock);
+       if (cwq->thread != NULL) {
+               insert_wq_barrier(cwq, &barr, 1);
+               cwq->should_stop = 1;
+               alive = 1;
+       }
+       spin_unlock_irq(&cwq->lock);
+
+       if (alive) {
+               wait_for_completion(&barr.done);
 
-       case CPU_DOWN_PREPARE:
+               while (unlikely(cwq->thread != NULL))
+                       cpu_relax();
+               /*
+                * Wait until cwq->thread unlocks cwq->lock,
+                * it won't touch *cwq after that.
+                */
+               smp_rmb();
+               spin_unlock_wait(&cwq->lock);
+       }
+}
+
+/**
+ * destroy_workqueue - safely terminate a workqueue
+ * @wq: target workqueue
+ *
+ * Safely destroy a workqueue. All work currently pending will be done first.
+ */
+void destroy_workqueue(struct workqueue_struct *wq)
+{
+       const cpumask_t *cpu_map = wq_cpu_map(wq);
+       struct cpu_workqueue_struct *cwq;
+       int cpu;
+
+       mutex_lock(&workqueue_mutex);
+       list_del(&wq->list);
+       mutex_unlock(&workqueue_mutex);
+
+       for_each_cpu_mask(cpu, *cpu_map) {
+               cwq = per_cpu_ptr(wq->cpu_wq, cpu);
+               cleanup_workqueue_thread(cwq, cpu);
+       }
+
+       free_percpu(wq->cpu_wq);
+       kfree(wq);
+}
+EXPORT_SYMBOL_GPL(destroy_workqueue);
+
+static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+                                               unsigned long action,
+                                               void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct cpu_workqueue_struct *cwq;
+       struct workqueue_struct *wq;
+
+       action &= ~CPU_TASKS_FROZEN;
+
+       switch (action) {
+       case CPU_LOCK_ACQUIRE:
                mutex_lock(&workqueue_mutex);
-               break;
+               return NOTIFY_OK;
 
-       case CPU_DOWN_FAILED:
+       case CPU_LOCK_RELEASE:
                mutex_unlock(&workqueue_mutex);
-               break;
+               return NOTIFY_OK;
 
-       case CPU_DEAD:
-               list_for_each_entry(wq, &workqueues, list)
-                       cleanup_workqueue_thread(wq, hotcpu);
-               list_for_each_entry(wq, &workqueues, list)
-                       take_over_work(wq, hotcpu);
-               mutex_unlock(&workqueue_mutex);
-               break;
+       case CPU_UP_PREPARE:
+               cpu_set(cpu, cpu_populated_map);
+       }
+
+       list_for_each_entry(wq, &workqueues, list) {
+               cwq = per_cpu_ptr(wq->cpu_wq, cpu);
+
+               switch (action) {
+               case CPU_UP_PREPARE:
+                       if (!create_workqueue_thread(cwq, cpu))
+                               break;
+                       printk(KERN_ERR "workqueue for %i failed\n", cpu);
+                       return NOTIFY_BAD;
+
+               case CPU_ONLINE:
+                       start_workqueue_thread(cwq, cpu);
+                       break;
+
+               case CPU_UP_CANCELED:
+                       start_workqueue_thread(cwq, -1);
+               case CPU_DEAD:
+                       cleanup_workqueue_thread(cwq, cpu);
+                       break;
+               }
        }
 
        return NOTIFY_OK;
 }
 
-void init_workqueues(void)
+void __init init_workqueues(void)
 {
+       cpu_populated_map = cpu_online_map;
        singlethread_cpu = first_cpu(cpu_possible_map);
+       cpu_singlethread_map = cpumask_of_cpu(singlethread_cpu);
        hotcpu_notifier(workqueue_cpu_callback, 0);
        keventd_wq = create_workqueue("events");
        BUG_ON(!keventd_wq);
 }
-
index 9a287796da8ecc6bbcad2f47c8ce8cdb1aecc27f..ee05b8a061b5a5277b8b2d16ca2ace00f8c71fe7 100644 (file)
@@ -86,23 +86,6 @@ config DEBUG_SHIRQ
          Drivers ought to be able to handle interrupts coming in at those
          points; some don't and need to be caught.
 
-config LOG_BUF_SHIFT
-       int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
-       range 12 21
-       default 17 if S390 || LOCKDEP
-       default 16 if X86_NUMAQ || IA64
-       default 15 if SMP
-       default 14
-       help
-         Select kernel log buffer size as a power of 2.
-         Defaults and Examples:
-                    17 => 128 KB for S/390
-                    16 => 64 KB for x86 NUMAQ or IA-64
-                    15 => 32 KB for SMP
-                    14 => 16 KB for uniprocessor
-                    13 =>  8 KB
-                    12 =>  4 KB
-
 config DETECT_SOFTLOCKUP
        bool "Detect Soft Lockups"
        depends on DEBUG_KERNEL && !S390
@@ -201,6 +184,16 @@ config DEBUG_MUTEXES
         This feature allows mutex semantics violations to be detected and
         reported.
 
+config DEBUG_SEMAPHORE
+       bool "Semaphore debugging"
+       depends on DEBUG_KERNEL
+       depends on ALPHA || FRV
+       default n
+       help
+         If you say Y here then semaphore processing will issue lots of
+         verbose debugging messages.  If you suspect a semaphore problem or a
+         kernel hacker asks for this option then say Y.  Otherwise say N.
+
 config DEBUG_LOCK_ALLOC
        bool "Lock debugging: detect incorrect freeing of live locks"
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
index 0fabd12c39d79786e3bcf0ce1fa3bb68c48d01d9..b18fc2ff9ffea5df3d3377fc092bb8306d556fd2 100644 (file)
@@ -72,9 +72,8 @@ static bool fail_stacktrace(struct fault_attr *attr)
        trace.entries = entries;
        trace.max_entries = depth;
        trace.skip = 1;
-       trace.all_contexts = 0;
 
-       save_stack_trace(&trace, NULL);
+       save_stack_trace(&trace);
        for (n = 0; n < trace.nr_entries; n++) {
                if (attr->reject_start <= entries[n] &&
                               entries[n] < attr->reject_end)
index d69ddbe438655be6b65672d2c7366371baadfd85..402eb4eb6b23634492245c4393a0c2829de81de0 100644 (file)
@@ -1004,7 +1004,7 @@ static int radix_tree_callback(struct notifier_block *nfb,
        struct radix_tree_preload *rtp;
 
        /* Free per-cpu pool of perloaded nodes */
-       if (action == CPU_DEAD) {
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
                rtp = &per_cpu(radix_tree_preloads, cpu);
                while (rtp->nr) {
                        kmem_cache_free(radix_tree_node_cachep,
index a4b730a2180cc129a46df390c4707ee247cf012f..5b0d8522b7ca16882b54cee337536a665cb825d0 100644 (file)
@@ -56,6 +56,7 @@ static DEFINE_MUTEX(rslistlock);
  * rs_init - Initialize a Reed-Solomon codec
  * @symsize:   symbol size, bits (1-8)
  * @gfpoly:    Field generator polynomial coefficients
+ * @gffunc:    Field generator function
  * @fcr:       first root of RS code generator polynomial, index form
  * @prim:      primitive element to generate polynomial roots
  * @nroots:    RS code generator polynomial degree (number of roots)
@@ -63,8 +64,8 @@ static DEFINE_MUTEX(rslistlock);
  * Allocate a control structure and the polynom arrays for faster
  * en/decoding. Fill the arrays according to the given parameters.
  */
-static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
-                                  int prim, int nroots)
+static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int),
+                                  int fcr, int prim, int nroots)
 {
        struct rs_control *rs;
        int i, j, sr, root, iprim;
@@ -82,6 +83,7 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
        rs->prim = prim;
        rs->nroots = nroots;
        rs->gfpoly = gfpoly;
+       rs->gffunc = gffunc;
 
        /* Allocate the arrays */
        rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
@@ -99,17 +101,26 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
        /* Generate Galois field lookup tables */
        rs->index_of[0] = rs->nn;       /* log(zero) = -inf */
        rs->alpha_to[rs->nn] = 0;       /* alpha**-inf = 0 */
-       sr = 1;
-       for (i = 0; i < rs->nn; i++) {
-               rs->index_of[sr] = i;
-               rs->alpha_to[i] = sr;
-               sr <<= 1;
-               if (sr & (1 << symsize))
-                       sr ^= gfpoly;
-               sr &= rs->nn;
+       if (gfpoly) {
+               sr = 1;
+               for (i = 0; i < rs->nn; i++) {
+                       rs->index_of[sr] = i;
+                       rs->alpha_to[i] = sr;
+                       sr <<= 1;
+                       if (sr & (1 << symsize))
+                               sr ^= gfpoly;
+                       sr &= rs->nn;
+               }
+       } else {
+               sr = gffunc(0);
+               for (i = 0; i < rs->nn; i++) {
+                       rs->index_of[sr] = i;
+                       rs->alpha_to[i] = sr;
+                       sr = gffunc(sr);
+               }
        }
        /* If it's not primitive, exit */
-       if(sr != 1)
+       if(sr != rs->alpha_to[0])
                goto errpol;
 
        /* Find prim-th root of 1, used in decoding */
@@ -173,18 +184,22 @@ void free_rs(struct rs_control *rs)
 }
 
 /**
- * init_rs - Find a matching or allocate a new rs control structure
+ * init_rs_internal - Find a matching or allocate a new rs control structure
  *  @symsize:  the symbol size (number of bits)
  *  @gfpoly:   the extended Galois field generator polynomial coefficients,
  *             with the 0th coefficient in the low order bit. The polynomial
  *             must be primitive;
+ *  @gffunc:   pointer to function to generate the next field element,
+ *             or the multiplicative identity element if given 0.  Used
+ *             instead of gfpoly if gfpoly is 0
  *  @fcr:      the first consecutive root of the rs code generator polynomial
  *             in index form
  *  @prim:     primitive element to generate polynomial roots
  *  @nroots:   RS code generator polynomial degree (number of roots)
  */
-struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
-                          int nroots)
+static struct rs_control *init_rs_internal(int symsize, int gfpoly,
+                                           int (*gffunc)(int), int fcr,
+                                           int prim, int nroots)
 {
        struct list_head        *tmp;
        struct rs_control       *rs;
@@ -208,6 +223,8 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
                        continue;
                if (gfpoly != rs->gfpoly)
                        continue;
+               if (gffunc != rs->gffunc)
+                       continue;
                if (fcr != rs->fcr)
                        continue;
                if (prim != rs->prim)
@@ -220,7 +237,7 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
        }
 
        /* Create a new one */
-       rs = rs_init(symsize, gfpoly, fcr, prim, nroots);
+       rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots);
        if (rs) {
                rs->users = 1;
                list_add(&rs->list, &rslist);
@@ -230,6 +247,42 @@ out:
        return rs;
 }
 
+/**
+ * init_rs - Find a matching or allocate a new rs control structure
+ *  @symsize:  the symbol size (number of bits)
+ *  @gfpoly:   the extended Galois field generator polynomial coefficients,
+ *             with the 0th coefficient in the low order bit. The polynomial
+ *             must be primitive;
+ *  @fcr:      the first consecutive root of the rs code generator polynomial
+ *             in index form
+ *  @prim:     primitive element to generate polynomial roots
+ *  @nroots:   RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
+                           int nroots)
+{
+       return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots);
+}
+
+/**
+ * init_rs_non_canonical - Find a matching or allocate a new rs control
+ *                         structure, for fields with non-canonical
+ *                         representation
+ *  @symsize:  the symbol size (number of bits)
+ *  @gffunc:   pointer to function to generate the next field element,
+ *             or the multiplicative identity element if given 0.  Used
+ *             instead of gfpoly if gfpoly is 0
+ *  @fcr:      the first consecutive root of the rs code generator polynomial
+ *             in index form
+ *  @prim:     primitive element to generate polynomial roots
+ *  @nroots:   RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int),
+                                         int fcr, int prim, int nroots)
+{
+       return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots);
+}
+
 #ifdef CONFIG_REED_SOLOMON_ENC8
 /**
  *  encode_rs8 - Calculate the parity for data values (8bit data width)
@@ -321,6 +374,7 @@ EXPORT_SYMBOL_GPL(decode_rs16);
 #endif
 
 EXPORT_SYMBOL_GPL(init_rs);
+EXPORT_SYMBOL_GPL(init_rs_non_canonical);
 EXPORT_SYMBOL_GPL(free_rs);
 
 MODULE_LICENSE("GPL");
index 9970e55c90bd7b28d90c5912bf3f63da3a4c7dc2..10c13ad0d82d89dadebcee23951830d18599f0e0 100644 (file)
@@ -778,7 +778,6 @@ swiotlb_dma_supported(struct device *hwdev, u64 mask)
        return virt_to_bus(io_tlb_end - 1) <= mask;
 }
 
-EXPORT_SYMBOL(swiotlb_init);
 EXPORT_SYMBOL(swiotlb_map_single);
 EXPORT_SYMBOL(swiotlb_unmap_single);
 EXPORT_SYMBOL(swiotlb_map_sg);
index cbab1df150cfed43bcbd4beeb8d40fe15e7042b5..0172902412613025213c07e7758af9492e2bd761 100644 (file)
@@ -825,6 +825,17 @@ int vsscanf(const char * buf, const char * fmt, va_list args)
                        break;
                str = next;
        }
+
+       /*
+        * Now we've come all the way through so either the input string or the
+        * format ended. In the former case, there can be a %n at the current
+        * position in the format that needs to be filled.
+        */
+       if (*fmt == '%' && *(fmt + 1) == 'n') {
+               int *p = (int *)va_arg(args, int *);
+               *p = str - buf;
+       }
+
        return num;
 }
 
index 1ac718f636ec6f5842217bd6b06c7ef0bff0dd21..a17da8bafe62758b6f0d86816d9d6c64b464e687 100644 (file)
@@ -166,5 +166,5 @@ config ZONE_DMA_FLAG
 config NR_QUICK
        int
        depends on QUICKLIST
+       default "2" if SUPERH
        default "1"
-
index 5631d6b2a62d8c18c43472dd5bf4eae3f5e88d10..7b48b2ad00e773853780c1dbc314b850307199cb 100644 (file)
@@ -750,6 +750,7 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
        read_unlock_irq(&mapping->tree_lock);
        return i;
 }
+EXPORT_SYMBOL(find_get_pages_contig);
 
 /**
  * find_get_pages_tag - find and return pages that match @tag
@@ -778,6 +779,7 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
        read_unlock_irq(&mapping->tree_lock);
        return ret;
 }
+EXPORT_SYMBOL(find_get_pages_tag);
 
 /**
  * grab_cache_page_nowait - returns locked page at given index in given cache
@@ -1110,6 +1112,45 @@ success:
        return size;
 }
 
+/*
+ * Performs necessary checks before doing a write
+ * @iov:       io vector request
+ * @nr_segs:   number of segments in the iovec
+ * @count:     number of bytes to write
+ * @access_flags: type of access: %VERIFY_READ or %VERIFY_WRITE
+ *
+ * Adjust number of segments and amount of bytes to write (nr_segs should be
+ * properly initialized first). Returns appropriate error code that caller
+ * should return or zero in case that write should be allowed.
+ */
+int generic_segment_checks(const struct iovec *iov,
+                       unsigned long *nr_segs, size_t *count, int access_flags)
+{
+       unsigned long   seg;
+       size_t cnt = 0;
+       for (seg = 0; seg < *nr_segs; seg++) {
+               const struct iovec *iv = &iov[seg];
+
+               /*
+                * If any segment has a negative length, or the cumulative
+                * length ever wraps negative then return -EINVAL.
+                */
+               cnt += iv->iov_len;
+               if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
+                       return -EINVAL;
+               if (access_ok(access_flags, iv->iov_base, iv->iov_len))
+                       continue;
+               if (seg == 0)
+                       return -EFAULT;
+               *nr_segs = seg;
+               cnt -= iv->iov_len;     /* This segment is no good */
+               break;
+       }
+       *count = cnt;
+       return 0;
+}
+EXPORT_SYMBOL(generic_segment_checks);
+
 /**
  * generic_file_aio_read - generic filesystem read routine
  * @iocb:      kernel I/O control block
@@ -1131,24 +1172,9 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        loff_t *ppos = &iocb->ki_pos;
 
        count = 0;
-       for (seg = 0; seg < nr_segs; seg++) {
-               const struct iovec *iv = &iov[seg];
-
-               /*
-                * If any segment has a negative length, or the cumulative
-                * length ever wraps negative then return -EINVAL.
-                */
-               count += iv->iov_len;
-               if (unlikely((ssize_t)(count|iv->iov_len) < 0))
-                       return -EINVAL;
-               if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len))
-                       continue;
-               if (seg == 0)
-                       return -EFAULT;
-               nr_segs = seg;
-               count -= iv->iov_len;   /* This segment is no good */
-               break;
-       }
+       retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
+       if (retval)
+               return retval;
 
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
        if (filp->f_flags & O_DIRECT) {
@@ -1758,7 +1784,7 @@ struct page *read_cache_page_async(struct address_space *mapping,
 retry:
        page = __read_cache_page(mapping, index, filler, data);
        if (IS_ERR(page))
-               goto out;
+               return page;
        mark_page_accessed(page);
        if (PageUptodate(page))
                goto out;
@@ -1776,9 +1802,9 @@ retry:
        err = filler(data, page);
        if (err < 0) {
                page_cache_release(page);
-               page = ERR_PTR(err);
+               return ERR_PTR(err);
        }
- out:
+out:
        mark_page_accessed(page);
        return page;
 }
@@ -2218,30 +2244,14 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        size_t ocount;          /* original count */
        size_t count;           /* after file limit checks */
        struct inode    *inode = mapping->host;
-       unsigned long   seg;
        loff_t          pos;
        ssize_t         written;
        ssize_t         err;
 
        ocount = 0;
-       for (seg = 0; seg < nr_segs; seg++) {
-               const struct iovec *iv = &iov[seg];
-
-               /*
-                * If any segment has a negative length, or the cumulative
-                * length ever wraps negative then return -EINVAL.
-                */
-               ocount += iv->iov_len;
-               if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
-                       return -EINVAL;
-               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-                       continue;
-               if (seg == 0)
-                       return -EFAULT;
-               nr_segs = seg;
-               ocount -= iv->iov_len;  /* This segment is no good */
-               break;
-       }
+       err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
+       if (err)
+               return err;
 
        count = ocount;
        pos = *ppos;
@@ -2301,10 +2311,10 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
                 * semantics.
                 */
                endbyte = pos + written_buffered - written - 1;
-               err = do_sync_file_range(file, pos, endbyte,
-                                        SYNC_FILE_RANGE_WAIT_BEFORE|
-                                        SYNC_FILE_RANGE_WRITE|
-                                        SYNC_FILE_RANGE_WAIT_AFTER);
+               err = do_sync_mapping_range(file->f_mapping, pos, endbyte,
+                                           SYNC_FILE_RANGE_WAIT_BEFORE|
+                                           SYNC_FILE_RANGE_WRITE|
+                                           SYNC_FILE_RANGE_WAIT_AFTER);
                if (err == 0) {
                        written = written_buffered;
                        invalidate_mapping_pages(mapping,
index cbb335813ec01509ccf0b5525ccb1a3e0f51e1cc..1b49dab9b25d5d04aa3b98fdfc9b69de5f1d4acb 100644 (file)
@@ -434,7 +434,6 @@ xip_truncate_page(struct address_space *mapping, loff_t from)
        unsigned blocksize;
        unsigned length;
        struct page *page;
-       void *kaddr;
 
        BUG_ON(!mapping->a_ops->get_xip_page);
 
@@ -458,11 +457,7 @@ xip_truncate_page(struct address_space *mapping, loff_t from)
                else
                        return PTR_ERR(page);
        }
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr + offset, 0, length);
-       kunmap_atomic(kaddr, KM_USER0);
-
-       flush_dcache_page(page);
+       zero_user_page(page, offset, length, KM_USER0);
        return 0;
 }
 EXPORT_SYMBOL_GPL(xip_truncate_page);
index 36db012b38dde252c827d0af4719c2e7b79e5083..eb7180db303326f73f7e099f84e2557e84cc87b1 100644 (file)
@@ -140,6 +140,8 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
        return page;
 
 fail:
+       if (vma->vm_flags & VM_MAYSHARE)
+               resv_huge_pages++;
        spin_unlock(&hugetlb_lock);
        return NULL;
 }
@@ -172,6 +174,17 @@ static int __init hugetlb_setup(char *s)
 }
 __setup("hugepages=", hugetlb_setup);
 
+static unsigned int cpuset_mems_nr(unsigned int *array)
+{
+       int node;
+       unsigned int nr = 0;
+
+       for_each_node_mask(node, cpuset_current_mems_allowed)
+               nr += array[node];
+
+       return nr;
+}
+
 #ifdef CONFIG_SYSCTL
 static void update_and_free_page(struct page *page)
 {
@@ -817,6 +830,26 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to)
        chg = region_chg(&inode->i_mapping->private_list, from, to);
        if (chg < 0)
                return chg;
+       /*
+        * When cpuset is configured, it breaks the strict hugetlb page
+        * reservation as the accounting is done on a global variable. Such
+        * reservation is completely rubbish in the presence of cpuset because
+        * the reservation is not checked against page availability for the
+        * current cpuset. Application can still potentially OOM'ed by kernel
+        * with lack of free htlb page in cpuset that the task is in.
+        * Attempt to enforce strict accounting with cpuset is almost
+        * impossible (or too ugly) because cpuset is too fluid that
+        * task or memory node can be dynamically moved between cpusets.
+        *
+        * The change of semantics for shared hugetlb mapping with cpuset is
+        * undesirable. However, in order to preserve some of the semantics,
+        * we fall back to check against current free page availability as
+        * a best attempt and hopefully to minimize the impact of changing
+        * semantics that cpuset has.
+        */
+       if (chg > cpuset_mems_nr(free_huge_pages_node))
+               return -ENOMEM;
+
        ret = hugetlb_acct_memory(chg);
        if (ret < 0)
                return ret;
index 52646d61ff696235e88b11175641bf7de884afd3..68b9ad2ef1d6917c28721419627fa9fd4a29e3b3 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1366,7 +1366,6 @@ unsigned long
 get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
 {
-       unsigned long ret;
        unsigned long (*get_area)(struct file *, unsigned long,
                                  unsigned long, unsigned long, unsigned long);
 
@@ -1721,7 +1720,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 
 /*
  * Split a vma into two pieces at address 'addr', a new vma is allocated
- * either for the first part or the the tail.
+ * either for the first part or the tail.
  */
 int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
              unsigned long addr, int new_below)
index 1f60194d9b9b436e0d8020c4bc73b5226429b2be..2b16b00a5b115be2c13897aab5763562312ecb84 100644 (file)
@@ -261,6 +261,14 @@ void vunmap(void *addr)
        BUG();
 }
 
+/*
+ * Implement a stub for vmalloc_sync_all() if the architecture chose not to
+ * have one.
+ */
+void  __attribute__((weak)) vmalloc_sync_all(void)
+{
+}
+
 /*
  *  sys_brk() for the most part doesn't need the global kernel
  *  lock, except when an application is doing something nasty
index 029dfad5a235753fab2b7f81dda1950e770e9f2d..63cd88840eb2d0bf758de29265ba9426a6d20ab4 100644 (file)
@@ -683,12 +683,7 @@ retry:
                        }
 
                        ret = (*writepage)(page, wbc);
-                       if (ret) {
-                               if (ret == -ENOSPC)
-                                       set_bit(AS_ENOSPC, &mapping->flags);
-                               else
-                                       set_bit(AS_EIO, &mapping->flags);
-                       }
+                       mapping_set_error(mapping, ret);
 
                        if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
                                unlock_page(page);
index 59164313167f39d3408b07557899bcf69f963fb9..f9b5d6d5f4d6cf7643d1c6f39b1d112e8bd18c33 100644 (file)
@@ -103,7 +103,7 @@ int min_free_kbytes = 1024;
 
 unsigned long __meminitdata nr_kernel_pages;
 unsigned long __meminitdata nr_all_pages;
-static unsigned long __initdata dma_reserve;
+static unsigned long __meminitdata dma_reserve;
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
   /*
@@ -126,10 +126,10 @@ static unsigned long __initdata dma_reserve;
     #endif
   #endif
 
-  struct node_active_region __initdata early_node_map[MAX_ACTIVE_REGIONS];
-  int __initdata nr_nodemap_entries;
-  unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
-  unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
+  struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
+  int __meminitdata nr_nodemap_entries;
+  unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
+  unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
 #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
   unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
   unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
@@ -691,43 +691,26 @@ static void __init setup_nr_node_ids(void) {}
 
 #ifdef CONFIG_NUMA
 /*
- * Called from the slab reaper to drain pagesets on a particular node that
- * belongs to the currently executing processor.
+ * Called from the vmstat counter updater to drain pagesets of this
+ * currently executing processor on remote nodes after they have
+ * expired.
+ *
  * Note that this function must be called with the thread pinned to
  * a single processor.
  */
-void drain_node_pages(int nodeid)
+void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
 {
-       int i;
-       enum zone_type z;
        unsigned long flags;
+       int to_drain;
 
-       for (z = 0; z < MAX_NR_ZONES; z++) {
-               struct zone *zone = NODE_DATA(nodeid)->node_zones + z;
-               struct per_cpu_pageset *pset;
-
-               if (!populated_zone(zone))
-                       continue;
-
-               pset = zone_pcp(zone, smp_processor_id());
-               for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
-                       struct per_cpu_pages *pcp;
-
-                       pcp = &pset->pcp[i];
-                       if (pcp->count) {
-                               int to_drain;
-
-                               local_irq_save(flags);
-                               if (pcp->count >= pcp->batch)
-                                       to_drain = pcp->batch;
-                               else
-                                       to_drain = pcp->count;
-                               free_pages_bulk(zone, to_drain, &pcp->list, 0);
-                               pcp->count -= to_drain;
-                               local_irq_restore(flags);
-                       }
-               }
-       }
+       local_irq_save(flags);
+       if (pcp->count >= pcp->batch)
+               to_drain = pcp->batch;
+       else
+               to_drain = pcp->count;
+       free_pages_bulk(zone, to_drain, &pcp->list, 0);
+       pcp->count -= to_drain;
+       local_irq_restore(flags);
 }
 #endif
 
@@ -2148,11 +2131,14 @@ static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                if (process_zones(cpu))
                        ret = NOTIFY_BAD;
                break;
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                free_zone_pagesets(cpu);
                break;
        default:
@@ -2179,7 +2165,7 @@ void __init setup_per_cpu_pageset(void)
 
 #endif
 
-static __meminit
+static __meminit noinline
 int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 {
        int i;
@@ -2267,7 +2253,7 @@ __meminit int init_currently_empty_zone(struct zone *zone,
  * Basic iterator support. Return the first range of PFNs for a node
  * Note: nid == MAX_NUMNODES returns first region regardless of node
  */
-static int __init first_active_region_index_in_nid(int nid)
+static int __meminit first_active_region_index_in_nid(int nid)
 {
        int i;
 
@@ -2282,7 +2268,7 @@ static int __init first_active_region_index_in_nid(int nid)
  * Basic iterator support. Return the next active range of PFNs for a node
  * Note: nid == MAX_NUMNODES returns next region regardles of node
  */
-static int __init next_active_region_index_in_nid(int index, int nid)
+static int __meminit next_active_region_index_in_nid(int index, int nid)
 {
        for (index = index + 1; index < nr_nodemap_entries; index++)
                if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
@@ -2435,7 +2421,7 @@ static void __init account_node_boundary(unsigned int nid,
  * with no available memory, a warning is printed and the start and end
  * PFNs will be 0.
  */
-void __init get_pfn_range_for_nid(unsigned int nid,
+void __meminit get_pfn_range_for_nid(unsigned int nid,
                        unsigned long *start_pfn, unsigned long *end_pfn)
 {
        int i;
@@ -2460,7 +2446,7 @@ void __init get_pfn_range_for_nid(unsigned int nid,
  * Return the number of pages a zone spans in a node, including holes
  * present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
  */
-unsigned long __init zone_spanned_pages_in_node(int nid,
+unsigned long __meminit zone_spanned_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long *ignored)
 {
@@ -2488,7 +2474,7 @@ unsigned long __init zone_spanned_pages_in_node(int nid,
  * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
  * then all holes in the requested range will be accounted for.
  */
-unsigned long __init __absent_pages_in_range(int nid,
+unsigned long __meminit __absent_pages_in_range(int nid,
                                unsigned long range_start_pfn,
                                unsigned long range_end_pfn)
 {
@@ -2548,7 +2534,7 @@ unsigned long __init absent_pages_in_range(unsigned long start_pfn,
 }
 
 /* Return the number of page frames in holes in a zone on a node */
-unsigned long __init zone_absent_pages_in_node(int nid,
+unsigned long __meminit zone_absent_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long *ignored)
 {
@@ -2584,7 +2570,7 @@ static inline unsigned long zone_absent_pages_in_node(int nid,
 
 #endif
 
-static void __init calculate_node_totalpages(struct pglist_data *pgdat,
+static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
                unsigned long *zones_size, unsigned long *zholes_size)
 {
        unsigned long realtotalpages, totalpages = 0;
@@ -2692,7 +2678,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
        }
 }
 
-static void __init alloc_node_mem_map(struct pglist_data *pgdat)
+static void __meminit alloc_node_mem_map(struct pglist_data *pgdat)
 {
        /* Skip empty nodes */
        if (!pgdat->node_spanned_pages)
@@ -3012,7 +2998,7 @@ static int page_alloc_cpu_notify(struct notifier_block *self,
 {
        int cpu = (unsigned long)hcpu;
 
-       if (action == CPU_DEAD) {
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
                local_irq_disable();
                __drain_pages(cpu);
                vm_events_fold_cpu(cpu);
index 75a32be64a2137e5e95279c9486a5aed4c3d761b..304f51985c78504cb67056922bfd2bb7c34a6e21 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -505,6 +505,7 @@ int page_mkclean(struct page *page)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(page_mkclean);
 
 /**
  * page_set_anon_rmap - setup new anonymous rmap
index 5920a412b377556ea5adf4e05bf59a41dcc175cd..944b20581f8c421369828fb2090381ad53aa3969 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
  * Usually, the kmalloc caches are cache_line_size() aligned, except when
  * DEBUG and FORCED_DEBUG are enabled, then they are BYTES_PER_WORD aligned.
  * Some archs want to perform DMA into kmalloc caches and need a guaranteed
- * alignment larger than BYTES_PER_WORD. ARCH_KMALLOC_MINALIGN allows that.
- * Note that this flag disables some debug features.
+ * alignment larger than the alignment of a 64-bit integer.
+ * ARCH_KMALLOC_MINALIGN allows that.
+ * Note that increasing this value may disable some debug features.
  */
-#define ARCH_KMALLOC_MINALIGN 0
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
 #endif
 
 #ifndef ARCH_SLAB_MINALIGN
@@ -536,19 +537,22 @@ static int obj_size(struct kmem_cache *cachep)
        return cachep->obj_size;
 }
 
-static unsigned long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
+static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
 {
        BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
-       return (unsigned long*) (objp+obj_offset(cachep)-BYTES_PER_WORD);
+       return (unsigned long long*) (objp + obj_offset(cachep) -
+                                     sizeof(unsigned long long));
 }
 
-static unsigned long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
+static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
 {
        BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
        if (cachep->flags & SLAB_STORE_USER)
-               return (unsigned long *)(objp + cachep->buffer_size -
-                                        2 * BYTES_PER_WORD);
-       return (unsigned long *)(objp + cachep->buffer_size - BYTES_PER_WORD);
+               return (unsigned long long *)(objp + cachep->buffer_size -
+                                             sizeof(unsigned long long) -
+                                             BYTES_PER_WORD);
+       return (unsigned long long *) (objp + cachep->buffer_size -
+                                      sizeof(unsigned long long));
 }
 
 static void **dbg_userword(struct kmem_cache *cachep, void *objp)
@@ -561,8 +565,8 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 
 #define obj_offset(x)                  0
 #define obj_size(cachep)               (cachep->buffer_size)
-#define dbg_redzone1(cachep, objp)     ({BUG(); (unsigned long *)NULL;})
-#define dbg_redzone2(cachep, objp)     ({BUG(); (unsigned long *)NULL;})
+#define dbg_redzone1(cachep, objp)     ({BUG(); (unsigned long long *)NULL;})
+#define dbg_redzone2(cachep, objp)     ({BUG(); (unsigned long long *)NULL;})
 #define dbg_userword(cachep, objp)     ({BUG(); (void **)NULL;})
 
 #endif
@@ -924,12 +928,6 @@ static void next_reap_node(void)
 {
        int node = __get_cpu_var(reap_node);
 
-       /*
-        * Also drain per cpu pages on remote zones
-        */
-       if (node != numa_node_id())
-               drain_node_pages(node);
-
        node = next_node(node, node_online_map);
        if (unlikely(node >= MAX_NUMNODES))
                node = first_node(node_online_map);
@@ -1182,8 +1180,11 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
        int memsize = sizeof(struct kmem_list3);
 
        switch (action) {
-       case CPU_UP_PREPARE:
+       case CPU_LOCK_ACQUIRE:
                mutex_lock(&cache_chain_mutex);
+               break;
+       case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                /*
                 * We need to do this right in the beginning since
                 * alloc_arraycache's are going to use this list.
@@ -1270,17 +1271,28 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                }
                break;
        case CPU_ONLINE:
-               mutex_unlock(&cache_chain_mutex);
+       case CPU_ONLINE_FROZEN:
                start_cpu_timer(cpu);
                break;
 #ifdef CONFIG_HOTPLUG_CPU
-       case CPU_DOWN_PREPARE:
-               mutex_lock(&cache_chain_mutex);
-               break;
-       case CPU_DOWN_FAILED:
-               mutex_unlock(&cache_chain_mutex);
-               break;
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
+               /*
+                * Shutdown cache reaper. Note that the cache_chain_mutex is
+                * held so that if cache_reap() is invoked it cannot do
+                * anything expensive but will only modify reap_work
+                * and reschedule the timer.
+               */
+               cancel_rearming_delayed_work(&per_cpu(reap_work, cpu));
+               /* Now the cache_reaper is guaranteed to be not running. */
+               per_cpu(reap_work, cpu).work.func = NULL;
+               break;
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               start_cpu_timer(cpu);
+               break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                /*
                 * Even if all the cpus of a node are down, we don't free the
                 * kmem_list3 of any cache. This to avoid a race between
@@ -1292,6 +1304,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                /* fall thru */
 #endif
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
                list_for_each_entry(cachep, &cache_chain, next) {
                        struct array_cache *nc;
                        struct array_cache *shared;
@@ -1350,6 +1363,8 @@ free_array_cache:
                                continue;
                        drain_freelist(cachep, l3, l3->free_objects);
                }
+               break;
+       case CPU_LOCK_RELEASE:
                mutex_unlock(&cache_chain_mutex);
                break;
        }
@@ -1776,7 +1791,7 @@ static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines)
        char *realobj;
 
        if (cachep->flags & SLAB_RED_ZONE) {
-               printk(KERN_ERR "Redzone: 0x%lx/0x%lx.\n",
+               printk(KERN_ERR "Redzone: 0x%llx/0x%llx.\n",
                        *dbg_redzone1(cachep, objp),
                        *dbg_redzone2(cachep, objp));
        }
@@ -2239,7 +2254,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
         * is greater than BYTES_PER_WORD.
         */
        if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
-               ralign = BYTES_PER_WORD;
+               ralign = __alignof__(unsigned long long);
 
        /* 2) arch mandated alignment */
        if (ralign < ARCH_SLAB_MINALIGN) {
@@ -2250,7 +2265,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                ralign = align;
        }
        /* disable debug if necessary */
-       if (ralign > BYTES_PER_WORD)
+       if (ralign > __alignof__(unsigned long long))
                flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        /*
         * 4) Store it.
@@ -2271,8 +2286,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
         */
        if (flags & SLAB_RED_ZONE) {
                /* add space for red zone words */
-               cachep->obj_offset += BYTES_PER_WORD;
-               size += 2 * BYTES_PER_WORD;
+               cachep->obj_offset += sizeof(unsigned long long);
+               size += 2 * sizeof(unsigned long long);
        }
        if (flags & SLAB_STORE_USER) {
                /* user store requires one word storage behind the end of
@@ -2833,7 +2848,7 @@ static void kfree_debugcheck(const void *objp)
 
 static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
 {
-       unsigned long redzone1, redzone2;
+       unsigned long long redzone1, redzone2;
 
        redzone1 = *dbg_redzone1(cache, obj);
        redzone2 = *dbg_redzone2(cache, obj);
@@ -2849,7 +2864,7 @@ static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
        else
                slab_error(cache, "memory outside object was overwritten");
 
-       printk(KERN_ERR "%p: redzone 1:0x%lx, redzone 2:0x%lx.\n",
+       printk(KERN_ERR "%p: redzone 1:0x%llx, redzone 2:0x%llx.\n",
                        obj, redzone1, redzone2);
 }
 
@@ -3065,7 +3080,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                        slab_error(cachep, "double free, or memory outside"
                                                " object was overwritten");
                        printk(KERN_ERR
-                               "%p: redzone 1:0x%lx, redzone 2:0x%lx\n",
+                               "%p: redzone 1:0x%llx, redzone 2:0x%llx\n",
                                objp, *dbg_redzone1(cachep, objp),
                                *dbg_redzone2(cachep, objp));
                }
@@ -3738,7 +3753,6 @@ EXPORT_SYMBOL(__kmalloc);
 
 /**
  * krealloc - reallocate memory. The contents will remain unchanged.
- *
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
@@ -4136,7 +4150,6 @@ next:
        check_irq_on();
        mutex_unlock(&cache_chain_mutex);
        next_reap_node();
-       refresh_cpu_vm_stats(smp_processor_id());
 out:
        /* Set up the next iteration */
        schedule_delayed_work(work, round_jiffies_relative(REAPTIMEOUT_CPUC));
@@ -4428,16 +4441,12 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s)
 static void show_symbol(struct seq_file *m, unsigned long address)
 {
 #ifdef CONFIG_KALLSYMS
-       char *modname;
-       const char *name;
        unsigned long offset, size;
-       char namebuf[KSYM_NAME_LEN+1];
-
-       name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
+       char modname[MODULE_NAME_LEN + 1], name[KSYM_NAME_LEN + 1];
 
-       if (name) {
+       if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
                seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
-               if (modname)
+               if (modname[0])
                        seq_printf(m, " [%s]", modname);
                return;
        }
index 5db3da5a60bf15507227eead81474a2575dfc653..bd2efae02bcd9cedf262b8dd6e2c79f3fd4b1bec 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
  * SLUB assigns one slab for allocation to each processor.
  * Allocations only occur from these slabs called cpu slabs.
  *
- * Slabs with free elements are kept on a partial list.
- * There is no list for full slabs. If an object in a full slab is
+ * Slabs with free elements are kept on a partial list and during regular
+ * operations no list for full slabs is used. If an object in a full slab is
  * freed then the slab will show up again on the partial lists.
- * Otherwise there is no need to track full slabs unless we have to
- * track full slabs for debugging purposes.
+ * We track full slabs for debugging purposes though because otherwise we
+ * cannot scan all objects.
  *
  * Slabs are freed when they become empty. Teardown and setup is
  * minimal so we rely on the page allocators per cpu caches for
  *                     the fast path.
  */
 
+static inline int SlabDebug(struct page *page)
+{
+#ifdef CONFIG_SLUB_DEBUG
+       return PageError(page);
+#else
+       return 0;
+#endif
+}
+
+static inline void SetSlabDebug(struct page *page)
+{
+#ifdef CONFIG_SLUB_DEBUG
+       SetPageError(page);
+#endif
+}
+
+static inline void ClearSlabDebug(struct page *page)
+{
+#ifdef CONFIG_SLUB_DEBUG
+       ClearPageError(page);
+#endif
+}
+
 /*
  * Issues still to be resolved:
  *
  * - The per cpu array is updated for each new slab and and is a remote
  *   cacheline for most nodes. This could become a bouncing cacheline given
- *   enough frequent updates. There are 16 pointers in a cacheline.so at
- *   max 16 cpus could compete. Likely okay.
+ *   enough frequent updates. There are 16 pointers in a cachelineso at
+ *   max 16 cpus could compete for the cacheline which may be okay.
  *
  * - Support PAGE_ALLOC_DEBUG. Should be easy to do.
  *
 
 #define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
                                SLAB_POISON | SLAB_STORE_USER)
+
 /*
  * Set of flags that will prevent slab merging
  */
 /* Internal SLUB flags */
 #define __OBJECT_POISON 0x80000000     /* Poison object */
 
+/* Not all arches define cache_line_size */
+#ifndef cache_line_size
+#define cache_line_size()      L1_CACHE_BYTES
+#endif
+
 static int kmem_size = sizeof(struct kmem_cache);
 
 #ifdef CONFIG_SMP
@@ -166,7 +195,7 @@ static struct notifier_block slab_notifier;
 static enum {
        DOWN,           /* No slab functionality available */
        PARTIAL,        /* kmem_cache_open() works but kmalloc does not */
-       UP,             /* Everything works */
+       UP,             /* Everything works but does not show up in sysfs */
        SYSFS           /* Sysfs up */
 } slab_state = DOWN;
 
@@ -174,7 +203,19 @@ static enum {
 static DECLARE_RWSEM(slub_lock);
 LIST_HEAD(slab_caches);
 
-#ifdef CONFIG_SYSFS
+/*
+ * Tracking user of a slab.
+ */
+struct track {
+       void *addr;             /* Called from address */
+       int cpu;                /* Was running on cpu */
+       int pid;                /* Pid context */
+       unsigned long when;     /* When did the operation occur */
+};
+
+enum track_item { TRACK_ALLOC, TRACK_FREE };
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
 static int sysfs_slab_add(struct kmem_cache *);
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
@@ -202,6 +243,63 @@ static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
 #endif
 }
 
+static inline int check_valid_pointer(struct kmem_cache *s,
+                               struct page *page, const void *object)
+{
+       void *base;
+
+       if (!object)
+               return 1;
+
+       base = page_address(page);
+       if (object < base || object >= base + s->objects * s->size ||
+               (object - base) % s->size) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Slow version of get and set free pointer.
+ *
+ * This version requires touching the cache lines of kmem_cache which
+ * we avoid to do in the fast alloc free paths. There we obtain the offset
+ * from the page struct.
+ */
+static inline void *get_freepointer(struct kmem_cache *s, void *object)
+{
+       return *(void **)(object + s->offset);
+}
+
+static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+{
+       *(void **)(object + s->offset) = fp;
+}
+
+/* Loop over all objects in a slab */
+#define for_each_object(__p, __s, __addr) \
+       for (__p = (__addr); __p < (__addr) + (__s)->objects * (__s)->size;\
+                       __p += (__s)->size)
+
+/* Scan freelist */
+#define for_each_free_object(__p, __s, __free) \
+       for (__p = (__free); __p; __p = get_freepointer((__s), __p))
+
+/* Determine object index from a given position */
+static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
+{
+       return (p - addr) / s->size;
+}
+
+#ifdef CONFIG_SLUB_DEBUG
+/*
+ * Debug settings:
+ */
+static int slub_debug;
+
+static char *slub_debug_slabs;
+
 /*
  * Object debugging
  */
@@ -237,35 +335,6 @@ static void print_section(char *text, u8 *addr, unsigned int length)
        }
 }
 
-/*
- * Slow version of get and set free pointer.
- *
- * This requires touching the cache lines of kmem_cache.
- * The offset can also be obtained from the page. In that
- * case it is in the cacheline that we already need to touch.
- */
-static void *get_freepointer(struct kmem_cache *s, void *object)
-{
-       return *(void **)(object + s->offset);
-}
-
-static void set_freepointer(struct kmem_cache *s, void *object, void *fp)
-{
-       *(void **)(object + s->offset) = fp;
-}
-
-/*
- * Tracking user of a slab.
- */
-struct track {
-       void *addr;             /* Called from address */
-       int cpu;                /* Was running on cpu */
-       int pid;                /* Pid context */
-       unsigned long when;     /* When did the operation occur */
-};
-
-enum track_item { TRACK_ALLOC, TRACK_FREE };
-
 static struct track *get_track(struct kmem_cache *s, void *object,
        enum track_item alloc)
 {
@@ -400,24 +469,6 @@ static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
        return 1;
 }
 
-
-static int check_valid_pointer(struct kmem_cache *s, struct page *page,
-                                        void *object)
-{
-       void *base;
-
-       if (!object)
-               return 1;
-
-       base = page_address(page);
-       if (object < base || object >= base + s->objects * s->size ||
-               (object - base) % s->size) {
-               return 0;
-       }
-
-       return 1;
-}
-
 /*
  * Object layout:
  *
@@ -425,26 +476,34 @@ static int check_valid_pointer(struct kmem_cache *s, struct page *page,
  *     Bytes of the object to be managed.
  *     If the freepointer may overlay the object then the free
  *     pointer is the first word of the object.
+ *
  *     Poisoning uses 0x6b (POISON_FREE) and the last byte is
  *     0xa5 (POISON_END)
  *
  * object + s->objsize
  *     Padding to reach word boundary. This is also used for Redzoning.
- *     Padding is extended to word size if Redzoning is enabled
- *     and objsize == inuse.
+ *     Padding is extended by another word if Redzoning is enabled and
+ *     objsize == inuse.
+ *
  *     We fill with 0xbb (RED_INACTIVE) for inactive objects and with
  *     0xcc (RED_ACTIVE) for objects in use.
  *
  * object + s->inuse
+ *     Meta data starts here.
+ *
  *     A. Free pointer (if we cannot overwrite object on free)
  *     B. Tracking data for SLAB_STORE_USER
- *     C. Padding to reach required alignment boundary
- *             Padding is done using 0x5a (POISON_INUSE)
+ *     C. Padding to reach required alignment boundary or at mininum
+ *             one word if debuggin is on to be able to detect writes
+ *             before the word boundary.
+ *
+ *     Padding is done using 0x5a (POISON_INUSE)
  *
  * object + s->size
+ *     Nothing is used beyond s->size.
  *
- * If slabcaches are merged then the objsize and inuse boundaries are to
- * be ignored. And therefore no slab options that rely on these boundaries
+ * If slabcaches are merged then the objsize and inuse boundaries are mostly
+ * ignored. And therefore no slab options that rely on these boundaries
  * may be used with merged slabcaches.
  */
 
@@ -570,8 +629,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
                /*
                 * No choice but to zap it and thus loose the remainder
                 * of the free objects in this slab. May cause
-                * another error because the object count maybe
-                * wrong now.
+                * another error because the object count is now wrong.
                 */
                set_freepointer(s, p, NULL);
                return 0;
@@ -611,9 +669,8 @@ static int check_slab(struct kmem_cache *s, struct page *page)
 }
 
 /*
- * Determine if a certain object on a page is on the freelist and
- * therefore free. Must hold the slab lock for cpu slabs to
- * guarantee that the chains are consistent.
+ * Determine if a certain object on a page is on the freelist. Must hold the
+ * slab lock to guarantee that the chains are in a consistent state.
  */
 static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
 {
@@ -659,7 +716,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
 }
 
 /*
- * Tracking of fully allocated slabs for debugging
+ * Tracking of fully allocated slabs for debugging purposes.
  */
 static void add_full(struct kmem_cache_node *n, struct page *page)
 {
@@ -710,7 +767,7 @@ bad:
                /*
                 * If this is a slab page then lets do the best we can
                 * to avoid issues in the future. Marking all objects
-                * as used avoids touching the remainder.
+                * as used avoids touching the remaining objects.
                 */
                printk(KERN_ERR "@@@ SLUB: %s slab 0x%p. Marking all objects used.\n",
                        s->name, page);
@@ -764,6 +821,113 @@ fail:
        return 0;
 }
 
+static void trace(struct kmem_cache *s, struct page *page, void *object, int alloc)
+{
+       if (s->flags & SLAB_TRACE) {
+               printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n",
+                       s->name,
+                       alloc ? "alloc" : "free",
+                       object, page->inuse,
+                       page->freelist);
+
+               if (!alloc)
+                       print_section("Object", (void *)object, s->objsize);
+
+               dump_stack();
+       }
+}
+
+static int __init setup_slub_debug(char *str)
+{
+       if (!str || *str != '=')
+               slub_debug = DEBUG_DEFAULT_FLAGS;
+       else {
+               str++;
+               if (*str == 0 || *str == ',')
+                       slub_debug = DEBUG_DEFAULT_FLAGS;
+               else
+               for( ;*str && *str != ','; str++)
+                       switch (*str) {
+                       case 'f' : case 'F' :
+                               slub_debug |= SLAB_DEBUG_FREE;
+                               break;
+                       case 'z' : case 'Z' :
+                               slub_debug |= SLAB_RED_ZONE;
+                               break;
+                       case 'p' : case 'P' :
+                               slub_debug |= SLAB_POISON;
+                               break;
+                       case 'u' : case 'U' :
+                               slub_debug |= SLAB_STORE_USER;
+                               break;
+                       case 't' : case 'T' :
+                               slub_debug |= SLAB_TRACE;
+                               break;
+                       default:
+                               printk(KERN_ERR "slub_debug option '%c' "
+                                       "unknown. skipped\n",*str);
+                       }
+       }
+
+       if (*str == ',')
+               slub_debug_slabs = str + 1;
+       return 1;
+}
+
+__setup("slub_debug", setup_slub_debug);
+
+static void kmem_cache_open_debug_check(struct kmem_cache *s)
+{
+       /*
+        * The page->offset field is only 16 bit wide. This is an offset
+        * in units of words from the beginning of an object. If the slab
+        * size is bigger then we cannot move the free pointer behind the
+        * object anymore.
+        *
+        * On 32 bit platforms the limit is 256k. On 64bit platforms
+        * the limit is 512k.
+        *
+        * Debugging or ctor/dtors may create a need to move the free
+        * pointer. Fail if this happens.
+        */
+       if (s->size >= 65535 * sizeof(void *)) {
+               BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON |
+                               SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
+               BUG_ON(s->ctor || s->dtor);
+       }
+       else
+               /*
+                * Enable debugging if selected on the kernel commandline.
+                */
+               if (slub_debug && (!slub_debug_slabs ||
+                   strncmp(slub_debug_slabs, s->name,
+                       strlen(slub_debug_slabs)) == 0))
+                               s->flags |= slub_debug;
+}
+#else
+
+static inline int alloc_object_checks(struct kmem_cache *s,
+               struct page *page, void *object) { return 0; }
+
+static inline int free_object_checks(struct kmem_cache *s,
+               struct page *page, void *object) { return 0; }
+
+static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
+static inline void remove_full(struct kmem_cache *s, struct page *page) {}
+static inline void trace(struct kmem_cache *s, struct page *page,
+                       void *object, int alloc) {}
+static inline void init_object(struct kmem_cache *s,
+                       void *object, int active) {}
+static inline void init_tracking(struct kmem_cache *s, void *object) {}
+static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
+                       { return 1; }
+static inline int check_object(struct kmem_cache *s, struct page *page,
+                       void *object, int active) { return 1; }
+static inline void set_track(struct kmem_cache *s, void *object,
+                       enum track_item alloc, void *addr) {}
+static inline void kmem_cache_open_debug_check(struct kmem_cache *s) {}
+#define slub_debug 0
+#endif
 /*
  * Slab allocation and freeing
  */
@@ -797,7 +961,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
 static void setup_object(struct kmem_cache *s, struct page *page,
                                void *object)
 {
-       if (PageError(page)) {
+       if (SlabDebug(page)) {
                init_object(s, object, 0);
                init_tracking(s, object);
        }
@@ -832,7 +996,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        page->flags |= 1 << PG_slab;
        if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
                        SLAB_STORE_USER | SLAB_TRACE))
-               page->flags |= 1 << PG_error;
+               SetSlabDebug(page);
 
        start = page_address(page);
        end = start + s->objects * s->size;
@@ -841,7 +1005,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
                memset(start, POISON_INUSE, PAGE_SIZE << s->order);
 
        last = start;
-       for (p = start + s->size; p < end; p += s->size) {
+       for_each_object(p, s, start) {
                setup_object(s, page, last);
                set_freepointer(s, last, p);
                last = p;
@@ -861,13 +1025,11 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
 {
        int pages = 1 << s->order;
 
-       if (unlikely(PageError(page) || s->dtor)) {
-               void *start = page_address(page);
-               void *end = start + (pages << PAGE_SHIFT);
+       if (unlikely(SlabDebug(page) || s->dtor)) {
                void *p;
 
                slab_pad_check(s, page);
-               for (p = start; p <= end - s->size; p += s->size) {
+               for_each_object(p, s, page_address(page)) {
                        if (s->dtor)
                                s->dtor(p, s, 0);
                        check_object(s, page, p, 0);
@@ -910,7 +1072,8 @@ static void discard_slab(struct kmem_cache *s, struct page *page)
 
        atomic_long_dec(&n->nr_slabs);
        reset_page_mapcount(page);
-       page->flags &= ~(1 << PG_slab | 1 << PG_error);
+       ClearSlabDebug(page);
+       __ClearPageSlab(page);
        free_slab(s, page);
 }
 
@@ -966,9 +1129,9 @@ static void remove_partial(struct kmem_cache *s,
 }
 
 /*
- * Lock page and remove it from the partial list
+ * Lock slab and remove from the partial list.
  *
- * Must hold list_lock
+ * Must hold list_lock.
  */
 static int lock_and_del_slab(struct kmem_cache_node *n, struct page *page)
 {
@@ -981,7 +1144,7 @@ static int lock_and_del_slab(struct kmem_cache_node *n, struct page *page)
 }
 
 /*
- * Try to get a partial slab from a specific node
+ * Try to allocate a partial slab from a specific node.
  */
 static struct page *get_partial_node(struct kmem_cache_node *n)
 {
@@ -990,7 +1153,8 @@ static struct page *get_partial_node(struct kmem_cache_node *n)
        /*
         * Racy check. If we mistakenly see no partial slabs then we
         * just allocate an empty slab. If we mistakenly try to get a
-        * partial slab then get_partials() will return NULL.
+        * partial slab and there is none available then get_partials()
+        * will return NULL.
         */
        if (!n || !n->nr_partial)
                return NULL;
@@ -1006,8 +1170,7 @@ out:
 }
 
 /*
- * Get a page from somewhere. Search in increasing NUMA
- * distances.
+ * Get a page from somewhere. Search in increasing NUMA distances.
  */
 static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
 {
@@ -1017,24 +1180,22 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
        struct page *page;
 
        /*
-        * The defrag ratio allows to configure the tradeoffs between
-        * inter node defragmentation and node local allocations.
-        * A lower defrag_ratio increases the tendency to do local
-        * allocations instead of scanning throught the partial
-        * lists on other nodes.
-        *
-        * If defrag_ratio is set to 0 then kmalloc() always
-        * returns node local objects. If its higher then kmalloc()
-        * may return off node objects in order to avoid fragmentation.
+        * The defrag ratio allows a configuration of the tradeoffs between
+        * inter node defragmentation and node local allocations. A lower
+        * defrag_ratio increases the tendency to do local allocations
+        * instead of attempting to obtain partial slabs from other nodes.
         *
-        * A higher ratio means slabs may be taken from other nodes
-        * thus reducing the number of partial slabs on those nodes.
+        * If the defrag_ratio is set to 0 then kmalloc() always
+        * returns node local objects. If the ratio is higher then kmalloc()
+        * may return off node objects because partial slabs are obtained
+        * from other nodes and filled up.
         *
         * If /sys/slab/xx/defrag_ratio is set to 100 (which makes
-        * defrag_ratio = 1000) then every (well almost) allocation
-        * will first attempt to defrag slab caches on other nodes. This
-        * means scanning over all nodes to look for partial slabs which
-        * may be a bit expensive to do on every slab allocation.
+        * defrag_ratio = 1000) then every (well almost) allocation will
+        * first attempt to defrag slab caches on other nodes. This means
+        * scanning over all nodes to look for partial slabs which may be
+        * expensive if we do it every time we are trying to find a slab
+        * with available objects.
         */
        if (!s->defrag_ratio || get_cycles() % 1024 > s->defrag_ratio)
                return NULL;
@@ -1087,18 +1248,19 @@ static void putback_slab(struct kmem_cache *s, struct page *page)
 
                if (page->freelist)
                        add_partial(n, page);
-               else if (PageError(page) && (s->flags & SLAB_STORE_USER))
+               else if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
                        add_full(n, page);
                slab_unlock(page);
 
        } else {
                if (n->nr_partial < MIN_PARTIAL) {
                        /*
-                        * Adding an empty page to the partial slabs in order
-                        * to avoid page allocator overhead. This page needs to
-                        * come after all the others that are not fully empty
-                        * in order to make sure that we do maximum
-                        * defragmentation.
+                        * Adding an empty slab to the partial slabs in order
+                        * to avoid page allocator overhead. This slab needs
+                        * to come after the other slabs with objects in
+                        * order to fill them up. That way the size of the
+                        * partial list stays small. kmem_cache_shrink can
+                        * reclaim empty slabs from the partial list.
                         */
                        add_partial_tail(n, page);
                        slab_unlock(page);
@@ -1166,11 +1328,11 @@ static void flush_all(struct kmem_cache *s)
  * 1. The page struct
  * 2. The first cacheline of the object to be allocated.
  *
- * The only cache lines that are read (apart from code) is the
+ * The only other cache lines that are read (apart from code) is the
  * per cpu array in the kmem_cache struct.
  *
  * Fastpath is not possible if we need to get a new slab or have
- * debugging enabled (which means all slabs are marked with PageError)
+ * debugging enabled (which means all slabs are marked with SlabDebug)
  */
 static void *slab_alloc(struct kmem_cache *s,
                                gfp_t gfpflags, int node, void *addr)
@@ -1193,7 +1355,7 @@ redo:
        object = page->freelist;
        if (unlikely(!object))
                goto another_slab;
-       if (unlikely(PageError(page)))
+       if (unlikely(SlabDebug(page)))
                goto debug;
 
 have_object:
@@ -1220,9 +1382,11 @@ have_slab:
                cpu = smp_processor_id();
                if (s->cpu_slab[cpu]) {
                        /*
-                        * Someone else populated the cpu_slab while we enabled
-                        * interrupts, or we have got scheduled on another cpu.
-                        * The page may not be on the requested node.
+                        * Someone else populated the cpu_slab while we
+                        * enabled interrupts, or we have gotten scheduled
+                        * on another cpu. The page may not be on the
+                        * requested node even if __GFP_THISNODE was
+                        * specified. So we need to recheck.
                         */
                        if (node == -1 ||
                                page_to_nid(s->cpu_slab[cpu]) == node) {
@@ -1235,7 +1399,7 @@ have_slab:
                                slab_lock(page);
                                goto redo;
                        }
-                       /* Dump the current slab */
+                       /* New slab does not fit our expectations */
                        flush_slab(s, s->cpu_slab[cpu], cpu);
                }
                slab_lock(page);
@@ -1248,12 +1412,7 @@ debug:
                goto another_slab;
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_ALLOC, addr);
-       if (s->flags & SLAB_TRACE) {
-               printk(KERN_INFO "TRACE %s alloc 0x%p inuse=%d fp=0x%p\n",
-                       s->name, object, page->inuse,
-                       page->freelist);
-               dump_stack();
-       }
+       trace(s, page, object, 1);
        init_object(s, object, 1);
        goto have_object;
 }
@@ -1276,7 +1435,8 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
  * The fastpath only writes the cacheline of the page struct and the first
  * cacheline of the object.
  *
- * No special cachelines need to be read
+ * We read the cpu_slab cacheline to check if the slab is the per cpu
+ * slab for this processor.
  */
 static void slab_free(struct kmem_cache *s, struct page *page,
                                        void *x, void *addr)
@@ -1288,7 +1448,7 @@ static void slab_free(struct kmem_cache *s, struct page *page,
        local_irq_save(flags);
        slab_lock(page);
 
-       if (unlikely(PageError(page)))
+       if (unlikely(SlabDebug(page)))
                goto debug;
 checks_ok:
        prior = object[page->offset] = page->freelist;
@@ -1321,7 +1481,7 @@ out_unlock:
 slab_empty:
        if (prior)
                /*
-                * Slab on the partial list.
+                * Slab still on the partial list.
                 */
                remove_partial(s, page);
 
@@ -1337,13 +1497,7 @@ debug:
                remove_full(s, page);
        if (s->flags & SLAB_STORE_USER)
                set_track(s, x, TRACK_FREE, addr);
-       if (s->flags & SLAB_TRACE) {
-               printk(KERN_INFO "TRACE %s free 0x%p inuse=%d fp=0x%p\n",
-                       s->name, object, page->inuse,
-                       page->freelist);
-               print_section("Object", (void *)object, s->objsize);
-               dump_stack();
-       }
+       trace(s, page, object, 0);
        init_object(s, object, 0);
        goto checks_ok;
 }
@@ -1370,22 +1524,16 @@ static struct page *get_object_page(const void *x)
 }
 
 /*
- * kmem_cache_open produces objects aligned at "size" and the first object
- * is placed at offset 0 in the slab (We have no metainformation on the
- * slab, all slabs are in essence "off slab").
- *
- * In order to get the desired alignment one just needs to align the
- * size.
+ * Object placement in a slab is made very easy because we always start at
+ * offset 0. If we tune the size of the object to the alignment then we can
+ * get the required alignment by putting one properly sized object after
+ * another.
  *
  * Notice that the allocation order determines the sizes of the per cpu
  * caches. Each processor has always one slab available for allocations.
  * Increasing the allocation order reduces the number of times that slabs
- * must be moved on and off the partial lists and therefore may influence
+ * must be moved on and off the partial lists and is therefore a factor in
  * locking overhead.
- *
- * The offset is used to relocate the free list link in each object. It is
- * therefore possible to move the free list link behind the object. This
- * is necessary for RCU to work properly and also useful for debugging.
  */
 
 /*
@@ -1396,76 +1544,110 @@ static struct page *get_object_page(const void *x)
  */
 static int slub_min_order;
 static int slub_max_order = DEFAULT_MAX_ORDER;
-
-/*
- * Minimum number of objects per slab. This is necessary in order to
- * reduce locking overhead. Similar to the queue size in SLAB.
- */
 static int slub_min_objects = DEFAULT_MIN_OBJECTS;
 
 /*
  * Merge control. If this is set then no merging of slab caches will occur.
+ * (Could be removed. This was introduced to pacify the merge skeptics.)
  */
 static int slub_nomerge;
 
-/*
- * Debug settings:
- */
-static int slub_debug;
-
-static char *slub_debug_slabs;
-
 /*
  * Calculate the order of allocation given an slab object size.
  *
- * The order of allocation has significant impact on other elements
- * of the system. Generally order 0 allocations should be preferred
- * since they do not cause fragmentation in the page allocator. Larger
- * objects may have problems with order 0 because there may be too much
- * space left unused in a slab. We go to a higher order if more than 1/8th
- * of the slab would be wasted.
+ * The order of allocation has significant impact on performance and other
+ * system components. Generally order 0 allocations should be preferred since
+ * order 0 does not cause fragmentation in the page allocator. Larger objects
+ * be problematic to put into order 0 slabs because there may be too much
+ * unused space left. We go to a higher order if more than 1/8th of the slab
+ * would be wasted.
  *
- * In order to reach satisfactory performance we must ensure that
- * a minimum number of objects is in one slab. Otherwise we may
- * generate too much activity on the partial lists. This is less a
- * concern for large slabs though. slub_max_order specifies the order
- * where we begin to stop considering the number of objects in a slab.
+ * In order to reach satisfactory performance we must ensure that a minimum
+ * number of objects is in one slab. Otherwise we may generate too much
+ * activity on the partial lists which requires taking the list_lock. This is
+ * less a concern for large slabs though which are rarely used.
  *
- * Higher order allocations also allow the placement of more objects
- * in a slab and thereby reduce object handling overhead. If the user
- * has requested a higher mininum order then we start with that one
- * instead of zero.
+ * slub_max_order specifies the order where we begin to stop considering the
+ * number of objects in a slab as critical. If we reach slub_max_order then
+ * we try to keep the page order as low as possible. So we accept more waste
+ * of space in favor of a small page order.
+ *
+ * Higher order allocations also allow the placement of more objects in a
+ * slab and thereby reduce object handling overhead. If the user has
+ * requested a higher mininum order then we start with that one instead of
+ * the smallest order which will fit the object.
  */
-static int calculate_order(int size)
+static inline int slab_order(int size, int min_objects,
+                               int max_order, int fract_leftover)
 {
        int order;
        int rem;
 
-       for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT);
-                       order < MAX_ORDER; order++) {
-               unsigned long slab_size = PAGE_SIZE << order;
+       for (order = max(slub_min_order,
+                               fls(min_objects * size - 1) - PAGE_SHIFT);
+                       order <= max_order; order++) {
 
-               if (slub_max_order > order &&
-                               slab_size < slub_min_objects * size)
-                       continue;
+               unsigned long slab_size = PAGE_SIZE << order;
 
-               if (slab_size < size)
+               if (slab_size < min_objects * size)
                        continue;
 
                rem = slab_size % size;
 
-               if (rem <= (PAGE_SIZE << order) / 8)
+               if (rem <= slab_size / fract_leftover)
                        break;
 
        }
-       if (order >= MAX_ORDER)
-               return -E2BIG;
+
        return order;
 }
 
+static inline int calculate_order(int size)
+{
+       int order;
+       int min_objects;
+       int fraction;
+
+       /*
+        * Attempt to find best configuration for a slab. This
+        * works by first attempting to generate a layout with
+        * the best configuration and backing off gradually.
+        *
+        * First we reduce the acceptable waste in a slab. Then
+        * we reduce the minimum objects required in a slab.
+        */
+       min_objects = slub_min_objects;
+       while (min_objects > 1) {
+               fraction = 8;
+               while (fraction >= 4) {
+                       order = slab_order(size, min_objects,
+                                               slub_max_order, fraction);
+                       if (order <= slub_max_order)
+                               return order;
+                       fraction /= 2;
+               }
+               min_objects /= 2;
+       }
+
+       /*
+        * We were unable to place multiple objects in a slab. Now
+        * lets see if we can place a single object there.
+        */
+       order = slab_order(size, 1, slub_max_order, 1);
+       if (order <= slub_max_order)
+               return order;
+
+       /*
+        * Doh this slab cannot be placed using slub_max_order.
+        */
+       order = slab_order(size, 1, MAX_ORDER, 1);
+       if (order <= MAX_ORDER)
+               return order;
+       return -ENOSYS;
+}
+
 /*
- * Function to figure out which alignment to use from the
- * various ways of specifying it.
+ * Figure out what the alignment of the objects will be.
  */
 static unsigned long calculate_alignment(unsigned long flags,
                unsigned long align, unsigned long size)
@@ -1480,8 +1662,8 @@ static unsigned long calculate_alignment(unsigned long flags,
         * then use it.
         */
        if ((flags & SLAB_HWCACHE_ALIGN) &&
-                       size > L1_CACHE_BYTES / 2)
-               return max_t(unsigned long, align, L1_CACHE_BYTES);
+                       size > cache_line_size() / 2)
+               return max_t(unsigned long, align, cache_line_size());
 
        if (align < ARCH_SLAB_MINALIGN)
                return ARCH_SLAB_MINALIGN;
@@ -1619,22 +1801,23 @@ static int calculate_sizes(struct kmem_cache *s)
         */
        size = ALIGN(size, sizeof(void *));
 
+#ifdef CONFIG_SLUB_DEBUG
        /*
-        * If we are redzoning then check if there is some space between the
+        * If we are Redzoning then check if there is some space between the
         * end of the object and the free pointer. If not then add an
-        * additional word, so that we can establish a redzone between
-        * the object and the freepointer to be able to check for overwrites.
+        * additional word to have some bytes to store Redzone information.
         */
        if ((flags & SLAB_RED_ZONE) && size == s->objsize)
                size += sizeof(void *);
+#endif
 
        /*
-        * With that we have determined how much of the slab is in actual
-        * use by the object. This is the potential offset to the free
-        * pointer.
+        * With that we have determined the number of bytes in actual use
+        * by the object. This is the potential offset to the free pointer.
         */
        s->inuse = size;
 
+#ifdef CONFIG_SLUB_DEBUG
        if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
                s->ctor || s->dtor)) {
                /*
@@ -1656,7 +1839,7 @@ static int calculate_sizes(struct kmem_cache *s)
                 */
                size += 2 * sizeof(struct track);
 
-       if (flags & DEBUG_DEFAULT_FLAGS)
+       if (flags & SLAB_RED_ZONE)
                /*
                 * Add some empty padding so that we can catch
                 * overwrites from earlier objects rather than let
@@ -1665,10 +1848,12 @@ static int calculate_sizes(struct kmem_cache *s)
                 * of the object.
                 */
                size += sizeof(void *);
+#endif
+
        /*
         * Determine the alignment based on various parameters that the
-        * user specified (this is unecessarily complex due to the attempt
-        * to be compatible with SLAB. Should be cleaned up some day).
+        * user specified and the dynamic determination of cache line size
+        * on bootup.
         */
        align = calculate_alignment(flags, align, s->objsize);
 
@@ -1700,23 +1885,6 @@ static int calculate_sizes(struct kmem_cache *s)
 
 }
 
-static int __init finish_bootstrap(void)
-{
-       struct list_head *h;
-       int err;
-
-       slab_state = SYSFS;
-
-       list_for_each(h, &slab_caches) {
-               struct kmem_cache *s =
-                       container_of(h, struct kmem_cache, list);
-
-               err = sysfs_slab_add(s);
-               BUG_ON(err);
-       }
-       return 0;
-}
-
 static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
                const char *name, size_t size,
                size_t align, unsigned long flags,
@@ -1730,32 +1898,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
        s->objsize = size;
        s->flags = flags;
        s->align = align;
-
-       /*
-        * The page->offset field is only 16 bit wide. This is an offset
-        * in units of words from the beginning of an object. If the slab
-        * size is bigger then we cannot move the free pointer behind the
-        * object anymore.
-        *
-        * On 32 bit platforms the limit is 256k. On 64bit platforms
-        * the limit is 512k.
-        *
-        * Debugging or ctor/dtors may create a need to move the free
-        * pointer. Fail if this happens.
-        */
-       if (s->size >= 65535 * sizeof(void *)) {
-               BUG_ON(flags & (SLAB_RED_ZONE | SLAB_POISON |
-                               SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
-               BUG_ON(ctor || dtor);
-       }
-       else
-               /*
-                * Enable debugging if selected on the kernel commandline.
-                */
-               if (slub_debug && (!slub_debug_slabs ||
-                   strncmp(slub_debug_slabs, name,
-                       strlen(slub_debug_slabs)) == 0))
-                               s->flags |= slub_debug;
+       kmem_cache_open_debug_check(s);
 
        if (!calculate_sizes(s))
                goto error;
@@ -1783,7 +1926,6 @@ EXPORT_SYMBOL(kmem_cache_open);
 int kmem_ptr_validate(struct kmem_cache *s, const void *object)
 {
        struct page * page;
-       void *addr;
 
        page = get_object_page(object);
 
@@ -1791,13 +1933,7 @@ int kmem_ptr_validate(struct kmem_cache *s, const void *object)
                /* No slab or wrong slab */
                return 0;
 
-       addr = page_address(page);
-       if (object < addr || object >= addr + s->objects * s->size)
-               /* Out of bounds */
-               return 0;
-
-       if ((object - addr) % s->size)
-               /* Improperly aligned */
+       if (!check_valid_pointer(s, page, object))
                return 0;
 
        /*
@@ -1826,7 +1962,8 @@ const char *kmem_cache_name(struct kmem_cache *s)
 EXPORT_SYMBOL(kmem_cache_name);
 
 /*
- * Attempt to free all slabs on a node
+ * Attempt to free all slabs on a node. Return the number of slabs we
+ * were unable to free.
  */
 static int free_list(struct kmem_cache *s, struct kmem_cache_node *n,
                        struct list_head *list)
@@ -1847,7 +1984,7 @@ static int free_list(struct kmem_cache *s, struct kmem_cache_node *n,
 }
 
 /*
- * Release all resources used by slab cache
+ * Release all resources used by a slab cache.
  */
 static int kmem_cache_close(struct kmem_cache *s)
 {
@@ -1932,45 +2069,6 @@ static int __init setup_slub_nomerge(char *str)
 
 __setup("slub_nomerge", setup_slub_nomerge);
 
-static int __init setup_slub_debug(char *str)
-{
-       if (!str || *str != '=')
-               slub_debug = DEBUG_DEFAULT_FLAGS;
-       else {
-               str++;
-               if (*str == 0 || *str == ',')
-                       slub_debug = DEBUG_DEFAULT_FLAGS;
-               else
-               for( ;*str && *str != ','; str++)
-                       switch (*str) {
-                       case 'f' : case 'F' :
-                               slub_debug |= SLAB_DEBUG_FREE;
-                               break;
-                       case 'z' : case 'Z' :
-                               slub_debug |= SLAB_RED_ZONE;
-                               break;
-                       case 'p' : case 'P' :
-                               slub_debug |= SLAB_POISON;
-                               break;
-                       case 'u' : case 'U' :
-                               slub_debug |= SLAB_STORE_USER;
-                               break;
-                       case 't' : case 'T' :
-                               slub_debug |= SLAB_TRACE;
-                               break;
-                       default:
-                               printk(KERN_ERR "slub_debug option '%c' "
-                                       "unknown. skipped\n",*str);
-                       }
-       }
-
-       if (*str == ',')
-               slub_debug_slabs = str + 1;
-       return 1;
-}
-
-__setup("slub_debug", setup_slub_debug);
-
 static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s,
                const char *name, int size, gfp_t gfp_flags)
 {
@@ -2108,13 +2206,14 @@ void kfree(const void *x)
 EXPORT_SYMBOL(kfree);
 
 /*
- *  kmem_cache_shrink removes empty slabs from the partial lists
- *  and then sorts the partially allocated slabs by the number
- *  of items in use. The slabs with the most items in use
- *  come first. New allocations will remove these from the
- *  partial list because they are full. The slabs with the
- *  least items are placed last. If it happens that the objects
- *  are freed then the page can be returned to the page allocator.
+ * kmem_cache_shrink removes empty slabs from the partial lists and sorts
+ * the remaining slabs by the number of items in use. The slabs with the
+ * most items in use come first. New allocations will then fill those up
+ * and thus they can be removed from the partial lists.
+ *
+ * The slabs with the least items are placed last. This results in them
+ * being allocated from last increasing the chance that the last objects
+ * are freed in them.
  */
 int kmem_cache_shrink(struct kmem_cache *s)
 {
@@ -2143,12 +2242,10 @@ int kmem_cache_shrink(struct kmem_cache *s)
                spin_lock_irqsave(&n->list_lock, flags);
 
                /*
-                * Build lists indexed by the items in use in
-                * each slab or free slabs if empty.
+                * Build lists indexed by the items in use in each slab.
                 *
-                * Note that concurrent frees may occur while
-                * we hold the list_lock. page->inuse here is
-                * the upper limit.
+                * Note that concurrent frees may occur while we hold the
+                * list_lock. page->inuse here is the upper limit.
                 */
                list_for_each_entry_safe(page, t, &n->partial, lru) {
                        if (!page->inuse && slab_trylock(page)) {
@@ -2172,8 +2269,8 @@ int kmem_cache_shrink(struct kmem_cache *s)
                        goto out;
 
                /*
-                * Rebuild the partial list with the slabs filled up
-                * most first and the least used slabs at the end.
+                * Rebuild the partial list with the slabs filled up most
+                * first and the least used slabs at the end.
                 */
                for (i = s->objects - 1; i >= 0; i--)
                        list_splice(slabs_by_inuse + i, n->partial.prev);
@@ -2189,7 +2286,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 
 /**
  * krealloc - reallocate memory. The contents will remain unchanged.
- *
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
@@ -2201,9 +2297,8 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  */
 void *krealloc(const void *p, size_t new_size, gfp_t flags)
 {
-       struct kmem_cache *new_cache;
        void *ret;
-       struct page *page;
+       size_t ks;
 
        if (unlikely(!p))
                return kmalloc(new_size, flags);
@@ -2213,19 +2308,13 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
                return NULL;
        }
 
-       page = virt_to_head_page(p);
-
-       new_cache = get_slab(new_size, flags);
-
-       /*
-        * If new size fits in the current cache, bail out.
-        */
-       if (likely(page->slab == new_cache))
+       ks = ksize(p);
+       if (ks >= new_size)
                return (void *)p;
 
        ret = kmalloc(new_size, flags);
        if (ret) {
-               memcpy(ret, p, min(new_size, ksize(p)));
+               memcpy(ret, p, min(new_size, ks));
                kfree(p);
        }
        return ret;
@@ -2243,7 +2332,7 @@ void __init kmem_cache_init(void)
 #ifdef CONFIG_NUMA
        /*
         * Must first have the slab cache available for the allocations of the
-        * struct kmalloc_cache_node's. There is special bootstrap code in
+        * struct kmem_cache_node's. There is special bootstrap code in
         * kmem_cache_open for slab_state == DOWN.
         */
        create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
@@ -2280,7 +2369,7 @@ void __init kmem_cache_init(void)
 
        printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
                " Processors=%d, Nodes=%d\n",
-               KMALLOC_SHIFT_HIGH, L1_CACHE_BYTES,
+               KMALLOC_SHIFT_HIGH, cache_line_size(),
                slub_min_order, slub_max_order, slub_min_objects,
                nr_cpu_ids, nr_node_ids);
 }
@@ -2415,8 +2504,8 @@ static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
 }
 
 /*
- * Use the cpu notifier to insure that the slab are flushed
- * when necessary.
+ * Use the cpu notifier to insure that the cpu slabs are flushed when
+ * necessary.
  */
 static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
                unsigned long action, void *hcpu)
@@ -2425,7 +2514,9 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                for_all_slabs(__flush_cpu_slab, cpu);
                break;
        default:
@@ -2439,153 +2530,6 @@ static struct notifier_block __cpuinitdata slab_notifier =
 
 #endif
 
-#ifdef CONFIG_NUMA
-
-/*****************************************************************
- * Generic reaper used to support the page allocator
- * (the cpu slabs are reaped by a per slab workqueue).
- *
- * Maybe move this to the page allocator?
- ****************************************************************/
-
-static DEFINE_PER_CPU(unsigned long, reap_node);
-
-static void init_reap_node(int cpu)
-{
-       int node;
-
-       node = next_node(cpu_to_node(cpu), node_online_map);
-       if (node == MAX_NUMNODES)
-               node = first_node(node_online_map);
-
-       __get_cpu_var(reap_node) = node;
-}
-
-static void next_reap_node(void)
-{
-       int node = __get_cpu_var(reap_node);
-
-       /*
-        * Also drain per cpu pages on remote zones
-        */
-       if (node != numa_node_id())
-               drain_node_pages(node);
-
-       node = next_node(node, node_online_map);
-       if (unlikely(node >= MAX_NUMNODES))
-               node = first_node(node_online_map);
-       __get_cpu_var(reap_node) = node;
-}
-#else
-#define init_reap_node(cpu) do { } while (0)
-#define next_reap_node(void) do { } while (0)
-#endif
-
-#define REAPTIMEOUT_CPUC       (2*HZ)
-
-#ifdef CONFIG_SMP
-static DEFINE_PER_CPU(struct delayed_work, reap_work);
-
-static void cache_reap(struct work_struct *unused)
-{
-       next_reap_node();
-       refresh_cpu_vm_stats(smp_processor_id());
-       schedule_delayed_work(&__get_cpu_var(reap_work),
-                                     REAPTIMEOUT_CPUC);
-}
-
-static void __devinit start_cpu_timer(int cpu)
-{
-       struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
-
-       /*
-        * When this gets called from do_initcalls via cpucache_init(),
-        * init_workqueues() has already run, so keventd will be setup
-        * at that time.
-        */
-       if (keventd_up() && reap_work->work.func == NULL) {
-               init_reap_node(cpu);
-               INIT_DELAYED_WORK(reap_work, cache_reap);
-               schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
-       }
-}
-
-static int __init cpucache_init(void)
-{
-       int cpu;
-
-       /*
-        * Register the timers that drain pcp pages and update vm statistics
-        */
-       for_each_online_cpu(cpu)
-               start_cpu_timer(cpu);
-       return 0;
-}
-__initcall(cpucache_init);
-#endif
-
-#ifdef SLUB_RESILIENCY_TEST
-static unsigned long validate_slab_cache(struct kmem_cache *s);
-
-static void resiliency_test(void)
-{
-       u8 *p;
-
-       printk(KERN_ERR "SLUB resiliency testing\n");
-       printk(KERN_ERR "-----------------------\n");
-       printk(KERN_ERR "A. Corruption after allocation\n");
-
-       p = kzalloc(16, GFP_KERNEL);
-       p[16] = 0x12;
-       printk(KERN_ERR "\n1. kmalloc-16: Clobber Redzone/next pointer"
-                       " 0x12->0x%p\n\n", p + 16);
-
-       validate_slab_cache(kmalloc_caches + 4);
-
-       /* Hmmm... The next two are dangerous */
-       p = kzalloc(32, GFP_KERNEL);
-       p[32 + sizeof(void *)] = 0x34;
-       printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
-                       " 0x34 -> -0x%p\n", p);
-       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
-
-       validate_slab_cache(kmalloc_caches + 5);
-       p = kzalloc(64, GFP_KERNEL);
-       p += 64 + (get_cycles() & 0xff) * sizeof(void *);
-       *p = 0x56;
-       printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
-                                                                       p);
-       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
-       validate_slab_cache(kmalloc_caches + 6);
-
-       printk(KERN_ERR "\nB. Corruption after free\n");
-       p = kzalloc(128, GFP_KERNEL);
-       kfree(p);
-       *p = 0x78;
-       printk(KERN_ERR "1. kmalloc-128: Clobber first word 0x78->0x%p\n\n", p);
-       validate_slab_cache(kmalloc_caches + 7);
-
-       p = kzalloc(256, GFP_KERNEL);
-       kfree(p);
-       p[50] = 0x9a;
-       printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n", p);
-       validate_slab_cache(kmalloc_caches + 8);
-
-       p = kzalloc(512, GFP_KERNEL);
-       kfree(p);
-       p[512] = 0xab;
-       printk(KERN_ERR "\n3. kmalloc-512: Clobber redzone 0xab->0x%p\n\n", p);
-       validate_slab_cache(kmalloc_caches + 9);
-}
-#else
-static void resiliency_test(void) {};
-#endif
-
-/*
- * These are not as efficient as kmalloc for the non debug case.
- * We do not have the page struct available so we have to touch one
- * cacheline in struct kmem_cache to check slab flags.
- */
 void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
 {
        struct kmem_cache *s = get_slab(size, gfpflags);
@@ -2607,13 +2551,12 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
        return slab_alloc(s, gfpflags, node, caller);
 }
 
-#ifdef CONFIG_SYSFS
-
+#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
 static int validate_slab(struct kmem_cache *s, struct page *page)
 {
        void *p;
        void *addr = page_address(page);
-       unsigned long map[BITS_TO_LONGS(s->objects)];
+       DECLARE_BITMAP(map, s->objects);
 
        if (!check_slab(s, page) ||
                        !on_freelist(s, page, NULL))
@@ -2622,14 +2565,14 @@ static int validate_slab(struct kmem_cache *s, struct page *page)
        /* Now we know that a valid freelist exists */
        bitmap_zero(map, s->objects);
 
-       for(p = page->freelist; p; p = get_freepointer(s, p)) {
-               set_bit((p - addr) / s->size, map);
+       for_each_free_object(p, s, page->freelist) {
+               set_bit(slab_index(p, s, addr), map);
                if (!check_object(s, page, p, 0))
                        return 0;
        }
 
-       for(p = addr; p < addr + s->objects * s->size; p += s->size)
-               if (!test_bit((p - addr) / s->size, map))
+       for_each_object(p, s, addr)
+               if (!test_bit(slab_index(p, s, addr), map))
                        if (!check_object(s, page, p, 1))
                                return 0;
        return 1;
@@ -2645,12 +2588,12 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page)
                        s->name, page);
 
        if (s->flags & DEBUG_DEFAULT_FLAGS) {
-               if (!PageError(page))
-                       printk(KERN_ERR "SLUB %s: PageError not set "
+               if (!SlabDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlabDebug not set "
                                "on slab 0x%p\n", s->name, page);
        } else {
-               if (PageError(page))
-                       printk(KERN_ERR "SLUB %s: PageError set on "
+               if (SlabDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlabDebug set on "
                                "slab 0x%p\n", s->name, page);
        }
 }
@@ -2702,14 +2645,76 @@ static unsigned long validate_slab_cache(struct kmem_cache *s)
        return count;
 }
 
+#ifdef SLUB_RESILIENCY_TEST
+static void resiliency_test(void)
+{
+       u8 *p;
+
+       printk(KERN_ERR "SLUB resiliency testing\n");
+       printk(KERN_ERR "-----------------------\n");
+       printk(KERN_ERR "A. Corruption after allocation\n");
+
+       p = kzalloc(16, GFP_KERNEL);
+       p[16] = 0x12;
+       printk(KERN_ERR "\n1. kmalloc-16: Clobber Redzone/next pointer"
+                       " 0x12->0x%p\n\n", p + 16);
+
+       validate_slab_cache(kmalloc_caches + 4);
+
+       /* Hmmm... The next two are dangerous */
+       p = kzalloc(32, GFP_KERNEL);
+       p[32 + sizeof(void *)] = 0x34;
+       printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
+                       " 0x34 -> -0x%p\n", p);
+       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+
+       validate_slab_cache(kmalloc_caches + 5);
+       p = kzalloc(64, GFP_KERNEL);
+       p += 64 + (get_cycles() & 0xff) * sizeof(void *);
+       *p = 0x56;
+       printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
+                                                                       p);
+       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+       validate_slab_cache(kmalloc_caches + 6);
+
+       printk(KERN_ERR "\nB. Corruption after free\n");
+       p = kzalloc(128, GFP_KERNEL);
+       kfree(p);
+       *p = 0x78;
+       printk(KERN_ERR "1. kmalloc-128: Clobber first word 0x78->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 7);
+
+       p = kzalloc(256, GFP_KERNEL);
+       kfree(p);
+       p[50] = 0x9a;
+       printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 8);
+
+       p = kzalloc(512, GFP_KERNEL);
+       kfree(p);
+       p[512] = 0xab;
+       printk(KERN_ERR "\n3. kmalloc-512: Clobber redzone 0xab->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 9);
+}
+#else
+static void resiliency_test(void) {};
+#endif
+
 /*
- * Generate lists of locations where slabcache objects are allocated
+ * Generate lists of code addresses where slabcache objects are allocated
  * and freed.
  */
 
 struct location {
        unsigned long count;
        void *addr;
+       long long sum_time;
+       long min_time;
+       long max_time;
+       long min_pid;
+       long max_pid;
+       cpumask_t cpus;
+       nodemask_t nodes;
 };
 
 struct loc_track {
@@ -2750,11 +2755,12 @@ static int alloc_loc_track(struct loc_track *t, unsigned long max)
 }
 
 static int add_location(struct loc_track *t, struct kmem_cache *s,
-                                               void *addr)
+                               const struct track *track)
 {
        long start, end, pos;
        struct location *l;
        void *caddr;
+       unsigned long age = jiffies - track->when;
 
        start = -1;
        end = t->count;
@@ -2770,19 +2776,36 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                        break;
 
                caddr = t->loc[pos].addr;
-               if (addr == caddr) {
-                       t->loc[pos].count++;
+               if (track->addr == caddr) {
+
+                       l = &t->loc[pos];
+                       l->count++;
+                       if (track->when) {
+                               l->sum_time += age;
+                               if (age < l->min_time)
+                                       l->min_time = age;
+                               if (age > l->max_time)
+                                       l->max_time = age;
+
+                               if (track->pid < l->min_pid)
+                                       l->min_pid = track->pid;
+                               if (track->pid > l->max_pid)
+                                       l->max_pid = track->pid;
+
+                               cpu_set(track->cpu, l->cpus);
+                       }
+                       node_set(page_to_nid(virt_to_page(track)), l->nodes);
                        return 1;
                }
 
-               if (addr < caddr)
+               if (track->addr < caddr)
                        end = pos;
                else
                        start = pos;
        }
 
        /*
-        * Not found. Insert new tracking element
+        * Not found. Insert new tracking element.
         */
        if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max))
                return 0;
@@ -2793,7 +2816,16 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                        (t->count - pos) * sizeof(struct location));
        t->count++;
        l->count = 1;
-       l->addr = addr;
+       l->addr = track->addr;
+       l->sum_time = age;
+       l->min_time = age;
+       l->max_time = age;
+       l->min_pid = track->pid;
+       l->max_pid = track->pid;
+       cpus_clear(l->cpus);
+       cpu_set(track->cpu, l->cpus);
+       nodes_clear(l->nodes);
+       node_set(page_to_nid(virt_to_page(track)), l->nodes);
        return 1;
 }
 
@@ -2801,19 +2833,16 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s,
                struct page *page, enum track_item alloc)
 {
        void *addr = page_address(page);
-       unsigned long map[BITS_TO_LONGS(s->objects)];
+       DECLARE_BITMAP(map, s->objects);
        void *p;
 
        bitmap_zero(map, s->objects);
-       for (p = page->freelist; p; p = get_freepointer(s, p))
-               set_bit((p - addr) / s->size, map);
-
-       for (p = addr; p < addr + s->objects * s->size; p += s->size)
-               if (!test_bit((p - addr) / s->size, map)) {
-                       void *addr = get_track(s, p, alloc)->addr;
+       for_each_free_object(p, s, page->freelist)
+               set_bit(slab_index(p, s, addr), map);
 
-                       add_location(t, s, addr);
-               }
+       for_each_object(p, s, addr)
+               if (!test_bit(slab_index(p, s, addr), map))
+                       add_location(t, s, get_track(s, p, alloc));
 }
 
 static int list_locations(struct kmem_cache *s, char *buf,
@@ -2847,15 +2876,47 @@ static int list_locations(struct kmem_cache *s, char *buf,
        }
 
        for (i = 0; i < t.count; i++) {
-               void *addr = t.loc[i].addr;
+               struct location *l = &t.loc[i];
 
                if (n > PAGE_SIZE - 100)
                        break;
-               n += sprintf(buf + n, "%7ld ", t.loc[i].count);
-               if (addr)
-                       n += sprint_symbol(buf + n, (unsigned long)t.loc[i].addr);
+               n += sprintf(buf + n, "%7ld ", l->count);
+
+               if (l->addr)
+                       n += sprint_symbol(buf + n, (unsigned long)l->addr);
                else
                        n += sprintf(buf + n, "<not-available>");
+
+               if (l->sum_time != l->min_time) {
+                       unsigned long remainder;
+
+                       n += sprintf(buf + n, " age=%ld/%ld/%ld",
+                       l->min_time,
+                       div_long_long_rem(l->sum_time, l->count, &remainder),
+                       l->max_time);
+               } else
+                       n += sprintf(buf + n, " age=%ld",
+                               l->min_time);
+
+               if (l->min_pid != l->max_pid)
+                       n += sprintf(buf + n, " pid=%ld-%ld",
+                               l->min_pid, l->max_pid);
+               else
+                       n += sprintf(buf + n, " pid=%ld",
+                               l->min_pid);
+
+               if (num_online_cpus() > 1 && !cpus_empty(l->cpus)) {
+                       n += sprintf(buf + n, " cpus=");
+                       n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50,
+                                       l->cpus);
+               }
+
+               if (num_online_nodes() > 1 && !nodes_empty(l->nodes)) {
+                       n += sprintf(buf + n, " nodes=");
+                       n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50,
+                                       l->nodes);
+               }
+
                n += sprintf(buf + n, "\n");
        }
 
@@ -3491,6 +3552,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
 
 static int __init slab_sysfs_init(void)
 {
+       struct list_head *h;
        int err;
 
        err = subsystem_register(&slab_subsys);
@@ -3499,7 +3561,15 @@ static int __init slab_sysfs_init(void)
                return -ENOSYS;
        }
 
-       finish_bootstrap();
+       slab_state = SYSFS;
+
+       list_for_each(h, &slab_caches) {
+               struct kmem_cache *s =
+                       container_of(h, struct kmem_cache, list);
+
+               err = sysfs_slab_add(s);
+               BUG_ON(err);
+       }
 
        while (alias_list) {
                struct saved_alias *al = alias_list;
@@ -3515,6 +3585,4 @@ static int __init slab_sysfs_init(void)
 }
 
 __initcall(slab_sysfs_init);
-#else
-__initcall(finish_bootstrap);
 #endif
index 893e5621c247c5a9be9f3d565f7f2c82d92ac80a..6f3fff907bc25719926d0e91f4b0ea70335b4447 100644 (file)
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(page_to_nid);
 #endif
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
-static struct mem_section *sparse_index_alloc(int nid)
+static struct mem_section noinline *sparse_index_alloc(int nid)
 {
        struct mem_section *section = NULL;
        unsigned long array_size = SECTIONS_PER_ROOT *
@@ -61,7 +61,7 @@ static struct mem_section *sparse_index_alloc(int nid)
        return section;
 }
 
-static int sparse_index_init(unsigned long section_nr, int nid)
+static int __meminit sparse_index_init(unsigned long section_nr, int nid)
 {
        static DEFINE_SPINLOCK(index_init_lock);
        unsigned long root = SECTION_NR_TO_ROOT(section_nr);
@@ -138,7 +138,7 @@ static inline int sparse_early_nid(struct mem_section *section)
 }
 
 /* Record a memory area against a node. */
-void memory_present(int nid, unsigned long start, unsigned long end)
+void __init memory_present(int nid, unsigned long start, unsigned long end)
 {
        unsigned long pfn;
 
@@ -197,7 +197,7 @@ struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pn
        return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
 }
 
-static int sparse_init_one_section(struct mem_section *ms,
+static int __meminit sparse_init_one_section(struct mem_section *ms,
                unsigned long pnum, struct page *mem_map)
 {
        if (!valid_section(ms))
@@ -209,7 +209,7 @@ static int sparse_init_one_section(struct mem_section *ms,
        return 1;
 }
 
-static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
+static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
 {
        struct page *map;
        struct mem_section *ms = __nr_to_section(pnum);
@@ -288,6 +288,7 @@ void __init sparse_init(void)
        }
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * returns the number of sections whose mem_maps were properly
  * set.  If this is <=0, then that means that the passed-in
@@ -327,3 +328,4 @@ out:
                __kfree_section_memmap(memmap, nr_pages);
        return ret;
 }
+#endif
index 218c52a24a216831a347736cde51045563854770..d3cb966fe9920734f9c97a1fb27cdda36829f493 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -488,7 +488,7 @@ static int cpu_swap_callback(struct notifier_block *nfb,
        long *committed;
 
        committed = &per_cpu(committed_space, (long)hcpu);
-       if (action == CPU_DEAD) {
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
                atomic_add(*committed, &vm_committed_space);
                *committed = 0;
                __lru_add_drain((long)hcpu);
index 0f4b6d18ab0ed663360e0fba11f46f23e8c6b5b3..4fbe1a2da5fb973acc352b1b17d87ca390aab376 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/swap.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 #include <linux/pagevec.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/buffer_head.h> /* grr. try_to_release_page,
@@ -46,7 +47,7 @@ void do_invalidatepage(struct page *page, unsigned long offset)
 
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
-       memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+       zero_user_page(page, partial, PAGE_CACHE_SIZE - partial, KM_USER0);
        if (PagePrivate(page))
                do_invalidatepage(page, partial);
 }
index cb5aabda70461818e2184872ef340bac87d3f055..faa2a521dea321f6b8a2b19d1b3ac4b2ad245044 100644 (file)
@@ -755,3 +755,10 @@ out_einval_locked:
 }
 EXPORT_SYMBOL(remap_vmalloc_range);
 
+/*
+ * Implement a stub for vmalloc_sync_all() if the architecture chose not to
+ * have one.
+ */
+void  __attribute__((weak)) vmalloc_sync_all(void)
+{
+}
index 56651a10c36645a7f58c87ac9b97599b72255b61..1be5a6376ef0719b5e46937924a8a66cf59a35f1 100644 (file)
@@ -284,12 +284,8 @@ static void handle_write_error(struct address_space *mapping,
                                struct page *page, int error)
 {
        lock_page(page);
-       if (page_mapping(page) == mapping) {
-               if (error == -ENOSPC)
-                       set_bit(AS_ENOSPC, &mapping->flags);
-               else
-                       set_bit(AS_EIO, &mapping->flags);
-       }
+       if (page_mapping(page) == mapping)
+               mapping_set_error(mapping, error);
        unlock_page(page);
 }
 
@@ -1532,7 +1528,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
        pg_data_t *pgdat;
        cpumask_t mask;
 
-       if (action == CPU_ONLINE) {
+       if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
                for_each_online_pgdat(pgdat) {
                        mask = node_to_cpumask(pgdat->node_id);
                        if (any_online_cpu(mask) != NR_CPUS)
index 6c488d6ac425d948b7b77d78a6cac899be16af6a..9832d9a41d8c721129a29f6b235b248b22de05dd 100644 (file)
@@ -281,6 +281,17 @@ EXPORT_SYMBOL(dec_zone_page_state);
 
 /*
  * Update the zone counters for one cpu.
+ *
+ * Note that refresh_cpu_vm_stats strives to only access
+ * node local memory. The per cpu pagesets on remote zones are placed
+ * in the memory local to the processor using that pageset. So the
+ * loop over all zones will access a series of cachelines local to
+ * the processor.
+ *
+ * The call to zone_page_state_add updates the cachelines with the
+ * statistics in the remote zone struct as well as the global cachelines
+ * with the global counters. These could cause remote node cache line
+ * bouncing and will have to be only done when necessary.
  */
 void refresh_cpu_vm_stats(int cpu)
 {
@@ -289,21 +300,54 @@ void refresh_cpu_vm_stats(int cpu)
        unsigned long flags;
 
        for_each_zone(zone) {
-               struct per_cpu_pageset *pcp;
+               struct per_cpu_pageset *p;
 
                if (!populated_zone(zone))
                        continue;
 
-               pcp = zone_pcp(zone, cpu);
+               p = zone_pcp(zone, cpu);
 
                for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
-                       if (pcp->vm_stat_diff[i]) {
+                       if (p->vm_stat_diff[i]) {
                                local_irq_save(flags);
-                               zone_page_state_add(pcp->vm_stat_diff[i],
+                               zone_page_state_add(p->vm_stat_diff[i],
                                        zone, i);
-                               pcp->vm_stat_diff[i] = 0;
+                               p->vm_stat_diff[i] = 0;
+#ifdef CONFIG_NUMA
+                               /* 3 seconds idle till flush */
+                               p->expire = 3;
+#endif
                                local_irq_restore(flags);
                        }
+#ifdef CONFIG_NUMA
+               /*
+                * Deal with draining the remote pageset of this
+                * processor
+                *
+                * Check if there are pages remaining in this pageset
+                * if not then there is nothing to expire.
+                */
+               if (!p->expire || (!p->pcp[0].count && !p->pcp[1].count))
+                       continue;
+
+               /*
+                * We never drain zones local to this processor.
+                */
+               if (zone_to_nid(zone) == numa_node_id()) {
+                       p->expire = 0;
+                       continue;
+               }
+
+               p->expire--;
+               if (p->expire)
+                       continue;
+
+               if (p->pcp[0].count)
+                       drain_zone_pages(zone, p->pcp + 0);
+
+               if (p->pcp[1].count)
+                       drain_zone_pages(zone, p->pcp + 1);
+#endif
        }
 }
 
@@ -640,6 +684,24 @@ const struct seq_operations vmstat_op = {
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
+int sysctl_stat_interval __read_mostly = HZ;
+
+static void vmstat_update(struct work_struct *w)
+{
+       refresh_cpu_vm_stats(smp_processor_id());
+       schedule_delayed_work(&__get_cpu_var(vmstat_work),
+               sysctl_stat_interval);
+}
+
+static void __devinit start_cpu_timer(int cpu)
+{
+       struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
+
+       INIT_DELAYED_WORK(vmstat_work, vmstat_update);
+       schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu);
+}
+
 /*
  * Use the cpu notifier to insure that the thresholds are recalculated
  * when necessary.
@@ -648,10 +710,24 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
                unsigned long action,
                void *hcpu)
 {
+       long cpu = (long)hcpu;
+
        switch (action) {
-       case CPU_UP_PREPARE:
-       case CPU_UP_CANCELED:
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               start_cpu_timer(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
+               cancel_rearming_delayed_work(&per_cpu(vmstat_work, cpu));
+               per_cpu(vmstat_work, cpu).work.func = NULL;
+               break;
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               start_cpu_timer(cpu);
+               break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                refresh_zone_stat_thresholds();
                break;
        default:
@@ -665,8 +741,13 @@ static struct notifier_block __cpuinitdata vmstat_notifier =
 
 int __init setup_vmstat(void)
 {
+       int cpu;
+
        refresh_zone_stat_thresholds();
        register_cpu_notifier(&vmstat_notifier);
+
+       for_each_online_cpu(cpu)
+               start_cpu_timer(cpu);
        return 0;
 }
 module_init(setup_vmstat)
index f6a92a0b7aa6b0400a8613c1d57569b8c9935587..fbdfb1224ae1a7a908a9e155564c7f56aa8a7df1 100644 (file)
@@ -1844,7 +1844,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
        .sendpage       = sock_no_sendpage,
 };
 
-#include <linux/smp_lock.h>
 SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);
 
 static struct notifier_block ddp_notifier = {
index 6ded95272a537636b0673b5ba040620d287e6049..429e13a6c6ad41ab7bab2b2d6e6bdde0d57aed1e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <net/ax25.h>
index ab2db55982ca3e4bb51c241ef7b3e6f1869ab0a8..1c8f4a0c5f4356dc9421bcc90dadc5efbc91c44c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/net.h>
 #include <net/sock.h>
 
index 359e3440cf292fff35b0a37938f19a1479a39ff6..25835403d6591551c953f1aa1c1331fec92ca9db 100644 (file)
@@ -322,7 +322,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
                if (device_create_file(dev, bt_attrs[i]) < 0)
                        BT_ERR("Failed to create device attribute");
 
-       if (sysfs_create_link(&bt_class->subsys.kset.kobj,
+       if (sysfs_create_link(&bt_class->subsys.kobj,
                                &dev->kobj, kobject_name(&dev->kobj)) < 0)
                BT_ERR("Failed to create class symlink");
 
@@ -333,7 +333,7 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
 {
        BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-       sysfs_remove_link(&bt_class->subsys.kset.kobj,
+       sysfs_remove_link(&bt_class->subsys.kobj,
                                        kobject_name(&hdev->dev.kobj));
 
        device_del(&hdev->dev);
index ebb0861e9bd573959eb2a4c1bdb7ef00cbcc3454..0e035d6162cc840e1e7a71592f79894e0cb5b316 100644 (file)
@@ -13,7 +13,6 @@
  *     2 of the License, or (at your option) any later version.
  */
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
index 3e246b37020eb2c32d7aa12d2c03ba5999177015..a786e786320096a786a19b578f39a42d944c16db 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 
index 030aa798fea70bd5b9ee4a6fc814529c569e460b..24e0ca4a3131948af3cf2d59c956ccf9f852fc96 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/kernel.h>
 #include <linux/times.h>
-#include <linux/smp_lock.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
index 4317c1be4d3ff658fa8f8eec221aa8b96f247aaf..8301e2ac747fcf7500a9c3e2999061033b686637 100644 (file)
@@ -3450,7 +3450,7 @@ static int dev_cpu_callback(struct notifier_block *nfb,
        unsigned int cpu, oldcpu = (unsigned long)ocpu;
        struct softnet_data *sd, *oldsd;
 
-       if (action != CPU_DEAD)
+       if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
                return NOTIFY_OK;
 
        local_irq_disable();
index 5d25697920b1ae183fe83e627044c601cb845632..051430545a05364bb9864df299c93130edaa626a 100644 (file)
@@ -338,7 +338,7 @@ static int flow_cache_cpu(struct notifier_block *nfb,
                          unsigned long action,
                          void *hcpu)
 {
-       if (action == CPU_DEAD)
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
                __flow_cache_shrink((unsigned long)hcpu, 0);
        return NOTIFY_OK;
 }
index b316435b0e2a5632446c70a23228e75c6294a6a5..758dafe284c026acc0bf180a260cd9fe7626b750 100644 (file)
@@ -9,7 +9,6 @@
  * Copyright (C) 2002  Red Hat, Inc.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/string.h>
index b92a322872a8caadbfb592f912393461397d94c8..9cd3a1cb60ef33b485075cb4ce49183d13f9c67b 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
index 9fbe87c938022b79c4f77f73d25cc328d051fbfe..bfa910b6ad25935af657beea80cadab38e843ee8 100644 (file)
@@ -1839,7 +1839,7 @@ static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *que
 }
 
 /*
- * The DECnet spec requires the the "routing layer" accepts packets which
+ * The DECnet spec requires that the "routing layer" accepts packets which
  * are at least 230 bytes in size. This excludes any headers which the NSP
  * layer might add, so we always assume that we'll be using the maximal
  * length header on data packets. The variation in length is due to the
index e62aee0ec4c588c9373ba484ca79beee2e20996e..c68196cc56abaea14b3922618fe67f7ca94f6b4f 100644 (file)
@@ -130,7 +130,7 @@ config IP_ROUTE_MULTIPATH_RR
        tristate "MULTIPATH: round robin algorithm"
        depends on IP_ROUTE_MULTIPATH_CACHED
        help
-         Mulitpath routes are chosen according to Round Robin
+         Multipath routes are chosen according to Round Robin
 
 config IP_ROUTE_MULTIPATH_RANDOM
        tristate "MULTIPATH: random algorithm"
@@ -651,7 +651,7 @@ config TCP_MD5SIG
        select CRYPTO
        select CRYPTO_MD5
        ---help---
-         RFC2385 specifices a method of giving MD5 protection to TCP sessions.
+         RFC2385 specifies a method of giving MD5 protection to TCP sessions.
          Its main (only?) use is to protect BGP sessions between core routers
          on the Internet.
 
index 16aae8ef5555b65855f5437a729c13134cf9739b..041fba3fa0aa312c3ff1e2de35b81bb8025d19aa 100644 (file)
@@ -92,7 +92,6 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/igmp.h>
 #include <linux/inetdevice.h>
index e1f18489db1d4f2cb36db0a20d774833f6573558..86a2b52aad3836c6aef2edf83413c3bda42a1319 100644 (file)
@@ -629,7 +629,7 @@ doi_walk_return:
  * @domain: the domain to add
  *
  * Description:
- * Adds the @domain to the the DOI specified by @doi_def, this function
+ * Adds the @domain to the DOI specified by @doi_def, this function
  * should only be called by external functions (i.e. NetLabel).  This function
  * does allocate memory.  Returns zero on success, negative values on failure.
  *
index b3050a6817e7af88ed58b7213ee342b4c6f9f1bd..68fe1d4d0210384d358947acbdd55ed17bdc4f8d 100644 (file)
@@ -2387,6 +2387,7 @@ void ip_vs_control_cleanup(void)
        EnterFunction(2);
        ip_vs_trash_cleanup();
        cancel_rearming_delayed_work(&defense_work);
+       cancel_work_sync(&defense_work.work);
        ip_vs_kill_estimator(&ip_vs_stats);
        unregister_sysctl_table(sysctl_header);
        proc_net_remove("ip_vs_stats");
index ff366f7390d9c7e15d4e5c42bafef20a3ccf40d0..dd7c128f9db33e48cc3cd4585a154c7dfa40f619 100644 (file)
@@ -18,7 +18,7 @@
  * The SED algorithm attempts to minimize each job's expected delay until
  * completion. The expected delay that the job will experience is
  * (Ci + 1) / Ui if sent to the ith server, in which Ci is the number of
- * jobs on the the ith server and Ui is the fixed service rate (weight) of
+ * jobs on the ith server and Ui is the fixed service rate (weight) of
  * the ith server. The SED algorithm adopts a greedy policy that each does
  * what is in its own best interest, i.e. to join the queue which would
  * minimize its expected delay of completion.
index 8b124eafbb90e15a53be727c8bfb3929c5d498ab..bd4c295f5d796347c2ba705710c417a50d6002fe 100644 (file)
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
index 0faacf9c419d5a888c8578d15e3f3c948edfb0b9..53232dd6fb48af5a9c4f5d2373a1630936bb7980 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <linux/compiler.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 
 /* People can turn this off for buggy TCP's found in printers etc. */
 int sysctl_tcp_retrans_collapse __read_mostly = 1;
index 113e0c4c8a928157d51f17abcd47804106ebdeca..66026df1cc7639bcba7f9b0232b8a4267107e7b4 100644 (file)
@@ -983,7 +983,7 @@ int udp_disconnect(struct sock *sk, int flags)
 }
 
 /* return:
- *     1  if the the UDP system should process it
+ *     1  if the UDP system should process it
  *     0  if we should drop this packet
  *     -1 if it should get processed by xfrm4_rcv_encap
  */
index 18cb928c8d92aaa79811083dbef10806fdce9ac3..6dd377253cf77dbc615d436ef123e7323d3ee1cc 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/inet.h>
 #include <linux/netdevice.h>
 #include <linux/icmpv6.h>
-#include <linux/smp_lock.h>
 #include <linux/netfilter_ipv6.h>
 
 #include <net/ip.h>
index bbe99f842f9f67e79e5e405abf60ed09a5c50c3f..838b8ddee8c03d6e40becb72ff15795cd2ab06ca 100644 (file)
@@ -28,7 +28,7 @@ config IP6_NF_QUEUE
          packets which enables users to receive the filtered packets
          with QUEUE target using libipq.
 
-         THis option enables the old IPv6-only "ip6_queue" implementation
+         This option enables the old IPv6-only "ip6_queue" implementation
          which has been obsoleted by the new "nfnetlink_queue" code (see
          CONFIG_NETFILTER_NETLINK_QUEUE).
 
index 392f8bc92691e2ed5ccd2cac0941a111aa9d2951..15419dd682fda75fbf46a07e9bf565598878c69f 100644 (file)
@@ -1961,7 +1961,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
        .sendpage       = sock_no_sendpage,
 };
 
-#include <linux/smp_lock.h>
 SOCKOPS_WRAP(ipx_dgram, PF_IPX);
 
 static struct packet_type ipx_8023_packet_type = {
index 06c97c60d54278404a7c62f69d3549f2f3be9350..dcd7e325b283cc66885aef639b92424df473769d 100644 (file)
@@ -2538,7 +2538,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
 };
 #endif /* CONFIG_IRDA_ULTRA */
 
-#include <linux/smp_lock.h>
 SOCKOPS_WRAP(irda_stream, PF_IRDA);
 SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
 SOCKOPS_WRAP(irda_dgram, PF_IRDA);
index fb3faf72e8508f73cea2e435182ea534f84a0ecc..b7333061016dfffbf8122460f63dda56e724a3c8 100644 (file)
@@ -556,6 +556,7 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
 
        switch (action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                if (!percpu_populate(iucv_irq_data,
                                     sizeof(struct iucv_irq_data),
                                     GFP_KERNEL|GFP_DMA, cpu))
@@ -567,15 +568,20 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
                }
                break;
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                percpu_depopulate(iucv_param, cpu);
                percpu_depopulate(iucv_irq_data, cpu);
                break;
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
        case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
                smp_call_function_on(iucv_declare_cpu, NULL, 0, 1, cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpumask = iucv_buffer_cpumask;
                cpu_clear(cpu, cpumask);
                if (cpus_empty(cpumask))
index 7d9fa38b6a7d14ca5a35d8c782d5b7e0f383a34a..6b8a103cf9e66f198984fed8656ddacf9781718a 100644 (file)
@@ -324,7 +324,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                memset(&laddr, 0, sizeof(laddr));
                memset(&daddr, 0, sizeof(daddr));
                /*
-                * FIXME: check if the the address is multicast,
+                * FIXME: check if the address is multicast,
                 *        only SOCK_DGRAM can do this.
                 */
                memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
index ea6211cade0acd2b464822eedec0ed819fc50583..a567dae8e5fdff5a3b0a80080f71d23fa0196236 100644 (file)
@@ -197,7 +197,7 @@ config NF_CONNTRACK_PPTP
 
          Please note that not all PPTP modes of operation are supported yet.
          Specifically these limitations exist:
-           - Blindy assumes that control connections are always established
+           - Blindly assumes that control connections are always established
              in PNS->PAC direction. This is a violation of RFC2637.
            - Only supports a single call within each session
 
index c31af29a4439f9266592abe0c162cf97fef291b7..117cbfdb910c57bf08b4f62e1a254cccb32df7c1 100644 (file)
@@ -177,7 +177,7 @@ void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
        struct nf_conntrack_expect *i;
 
        write_lock_bh(&nf_conntrack_lock);
-       /* choose the the oldest expectation to evict */
+       /* choose the oldest expectation to evict */
        list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
                if (expect_matches(i, exp) && del_timer(&i->timeout)) {
                        nf_ct_unlink_expect(i);
index 507828d7d4aeb807220462a4d494441388ac5624..1f15821c8da4c64894fd7e07d8340a8b8c430b4a 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/rtnetlink.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/security.h>
 #include <linux/jhash.h>
index 83ef411772f46f1494175d0320a0f4d43d134b46..77fb7b06a9c4eb62d2836b8b93fd779f6be4dfc0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * This file is part of the SCTP kernel reference Implementation
  *
- * This file contains the code relating the the chunk abstraction.
+ * This file contains the code relating the chunk abstraction.
  *
  * The SCTP reference implementation is free software;
  * you can redistribute it and/or modify it under the terms of
index 9f1a908776deac0a53be04e1b46aa1b87d59a98a..83a76ba9d7b3f2f5eadbe3c3214368e3e1641c70 100644 (file)
@@ -2586,7 +2586,7 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int opt
  *
  * 7.1.2 SCTP_ASSOCINFO
  *
- * This option is used to tune the the maximum retransmission attempts
+ * This option is used to tune the maximum retransmission attempts
  * of the association.
  * Returns an error if the new association retransmission value is
  * greater than the sum of the retransmission value  of the peer.
@@ -4547,7 +4547,7 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
  *
  * 7.1.2 SCTP_ASSOCINFO
  *
- * This option is used to tune the the maximum retransmission attempts
+ * This option is used to tune the maximum retransmission attempts
  * of the association.
  * Returns an error if the new association retransmission value is
  * greater than the sum of the retransmission value  of the peer.
index 759825b7ca263b4073d39338debc7a4a04a4a6a1..98a8f67abbfcfe84f2cb026737c710c39647d8cc 100644 (file)
@@ -313,8 +313,19 @@ static int sockfs_delete_dentry(struct dentry *dentry)
        dentry->d_flags |= DCACHE_UNHASHED;
        return 0;
 }
+
+/*
+ * sockfs_dname() is called from d_path().
+ */
+static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+       return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
+                               dentry->d_inode->i_ino);
+}
+
 static struct dentry_operations sockfs_dentry_operations = {
        .d_delete = sockfs_delete_dentry,
+       .d_dname  = sockfs_dname,
 };
 
 /*
@@ -354,14 +365,9 @@ static int sock_alloc_fd(struct file **filep)
 
 static int sock_attach_fd(struct socket *sock, struct file *file)
 {
-       struct qstr this;
-       char name[32];
-
-       this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
-       this.name = name;
-       this.hash = 0;
+       struct qstr name = { .name = "" };
 
-       file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+       file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
        if (unlikely(!file->f_path.dentry))
                return -ENOMEM;
 
index db298b501c817d1c0a90825aa526068293c59565..099a983797da329249942ccbbf279c92e8ac853b 100644 (file)
@@ -924,6 +924,7 @@ static inline int
 gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
 {
        struct rsc *rsci;
+       int        rc;
 
        if (rsip->major_status != GSS_S_COMPLETE)
                return gss_write_null_verf(rqstp);
@@ -932,7 +933,9 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
                rsip->major_status = GSS_S_NO_CONTEXT;
                return gss_write_null_verf(rqstp);
        }
-       return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+       rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+       cache_put(&rsci->h, &rsc_cache);
+       return rc;
 }
 
 /*
@@ -1089,6 +1092,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                }
                goto complete;
        case RPC_GSS_PROC_DESTROY:
+               if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
+                       goto auth_err;
                set_bit(CACHE_NEGATIVE, &rsci->h.flags);
                if (resv->iov_len + 4 > PAGE_SIZE)
                        goto drop;
@@ -1196,13 +1201,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
        if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset,
                                integ_len))
                BUG();
-       if (resbuf->page_len == 0
-                       && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
-                       < PAGE_SIZE) {
-               BUG_ON(resbuf->tail[0].iov_len);
-               /* Use head for everything */
-               resv = &resbuf->head[0];
-       } else if (resbuf->tail[0].iov_base == NULL) {
+       if (resbuf->tail[0].iov_base == NULL) {
                if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
                        goto out_err;
                resbuf->tail[0].iov_base = resbuf->head[0].iov_base
index ad39b47e05bcc6f2bfe027f5b6dc3164361a62f6..a2f1893bde53e41137a96b3cee5de618a629c2b9 100644 (file)
@@ -845,6 +845,8 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 
 int register_rpc_pipefs(void)
 {
+       int err;
+
        rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
                                sizeof(struct rpc_inode),
                                0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
@@ -852,7 +854,12 @@ int register_rpc_pipefs(void)
                                init_once, NULL);
        if (!rpc_inode_cachep)
                return -ENOMEM;
-       register_filesystem(&rpc_pipe_fs_type);
+       err = register_filesystem(&rpc_pipe_fs_type);
+       if (err) {
+               kmem_cache_destroy(rpc_inode_cachep);
+               return err;
+       }
+
        return 0;
 }
 
index 4a53e94f813415ac757f5180bf0d20a3323ba2d2..99014516b73c7855294df0788c88f3d954a7214f 100644 (file)
@@ -763,9 +763,9 @@ void *rpc_malloc(struct rpc_task *task, size_t size)
        else
                buf = kmalloc(size, gfp);
        *buf = size;
-       dprintk("RPC: %5u allocated buffer of size %u at %p\n",
+       dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
                        task->tk_pid, size, buf);
-       return (void *) ++buf;
+       return ++buf;
 }
 
 /**
@@ -775,14 +775,14 @@ void *rpc_malloc(struct rpc_task *task, size_t size)
  */
 void rpc_free(void *buffer)
 {
-       size_t size, *buf = (size_t *) buffer;
+       size_t size, *buf = buffer;
 
        if (!buffer)
                return;
        size = *buf;
        buf--;
 
-       dprintk("RPC:       freeing buffer of size %u at %p\n",
+       dprintk("RPC:       freeing buffer of size %zu at %p\n",
                        size, buf);
        if (size <= RPC_BUFFER_MAXSIZE)
                mempool_free(buf, rpc_buffer_mempool);
index 43ecf62f12ef2b6797631b420009198d1ce9d883..0d35bc796d0034bba98284c4d7fd75bf93e7153f 100644 (file)
@@ -146,9 +146,11 @@ init_sunrpc(void)
        int err = register_rpc_pipefs();
        if (err)
                goto out;
-       err = rpc_init_mempool() != 0;
-       if (err)
+       err = rpc_init_mempool();
+       if (err) {
+               unregister_rpc_pipefs();
                goto out;
+       }
 #ifdef RPC_DEBUG
        rpc_register_sysctl();
 #endif
index b7503c103ae814f012041a6f8f02e073c1d1ab26..e673ef9939043edc4a2d7aac1bf0c745ebd22917 100644 (file)
@@ -907,7 +907,7 @@ svc_process(struct svc_rqst *rqstp)
         * better idea of reply size
         */
        if (procp->pc_xdrressize)
-               svc_reserve(rqstp, procp->pc_xdrressize<<2);
+               svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
 
        /* Call the function that processes the request. */
        if (!versp->vs_dispatch) {
index f5c3808bf85ab7cf1d03edaf8c43bbebc5faa3cf..af7c5f05c6e11b3d5d734d1ee2143e54c71517bb 100644 (file)
@@ -64,7 +64,7 @@ int svc_set_client(struct svc_rqst *rqstp)
 }
 
 /* A request, which was authenticated, has now executed.
- * Time to finalise the the credentials and verifier
+ * Time to finalise the credentials and verifier
  * and release and resources
  */
 int svc_authorise(struct svc_rqst *rqstp)
index 2bd23ea2aa8b9cfefc3c771e8444d4dd4d33b8c5..07dcd20cbee4c366ee7ba8a0d19d7729b0b0b050 100644 (file)
@@ -385,7 +385,7 @@ ip_map_cached_get(struct svc_rqst *rqstp)
 {
        struct ip_map *ipm;
        struct svc_sock *svsk = rqstp->rq_sock;
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        ipm = svsk->sk_info_authunix;
        if (ipm != NULL) {
                if (!cache_valid(&ipm->h)) {
@@ -395,13 +395,13 @@ ip_map_cached_get(struct svc_rqst *rqstp)
                         * same IP address.
                         */
                        svsk->sk_info_authunix = NULL;
-                       spin_unlock_bh(&svsk->sk_defer_lock);
+                       spin_unlock(&svsk->sk_lock);
                        cache_put(&ipm->h, &ip_map_cache);
                        return NULL;
                }
                cache_get(&ipm->h);
        }
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        return ipm;
 }
 
@@ -410,14 +410,14 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
 {
        struct svc_sock *svsk = rqstp->rq_sock;
 
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        if (svsk->sk_sock->type == SOCK_STREAM &&
            svsk->sk_info_authunix == NULL) {
                /* newly cached, keep the reference */
                svsk->sk_info_authunix = ipm;
                ipm = NULL;
        }
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        if (ipm)
                cache_put(&ipm->h, &ip_map_cache);
 }
index 22f61aee4824cea33b419529f62bb5eee599f5fd..5baf48de25588f9e6610e1e1fdadeac4400636bd 100644 (file)
@@ -53,7 +53,8 @@
  *     svc_serv->sv_lock protects sv_tempsocks, sv_permsocks, sv_tmpcnt.
  *     when both need to be taken (rare), svc_serv->sv_lock is first.
  *     BKL protects svc_serv->sv_nrthread.
- *     svc_sock->sk_defer_lock protects the svc_sock->sk_deferred list
+ *     svc_sock->sk_lock protects the svc_sock->sk_deferred list
+ *             and the ->sk_info_authunix cache.
  *     svc_sock->sk_flags.SK_BUSY prevents a svc_sock being enqueued multiply.
  *
  *     Some flags can be set to certain values at any time
@@ -787,15 +788,20 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        }
 
        clear_bit(SK_DATA, &svsk->sk_flags);
-       while ((err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
-                                    0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 ||
-              (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
-               if (err == -EAGAIN) {
-                       svc_sock_received(svsk);
-                       return err;
+       skb = NULL;
+       err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
+                            0, 0, MSG_PEEK | MSG_DONTWAIT);
+       if (err >= 0)
+               skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err);
+
+       if (skb == NULL) {
+               if (err != -EAGAIN) {
+                       /* possibly an icmp error */
+                       dprintk("svc: recvfrom returned error %d\n", -err);
+                       set_bit(SK_DATA, &svsk->sk_flags);
                }
-               /* possibly an icmp error */
-               dprintk("svc: recvfrom returned error %d\n", -err);
+               svc_sock_received(svsk);
+               return -EAGAIN;
        }
        rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
        if (skb->tstamp.tv64 == 0) {
@@ -1633,7 +1639,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        svsk->sk_server = serv;
        atomic_set(&svsk->sk_inuse, 1);
        svsk->sk_lastrecv = get_seconds();
-       spin_lock_init(&svsk->sk_defer_lock);
+       spin_lock_init(&svsk->sk_lock);
        INIT_LIST_HEAD(&svsk->sk_deferred);
        INIT_LIST_HEAD(&svsk->sk_ready);
        mutex_init(&svsk->sk_mutex);
@@ -1857,9 +1863,9 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
        dprintk("revisit queued\n");
        svsk = dr->svsk;
        dr->svsk = NULL;
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        list_add(&dr->handle.recent, &svsk->sk_deferred);
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        set_bit(SK_DEFERRED, &svsk->sk_flags);
        svc_sock_enqueue(svsk);
        svc_sock_put(svsk);
@@ -1925,7 +1931,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
 
        if (!test_bit(SK_DEFERRED, &svsk->sk_flags))
                return NULL;
-       spin_lock_bh(&svsk->sk_defer_lock);
+       spin_lock(&svsk->sk_lock);
        clear_bit(SK_DEFERRED, &svsk->sk_flags);
        if (!list_empty(&svsk->sk_deferred)) {
                dr = list_entry(svsk->sk_deferred.next,
@@ -1934,6 +1940,6 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
                list_del_init(&dr->handle.recent);
                set_bit(SK_DEFERRED, &svsk->sk_flags);
        }
-       spin_unlock_bh(&svsk->sk_defer_lock);
+       spin_unlock(&svsk->sk_lock);
        return dr;
 }
index aec8cf165e1a5d774d5136ab91c30c8f45842a1a..fc12ba51c1fc8223672c744e2c3eb06239741303 100644 (file)
 #include <net/scm.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/rtnetlink.h>
 #include <linux/mount.h>
 #include <net/checksum.h>
index 0d6002fc77b26108973c0e270263ec389db0690e..479927cb45cacd3c8f3f797a916bb51edf0cbbfc 100644 (file)
@@ -1605,7 +1605,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
        .sendpage =     sock_no_sendpage,
 };
 
-#include <linux/smp_lock.h>
 SOCKOPS_WRAP(x25_proto, AF_X25);
 
 static struct packet_type x25_packet_type = {
index d6071cbf13d7645ee53f96089bb8c12af04fcb8b..f4d2f68452baa8860769b7ac9cecac75747d6118 100644 (file)
@@ -211,7 +211,7 @@ void find_export_symbols(char * filename)
  * Document all external or internal functions in a file.
  * Call kernel-doc with following parameters:
  * kernel-doc -docbook -nofunction function_name1 filename
- * function names are obtained from all the the src files
+ * function names are obtained from all the src files
  * by find_export_symbols.
  * intfunc uses -nofunction
  * extfunc uses -function
index 8be269ffbf9d4f8159ca7a49a589f879a3d38583..e5bf649e516a1d38bb9cc0ebf226b989246d09ac 100755 (executable)
@@ -159,7 +159,8 @@ my $warnings = 0;
 my $type_constant = '\%([-_\w]+)';
 my $type_func = '(\w+)\(\)';
 my $type_param = '\@(\w+)';
-my $type_struct = '\&((struct\s*)?[_\w]+)';
+my $type_struct = '\&((struct\s*)*[_\w]+)';
+my $type_struct_xml = '\\\amp;((struct\s*)*[_\w]+)';
 my $type_env = '(\$\w+)';
 
 # Output conversion substitutions.
@@ -168,7 +169,8 @@ my $type_env = '(\$\w+)';
 # these work fairly well
 my %highlights_html = ( $type_constant, "<i>\$1</i>",
                        $type_func, "<b>\$1</b>",
-                       $type_struct, "<i>\$1</i>",
+                       $type_struct_xml, "<i>\$1</i>",
+                       $type_env, "<b><i>\$1</i></b>",
                        $type_param, "<tt><b>\$1</b></tt>" );
 my $blankline_html = "<p>";
 
@@ -326,12 +328,22 @@ while ($ARGV[0] =~ m/^-(.*)/) {
     }
 }
 
+# get kernel version from env
+sub get_kernel_version() {
+    my $version;
+
+    if (defined($ENV{'KERNELVERSION'})) {
+       $version = $ENV{'KERNELVERSION'};
+    }
+    return $version;
+}
+my $kernelversion = get_kernel_version();
 
 # generate a sequence of code that will splice in highlighting information
 # using the s// operator.
 my $dohighlight = "";
 foreach my $pattern (keys %highlights) {
-#    print "scanning pattern $pattern ($highlights{$pattern})\n";
+#   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
 }
 
@@ -378,13 +390,19 @@ sub output_highlight {
 #      confess "output_highlight got called with no args?\n";
 #   }
 
+#   print STDERR "contents b4:$contents\n";
     eval $dohighlight;
     die $@ if $@;
+    if ($output_mode eq "html") {
+       $contents =~ s/\\\\//;
+    }
+#   print STDERR "contents af:$contents\n";
+
     foreach $line (split "\n", $contents) {
-      if ($line eq ""){
+       if ($line eq ""){
            print $lineprefix, $blankline;
        } else {
-            $line =~ s/\\\\\\/\&/g;
+           $line =~ s/\\\\\\/\&/g;
            print $lineprefix, $line;
        }
        print "\n";
@@ -414,7 +432,7 @@ sub output_enum_html(%) {
     print "<b>enum ".$args{'enum'}."</b> {<br>\n";
     $count = 0;
     foreach $parameter (@{$args{'parameterlist'}}) {
-        print " <b>".$parameter."</b>";
+       print " <b>".$parameter."</b>";
        if ($count != $#{$args{'parameterlist'}}) {
            $count++;
            print ",\n";
@@ -462,15 +480,16 @@ sub output_struct_html(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
-           print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
+           print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
-           print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
+           # bitfield
+           print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
        } else {
-           print " <i>$type</i> <b>$parameter</b>;<br>\n";
+           print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
        }
     }
     print "};<br>\n";
@@ -483,7 +502,7 @@ sub output_struct_html(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print "<dt><b>".$parameter."</b>\n";
        print "<dd>";
        output_highlight($args{'parameterdescs'}{$parameter_name});
@@ -525,7 +544,7 @@ sub output_function_html(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print "<dt><b>".$parameter."</b>\n";
        print "<dd>";
        output_highlight($args{'parameterdescs'}{$parameter_name});
@@ -592,6 +611,7 @@ sub output_function_xml(%) {
     print "<refmeta>\n";
     print " <refentrytitle><phrase>".$args{'function'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
+    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'function'}."</refname>\n";
@@ -668,6 +688,7 @@ sub output_struct_xml(%) {
     print "<refmeta>\n";
     print " <refentrytitle><phrase>".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
+    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
@@ -691,7 +712,7 @@ sub output_struct_xml(%) {
        $parameter_name =~ s/\[.*//;
 
        defined($args{'parameterdescs'}{$parameter_name}) || next;
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
@@ -752,6 +773,7 @@ sub output_enum_xml(%) {
     print "<refmeta>\n";
     print " <refentrytitle><phrase>enum ".$args{'enum'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
+    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>enum ".$args{'enum'}."</refname>\n";
@@ -767,11 +789,11 @@ sub output_enum_xml(%) {
     print "enum ".$args{'enum'}." {\n";
     $count = 0;
     foreach $parameter (@{$args{'parameterlist'}}) {
-        print "  $parameter";
-        if ($count != $#{$args{'parameterlist'}}) {
+       print "  $parameter";
+       if ($count != $#{$args{'parameterlist'}}) {
            $count++;
            print ",";
-        }
+       }
        print "\n";
     }
     print "};";
@@ -1007,7 +1029,7 @@ sub output_enum_man(%) {
     print "enum ".$args{'enum'}." {\n";
     $count = 0;
     foreach my $parameter (@{$args{'parameterlist'}}) {
-        print ".br\n.BI \"    $parameter\"\n";
+       print ".br\n.BI \"    $parameter\"\n";
        if ($count == $#{$args{'parameterlist'}}) {
            print "\n};\n";
            last;
@@ -1054,7 +1076,7 @@ sub output_struct_man(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
@@ -1077,7 +1099,7 @@ sub output_struct_man(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print ".IP \"".$parameter."\" 12\n";
        output_highlight($args{'parameterdescs'}{$parameter_name});
     }
@@ -1187,7 +1209,7 @@ sub output_enum_text(%) {
     print "enum ".$args{'enum'}." {\n";
     $count = 0;
     foreach $parameter (@{$args{'parameterlist'}}) {
-        print "\t$parameter";
+       print "\t$parameter";
        if ($count != $#{$args{'parameterlist'}}) {
            $count++;
            print ",";
@@ -1232,7 +1254,7 @@ sub output_struct_text(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
@@ -1252,7 +1274,7 @@ sub output_struct_text(%) {
        my $parameter_name = $parameter;
        $parameter_name =~ s/\[.*//;
 
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print "$parameter\n\t";
        print $args{'parameterdescs'}{$parameter_name}."\n";
     }
@@ -1284,7 +1306,7 @@ sub output_declaration {
        ( $function_only == 1 && defined($function_table{$name})) ||
        ( $function_only == 2 && !defined($function_table{$name})))
     {
-        &$func(@_);
+       &$func(@_);
        $section_counter++;
     }
 }
@@ -1317,8 +1339,8 @@ sub dump_struct($$) {
     my $file = shift;
 
     if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
-        $declaration_name = $2;
-        my $members = $3;
+       $declaration_name = $2;
+       my $members = $3;
 
        # ignore embedded structs or unions
        $members =~ s/{.*?}//g;
@@ -1345,7 +1367,7 @@ sub dump_struct($$) {
                           });
     }
     else {
-        print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
+       print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
        ++$errors;
     }
 }
@@ -1356,15 +1378,15 @@ sub dump_enum($$) {
 
     $x =~ s@/\*.*?\*/@@gos;    # strip comments.
     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
-        $declaration_name = $1;
-        my $members = $2;
+       $declaration_name = $1;
+       my $members = $2;
 
        foreach my $arg (split ',', $members) {
            $arg =~ s/^\s*(\w+).*/$1/;
            push @parameterlist, $arg;
            if (!$parameterdescs{$arg}) {
-               $parameterdescs{$arg} = $undescribed;
-               print STDERR "Warning(${file}:$.): Enum value '$arg' ".
+               $parameterdescs{$arg} = $undescribed;
+               print STDERR "Warning(${file}:$.): Enum value '$arg' ".
                    "not described in enum '$declaration_name'\n";
            }
 
@@ -1382,7 +1404,7 @@ sub dump_enum($$) {
                           });
     }
     else {
-        print STDERR "Error(${file}:$.): Cannot parse enum!\n";
+       print STDERR "Error(${file}:$.): Cannot parse enum!\n";
        ++$errors;
     }
 }
@@ -1393,12 +1415,12 @@ sub dump_typedef($$) {
 
     $x =~ s@/\*.*?\*/@@gos;    # strip comments.
     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
-        $x =~ s/\(*.\)\s*;$/;/;
+       $x =~ s/\(*.\)\s*;$/;/;
        $x =~ s/\[*.\]\s*;$/;/;
     }
 
     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
-        $declaration_name = $1;
+       $declaration_name = $1;
 
        output_declaration($declaration_name,
                           'typedef',
@@ -1410,7 +1432,7 @@ sub dump_typedef($$) {
                           });
     }
     else {
-        print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
+       print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
        ++$errors;
     }
 }
@@ -1424,14 +1446,14 @@ sub create_parameterlist($$$) {
 
     # temporarily replace commas inside function pointer definition
     while ($args =~ /(\([^\),]+),/) {
-        $args =~ s/(\([^\),]+),/$1#/g;
+       $args =~ s/(\([^\),]+),/$1#/g;
     }
 
     foreach my $arg (split($splitter, $args)) {
        # strip comments
        $arg =~ s/\/\*.*\*\///;
-        # strip leading/trailing spaces
-        $arg =~ s/^\s*//;
+       # strip leading/trailing spaces
+       $arg =~ s/^\s*//;
        $arg =~ s/\s*$//;
        $arg =~ s/\s+/ /;
 
@@ -1456,7 +1478,16 @@ sub create_parameterlist($$$) {
            if ($args[0] =~ m/\*/) {
                $args[0] =~ s/(\*+)\s*/ $1/;
            }
-           my @first_arg = split('\s+', shift @args);
+
+           my @first_arg;
+           if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
+                   shift @args;
+                   push(@first_arg, split('\s+', $1));
+                   push(@first_arg, $2);
+           } else {
+                   @first_arg = split('\s+', shift @args);
+           }
+
            unshift(@args, pop @first_arg);
            $type = join " ", @first_arg;
 
@@ -1514,15 +1545,15 @@ sub push_parameter($$$) {
            $parameterdescs{$param_name} = $undescribed;
 
            if (($type eq 'function') || ($type eq 'enum')) {
-               print STDERR "Warning(${file}:$.): Function parameter ".
+               print STDERR "Warning(${file}:$.): Function parameter ".
                    "or member '$param' not " .
                    "described in '$declaration_name'\n";
            }
            print STDERR "Warning(${file}:$.):".
-                        " No description found for parameter '$param'\n";
+                        " No description found for parameter '$param'\n";
            ++$warnings;
-        }
-        }
+       }
+       }
 
        push @parameterlist, $param;
        $parametertypes{$param} = $type;
@@ -1664,10 +1695,10 @@ sub process_state3_function($$) {
        # do nothing
     }
     elsif ($x =~ /([^\{]*)/) {
-        $prototype .= $1;
+       $prototype .= $1;
     }
     if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {
-        $prototype =~ s@/\*.*?\*/@@gos;        # strip comments.
+       $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
        $prototype =~ s@^\s+@@gos; # strip leading spaces
        dump_function($prototype,$file);
@@ -1688,17 +1719,17 @@ sub process_state3_type($$) {
     }
 
     while (1) {
-        if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
+       if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
            $prototype .= $1 . $2;
            ($2 eq '{') && $brcount++;
            ($2 eq '}') && $brcount--;
            if (($2 eq ';') && ($brcount == 0)) {
-               dump_declaration($prototype,$file);
+               dump_declaration($prototype,$file);
                reset_state();
-               last;
+               last;
            }
            $x = $3;
-        } else {
+       } else {
            $prototype .= $x;
            last;
        }
@@ -1756,7 +1787,7 @@ sub process_file($) {
                } else {
                        $section = $1;
                }
-            }
+           }
            elsif (/$doc_decl/o) {
                $identifier = $1;
                if (/\s*([\w\s]+?)\s*-/) {
@@ -1849,13 +1880,13 @@ sub process_file($) {
            }
        } elsif ($state == 3) { # scanning for function '{' (end of prototype)
            if ($decl_type eq 'function') {
-               process_state3_function($_, $file);
+               process_state3_function($_, $file);
            } else {
-               process_state3_type($_, $file);
+               process_state3_type($_, $file);
            }
        } elsif ($state == 4) {
                # Documentation block
-               if (/$doc_block/) {
+               if (/$doc_block/) {
                        dump_section($section, $contents);
                        output_intro({'sectionlist' => \@sectionlist,
                                      'sections' => \%sections });
@@ -1873,7 +1904,7 @@ sub process_file($) {
                        } else {
                                $section = $1;
                        }
-                }
+               }
                elsif (/$doc_end/)
                {
                        dump_section($section, $contents);
@@ -1900,8 +1931,8 @@ sub process_file($) {
                        {
                                $contents .= $1 . "\n";
                        }
-               }
-          }
+               }
+       }
     }
     if ($initial_section_counter == $section_counter) {
        print STDERR "Warning(${file}): no structured comments found\n";
index 4ab36de45aa25ad0bec4c7ecf032ceb82889ce27..113dc77b9f60f9e147239bc3daff8bc92164c80c 100644 (file)
@@ -642,6 +642,16 @@ static int strrcmp(const char *s, const char *sub)
  *  tosec   = .init.text
  *  fromsec  = .paravirtprobe
  *
+ * Pattern 9:
+ *  Some of functions are common code between boot time and hotplug
+ *  time. The bootmem allocater is called only boot time in its
+ *  functions. So it's ok to reference.
+ *  tosec    = .init.text
+ *
+ * Pattern 10:
+ *  ia64 has machvec table for each platform. It is mixture of function
+ *  pointer of .init.text and .text.
+ *  fromsec  = .machvec
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
                            const char *fromsec, const char *atsym,
@@ -668,6 +678,12 @@ static int secref_whitelist(const char *modname, const char *tosec,
                NULL
        };
 
+       const char *pat4sym[] = {
+               "sparse_index_alloc",
+               "zone_wait_table_init",
+               NULL
+       };
+
        /* Check for pattern 1 */
        if (strcmp(tosec, ".init.data") != 0)
                f1 = 0;
@@ -726,6 +742,17 @@ static int secref_whitelist(const char *modname, const char *tosec,
            (strcmp(fromsec, ".paravirtprobe") == 0))
                return 1;
 
+       /* Check for pattern 9 */
+       if ((strcmp(tosec, ".init.text") == 0) &&
+           (strcmp(fromsec, ".text") == 0))
+               for (s = pat4sym; *s; s++)
+                       if (strcmp(atsym, *s) == 0)
+                               return 1;
+
+       /* Check for pattern 10 */
+       if (strcmp(fromsec, ".machvec") == 0)
+               return 1;
+
        return 0;
 }
 
@@ -1316,6 +1343,7 @@ static void add_header(struct buffer *b, struct module *mod)
                buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
                              " .exit = cleanup_module,\n"
                              "#endif\n");
+       buf_printf(b, " .arch = MODULE_ARCH_INIT,\n");
        buf_printf(b, "};\n");
 }
 
index b868e7eda5f06fafa49ed73c21cf1d5332a77e40..38296a0054653f9180bd554f167e077bb311a35a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
-#include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/ptrace.h>
index 5a5ef5ca7ea97eb9a2ef3901e3faff71fcaefcc6..384379ede4fd7c0f0e1a5c78c4ee9c70ce9f5cbb 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
-#include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/ptrace.h>
index 23b51047494ef0bd9673911979a049c7295d0b44..b32a459c0683c720271b6ab15d0829b11ef3e125 100644 (file)
@@ -137,7 +137,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
 
          Examples:
          For the Fedora Core 3 or 4 Linux distributions, enable this option
-         and set the value via the next option. For Fedore Core 5 and later,
+         and set the value via the next option. For Fedora Core 5 and later,
          do not enable this option.
 
          If you are unsure how to answer this question, answer N.
index 885a9a958b8d6181db6e207f31ce1e927ab9bc83..ad8dd4e8657e5487bd7668328238c166248176da 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/file.h>
@@ -1758,12 +1757,11 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                        }
                }
                file_list_unlock();
-
-               /* Reset controlling tty. */
-               if (drop_tty)
-                       proc_set_tty(current, NULL);
        }
        mutex_unlock(&tty_mutex);
+       /* Reset controlling tty. */
+       if (drop_tty)
+               no_tty();
 
        /* Revalidate access to inherited open files. */
 
index 7f980be5d0606d0f9783412301b9986164c6f808..e91f9f66f3957f3689aba3ae1e8c31a511ad20f9 100644 (file)
@@ -1061,7 +1061,7 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
        busnode = pmac_i2c_get_bus_node(bus);
 
        while ((dev = of_get_next_child(busnode, dev)) != NULL) {
-               if (device_is_compatible(dev, "pcm3052")) {
+               if (of_device_is_compatible(dev, "pcm3052")) {
                        const u32 *addr;
                        printk(KERN_DEBUG PFX "found pcm3052\n");
                        addr = of_get_property(dev, "reg", NULL);
@@ -1074,7 +1074,7 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
        /* if that didn't work, try desperate mode for older
         * machines that have stuff missing from the device tree */
        
-       if (!device_is_compatible(busnode, "k2-i2c"))
+       if (!of_device_is_compatible(busnode, "k2-i2c"))
                return -ENODEV;
 
        printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
index ceca38486eae7d4a54797f981ff383e150e6a27b..041fe52cbf2987ce6dfcc2daff3def22bd044c6b 100644 (file)
@@ -938,7 +938,7 @@ static int tas_i2c_attach(struct i2c_adapter *adapter)
        busnode = pmac_i2c_get_bus_node(bus);
 
        while ((dev = of_get_next_child(busnode, dev)) != NULL) {
-               if (device_is_compatible(dev, "tas3004")) {
+               if (of_device_is_compatible(dev, "tas3004")) {
                        const u32 *addr;
                        printk(KERN_DEBUG PFX "found tas3004\n");
                        addr = of_get_property(dev, "reg", NULL);
index 79fc4bc09e5e0e8de5a5b73f068324e4de6cd109..0fccdbf5166341d78ad0064a4268d38f9c6e6a02 100644 (file)
@@ -336,8 +336,8 @@ static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
        }
 
        while ((np = of_get_next_child(dev->ofdev.node, np))) {
-               if (device_is_compatible(np, "i2sbus") ||
-                   device_is_compatible(np, "i2s-modem")) {
+               if (of_device_is_compatible(np, "i2sbus") ||
+                   of_device_is_compatible(np, "i2s-modem")) {
                        got += i2sbus_add_dev(dev, control, np);
                }
        }
index b2927523d79df9c7ad796049ebb8145fb537ac57..829ca38b595e82d63eabb932506fb126eff723bf 100644 (file)
@@ -146,7 +146,7 @@ config SND_VERBOSE_PROCFS
        default y
        help
          Say Y here to include code for verbose procfs contents (provides
-          usefull information to developers when a problem occurs). On the
+          useful information to developers when a problem occurs).  On the
           other side, it makes the ALSA subsystem larger.
 
 config SND_VERBOSE_PRINTK
index 86de7258b76d04a0695251e94ecfcbc2e63c10a4..1f1ab9c1b668c5704badb84379f809439b085c09 100644 (file)
@@ -22,7 +22,6 @@
 #include <sound/driver.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/time.h>
index 96ffdf18c3fef89e7aa6e39d303a6a678df932ba..51ad95b7c894e9d6d1b12a3c5b748cd4978347ff 100644 (file)
@@ -22,7 +22,6 @@
 #include <sound/driver.h>
 #include <linux/major.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
index 74a2923eb40155708d5f97543e3fc3e3f0e65926..fccad8f0a6bb1de4d9b528a88934d7778e9c1042 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/string.h>
index c4744bb07f4119c2ee930953fd9049b7daa9e210..fc11572c48cf8038b52d329f9aa12d7ec047f9ca 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
index 3e276fcf3336eec5f0234de0750f83d54404b0a4..905234817c891d8c2cb0f2446416386aafac1fcc 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <sound/driver.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
index d14dcbb6dbca70a6789b0b56144cd1d99f85f361..e470c3c7d61162011b5dde5ff31c13f825e3a010 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/core.h>
 #include <linux/major.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/time.h>
index 2eb987308b539af5f321c9ea0c7264ca24a56a33..bc0992398461bbf40d0cf3da9f8d99f4feabb27f 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <sound/core.h>
index 694efe832b6787f9aa683635c42a00346d626aab..b31b5282a2c84637b48224c6911f2822ee423717 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/minors.h>
index 160e40ede72316a68bc13e47ee4d9bd25bf2be94..67520b3c0042d6f08178a8ed9c9d4fdfb5f25289 100644 (file)
@@ -22,7 +22,6 @@
 #include <sound/driver.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
index 4c419300305d34de140cd9c5c87399906883a3a4..4b30ae6d8ba511e4694c03d7322b05ad75a723d2 100644 (file)
@@ -5,23 +5,22 @@
 #
 # Prompt user for primary drivers.
 
-config OBSOLETE_OSS
+config OSS_OBSOLETE
        bool "Obsolete OSS drivers"
        depends on SOUND_PRIME
        help
          This option enables support for obsolete OSS drivers that
-         are scheduled for removal in the near future since there
-         are ALSA drivers for the same hardware.
+         are scheduled for removal in the near future.
 
          Please contact Adrian Bunk <bunk@stusta.de> if you had to
-         say Y here because your soundcard is not properly supported
+         say Y here because your hardware is not properly supported
          by ALSA.
 
          If unsure, say N.
 
 config SOUND_BT878
        tristate "BT878 audio dma"
-       depends on SOUND_PRIME && PCI
+       depends on SOUND_PRIME && PCI && OSS_OBSOLETE
        ---help---
          Audio DMA support for bt878 based grabber boards.  As you might have
          already noticed, bt878 is listed with two functions in /proc/pci.
@@ -45,22 +44,9 @@ config SOUND_BCM_CS4297A
          note that CONFIG_KGDB should not be enabled at the same
          time, since it also attempts to use this UART port.
 
-config SOUND_ES1371
-       tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS
-       help
-         Say Y or M if you have a PCI sound card utilizing the Ensoniq
-         ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
-         your sound card uses an ES1371 without removing your computer's
-         cover, use lspci -n and look for the PCI ID 1274:1371. Since
-         Ensoniq was bought by Creative Labs, Sound Blaster 64/PCI
-         models are either ES1370 or ES1371 based. This driver differs
-         slightly from OSS/Free, so PLEASE READ
-         <file:Documentation/sound/oss/es1371>.
-
 config SOUND_ICH
        tristate "Intel ICH (i8xx) audio support"
-       depends on SOUND_PRIME && PCI
+       depends on SOUND_PRIME && PCI && OSS_OBSOLETE
        help
          Support for integral audio in Intel's I/O Controller Hub (ICH)
          chipset, as used on the 810/820/840 motherboards.
@@ -362,7 +348,7 @@ config MSND_FIFOSIZE
 
 config SOUND_VIA82CXXX
        tristate "VIA 82C686 Audio Codec"
-       depends on SOUND_PRIME && PCI
+       depends on SOUND_PRIME && PCI && OSS_OBSOLETE
        help
          Say Y here to include support for the audio codec found on VIA
          82Cxxx-based chips. Typically these are built into a motherboard.
@@ -416,7 +402,7 @@ config SOUND_DMAP
 
 config SOUND_CS4232
        tristate "Crystal CS4232 based (PnP) cards"
-       depends on SOUND_OSS
+       depends on SOUND_OSS && OSS_OBSOLETE
        help
          Say Y here if you have a card based on the Crystal CS4232 chip set,
          which uses its own Plug and Play protocol.
@@ -735,7 +721,7 @@ config SOUND_WAVEARTIST
 
 config SOUND_TVMIXER
        tristate "TV card (bt848) mixer support"
-       depends on SOUND_PRIME && I2C && VIDEO_V4L1
+       depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE
        help
          Support for audio mixer facilities on the BT848 TV frame-grabber
          card.
index f813ae9c2134e2e7b17f41c486bf23c7d167a543..4d5cf05b8922605421a09a9716c957782c771635 100644 (file)
@@ -344,7 +344,7 @@ static int btaudio_mixer_ioctl(struct inode *inode, struct file *file,
        if (cmd == SOUND_OLD_MIXER_INFO) {
                _old_mixer_info info;
                memset(&info,0,sizeof(info));
-                strlcpy(info.id,"bt878",sizeof(info.id)-1);
+                strlcpy(info.id, "bt878", sizeof(info.id));
                 strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
                 if (copy_to_user(argp, &info, sizeof(info)))
                         return -EFAULT;
index 18e149f52a8869b6b2b22600afe17ddb194e89e7..71b313479f8331c8ce8e0b0c3e91f19a7699bdaf 100644 (file)
@@ -12,20 +12,6 @@ config DMASOUND_ATARI
          want). If you want to compile it as a module, say M here and read
          <file:Documentation/kbuild/modules.txt>.
 
-config DMASOUND_PMAC
-       tristate "PowerMac DMA sound support"
-       depends on PPC32 && PPC_PMAC && SOUND && I2C && OBSOLETE_OSS
-       select DMASOUND
-       help
-         If you want to use the internal audio of your PowerMac in Linux,
-         answer Y to this question. This will provide a Sun-like /dev/audio,
-         compatible with the Linux/i386 sound system. Otherwise, say N.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you
-         want). If you want to compile it as a module, say M here and read
-         <file:Documentation/kbuild/modules.txt>.
-
 config DMASOUND_PAULA
        tristate "Amiga DMA sound support"
        depends on (AMIGA || APUS) && SOUND
index 730fa1d001a5c7b366ef6814475f833319f93a9d..8f6388004f44d9af58e2be80e2e15ea2f036ea89 100644 (file)
@@ -362,7 +362,7 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int*
                                of_get_property(np,"audio-gpio",NULL);
                        if (property != 0 && strcmp(property,name) == 0)
                                break;
-               } else if (compatible && device_is_compatible(np, compatible))
+               } else if (compatible && of_device_is_compatible(np, compatible))
                        break;
                np = of_get_next_child(gpiop, np);
        }
@@ -2620,17 +2620,17 @@ get_codec_type(struct device_node *info)
 
        if (info) {
                /* must do awacs first to allow screamer to overide it */
-               if (device_is_compatible(info, "awacs"))
+               if (of_device_is_compatible(info, "awacs"))
                        codec = AWACS_AWACS ;
-               if (device_is_compatible(info, "screamer"))
+               if (of_device_is_compatible(info, "screamer"))
                        codec = AWACS_SCREAMER;
-               if (device_is_compatible(info, "burgundy"))
+               if (of_device_is_compatible(info, "burgundy"))
                        codec = AWACS_BURGUNDY ;
-               if (device_is_compatible(info, "daca"))
+               if (of_device_is_compatible(info, "daca"))
                        codec = AWACS_DACA;
-               if (device_is_compatible(info, "tumbler"))
+               if (of_device_is_compatible(info, "tumbler"))
                        codec = AWACS_TUMBLER;
-               if (device_is_compatible(info, "snapper"))
+               if (of_device_is_compatible(info, "snapper"))
                        codec = AWACS_SNAPPER;
        }
        return codec ;
@@ -2772,7 +2772,7 @@ set_hw_byteswap(struct device_node *io)
 
        for (mio = io->parent; mio ; mio = mio->parent) {
                if (strcmp(mio->name, "mac-io") == 0) {
-                       if (device_is_compatible(mio, "Keylargo"))
+                       if (of_device_is_compatible(mio, "Keylargo"))
                                kl = 1;
                        break;
                }
index 974dd732b1499606c37d6b324e6b932a4dddab14..593a3aac12ce50da78354877942c27b0c8053254 100644 (file)
  *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  *    05.01.2001   0.29  Hopefully updates will not be required anymore when Creative bumps
  *                       the CT5880 revision.
- *                       suggested by Stephan Müller <smueller@chronox.de>
+ *                       suggested by Stephan Müller <smueller@chronox.de>
  *    31.01.2001   0.30  Register/Unregister gameport
  *                       Fix SETTRIGGER non OSS API conformity
  *    14.07.2001   0.31  Add list of laptops needing amplifier control
index 4af6aafa3d862304d85ab611d16ad71a032c593e..36c3ea62086be882dbba7d630643b2f6ea110978 100644 (file)
@@ -85,7 +85,7 @@ static int pcm_set_speed(int arg)
         * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
         *
         * I cleared bit 5 of these values, since that bit controls the master
-        * mute flag. (Olav Wölfelschneider)
+        * mute flag. (Olav Wölfelschneider)
         *
         */
 #if !defined NO_AUTO_FILTER_SET
index 016b918329ada95227ddb95666fdd6ccc7615531..a8057f25955319d089badd9515553b62497f82a1 100644 (file)
@@ -75,7 +75,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/kernel.h>
 
index 72a8a0ed36a2855cca84d0d64a1c3844a96ab344..3bc1f6e9e4a3b35b8a1f9ac170d743f916ec54d6 100644 (file)
@@ -18,7 +18,7 @@
  *     Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
  *     Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support 
  *     Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
- *     Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
+ *     Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
  *      Muli Ben-Yehuda <mulix@mulix.org>
  *
  *
@@ -89,7 +89,7 @@
  *     use set_current_state, properly release resources on failure in
  *     trident_probe, get rid of check_region
  *  v0.14.9c
- *     August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de>
+ *     August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de>
  *     added support for Tvia (formerly Integraphics/IGST) CyberPro5050
  *     this chip is often found in settop boxes (combined video+audio)
  *  v0.14.9b
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
index 7ab3a732e184443ecc299147240f1470df2e9e84..5d3c0372df3289211223afe4968ff50eb4109cbb 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/poll.h>
 #include <linux/soundcard.h>
 #include <linux/ac97_codec.h>
-#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
index a9eec2a2357d5fae8638d2234444aca90ffe1bc2..3bfb2102fc5d24c7e851df978ebd2dd3f97f775d 100644 (file)
@@ -1083,7 +1083,7 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha
                unsigned short val;
                snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
                /* Do the read twice due to buffers on some ac97 codecs.
-                * e.g. The STAC9704 returns exactly what you wrote the the register
+                * e.g. The STAC9704 returns exactly what you wrote to the register
                 * if you read it immediately. This causes the detect routine to fail.
                 */
                val = snd_ac97_read(ac97, reg);
index e65d669af6391fb15ff4eff5e31a25d8e660687c..e47861ccd6e75fd94718d3454a15f152268592d6 100644 (file)
@@ -63,7 +63,7 @@ extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[];
                                        /* look to CS8414 datasheet */
 #define ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK 0x04
                                        /* S/PDIF output status clock */
-                                       /* (writting on rising edge - 0->1) */
+                                       /* (writing on rising edge - 0->1) */
                                        /* all except Delta44 */
                                        /* look to CS8404A datasheet */
 #define ICE1712_DELTA_SPDIF_OUT_STAT_DATA 0x08
@@ -100,7 +100,7 @@ extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[];
                                        /* AKM4524 serial data */
 #define ICE1712_DELTA_CODEC_SERIAL_CLOCK 0x20
                                        /* AKM4524 serial clock */
-                                       /* (writting on rising edge - 0->1 */
+                                       /* (writing on rising edge - 0->1 */
 #define ICE1712_DELTA_CODEC_CHIP_A     0x40
 #define ICE1712_DELTA_CODEC_CHIP_B     0x80
                                        /* 1 - select chip A or B */
index 21386da3bc869aab17d446f83310ffb0ee0a5a7a..ac007cec08791fbcd73f8a014257ea5e96377840 100644 (file)
@@ -472,7 +472,7 @@ static int snd_mixart_prepare(struct snd_pcm_substream *subs)
        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
        struct mixart_stream *stream = subs->runtime->private_data;
 
-       /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
+       /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
 
        snd_printdd("snd_mixart_prepare\n");
 
index 2bae9c1a2b54b9daa134a9765a99d8eec035bb87..5a2bef44a2f5c7ef52d2e5312b89e21c02670425 100644 (file)
@@ -843,7 +843,7 @@ static void __init detect_byte_swap(struct snd_pmac *chip)
        /* if seems that Keylargo can't byte-swap  */
        for (mio = chip->node->parent; mio; mio = mio->parent) {
                if (strcmp(mio->name, "mac-io") == 0) {
-                       if (device_is_compatible(mio, "Keylargo"))
+                       if (of_device_is_compatible(mio, "Keylargo"))
                                chip->can_byte_swap = 0;
                        break;
                }
@@ -910,7 +910,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
                chip->node = of_find_node_by_name(NULL, "i2s-a");
                if (chip->node && chip->node->parent &&
                    chip->node->parent->parent) {
-                       if (device_is_compatible(chip->node->parent->parent,
+                       if (of_device_is_compatible(chip->node->parent->parent,
                                                 "K2-Keylargo"))
                                chip->is_k2 = 1;
                }
@@ -941,22 +941,22 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
                return -ENODEV;
        }
        /* This should be verified on older screamers */
-       if (device_is_compatible(sound, "screamer")) {
+       if (of_device_is_compatible(sound, "screamer")) {
                chip->model = PMAC_SCREAMER;
                // chip->can_byte_swap = 0; /* FIXME: check this */
        }
-       if (device_is_compatible(sound, "burgundy")) {
+       if (of_device_is_compatible(sound, "burgundy")) {
                chip->model = PMAC_BURGUNDY;
                chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
        }
-       if (device_is_compatible(sound, "daca")) {
+       if (of_device_is_compatible(sound, "daca")) {
                chip->model = PMAC_DACA;
                chip->can_capture = 0;  /* no capture */
                chip->can_duplex = 0;
                // chip->can_byte_swap = 0; /* FIXME: check this */
                chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
        }
-       if (device_is_compatible(sound, "tumbler")) {
+       if (of_device_is_compatible(sound, "tumbler")) {
                chip->model = PMAC_TUMBLER;
                chip->can_capture = 0;  /* no capture */
                chip->can_duplex = 0;
@@ -965,7 +965,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
                chip->freq_table = tumbler_freqs;
                chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
        }
-       if (device_is_compatible(sound, "snapper")) {
+       if (of_device_is_compatible(sound, "snapper")) {
                chip->model = PMAC_SNAPPER;
                // chip->can_byte_swap = 0; /* FIXME: check this */
                chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
index 54e333fbb1d06e0710cb7a1ece09eccd2bb416d5..5821cdd0bec9c224ac50d63d544e59ec73dfe816 100644 (file)
@@ -1060,7 +1060,7 @@ static struct device_node *find_compatible_audio_device(const char *name)
   
        for (np = of_get_next_child(gpiop, NULL); np;
                        np = of_get_next_child(gpiop, np)) {
-               if (device_is_compatible(np, name))
+               if (of_device_is_compatible(np, name))
                        break;
        }  
        of_node_put(gpiop);
index 4c4b882316ac4940259a798e06c8675f87793659..b8ccfee095c4711ce17b0fc80176d5b9d409da28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/sound/arm/pxa2xx-ac97.h
+ * linux/sound/soc/pxa/pxa2xx-ac97.h
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
index a2484f0881f146bac98c6e0e42c83914f0c67e6f..4435bd9f884faec12ab5532c43f5ba687f638367 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/sound/arm/pxa2xx-i2s.h
+ * linux/sound/soc/pxa/pxa2xx-i2s.h
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
index 25a2a733300677162e28186b5e2b274751c9a10f..e07085a7cfc340baafc170f3cd876c2f2980c694 100644 (file)
@@ -673,7 +673,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
 }
 
 /*
- * Send prepared cmd string. It works by writting a JUMP cmd into
+ * Send prepared cmd string. It works by writing a JUMP cmd into
  * the last WAIT cmd and force DBRI to reread the cmd.
  * The JUMP cmd points to the new cmd string.
  * It also releases the cmdlock spinlock.